Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e95146f5 authored by Azhar Shaikh's avatar Azhar Shaikh
Browse files

USB: f_mass_storage: Add support for performance recording



This patch adds support for populating the read/write performance values
for debugging the Mass storage performance numbers at VFS level.
To check the read/write values, user needs to invoke below command
cat /sys/class/android_usb/f_mass_storage/lun/perf
To reset the read/write values to zero
echo 0 > /sys/class/android_usb/f_mass_storage/lun/perf

Change-Id: Ied51969ce144a2335d2140259e28e8acbda44635
Signed-off-by: default avatarChiranjeevi Velempati <cvelempa@codeaurora.org>
Signed-off-by: default avatarRajkumar Raghupathy <raghup@codeaurora.org>
Signed-off-by: default avatarAzhar Shaikh <azhars@codeaurora.org>
parent a5f9d251
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -635,7 +635,7 @@ static int do_read(struct fsg_common *common)
	loff_t			file_offset, file_offset_tmp;
	unsigned int		amount;
	ssize_t			nread;

	ktime_t			start, diff;
	/*
	 * Get the starting Logical Block Address and check that it's
	 * not too big.
@@ -702,11 +702,15 @@ static int do_read(struct fsg_common *common)

		/* Perform the read */
		file_offset_tmp = file_offset;
		start = ktime_get();
		nread = vfs_read(curlun->filp,
				 (char __user *)bh->buf,
				 amount, &file_offset_tmp);
		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
		      (unsigned long long)file_offset, (int)nread);
		diff = ktime_sub(ktime_get(), start);
		curlun->perf.rbytes += nread;
		curlun->perf.rtime = ktime_add(curlun->perf.rtime, diff);
		if (signal_pending(current))
			return -EINTR;

@@ -767,6 +771,7 @@ static int do_write(struct fsg_common *common)
	unsigned int		amount;
	ssize_t			nwritten;
	int			rc;
	ktime_t			start, diff;

	if (curlun->ro) {
		curlun->sense_data = SS_WRITE_PROTECTED;
@@ -895,11 +900,16 @@ static int do_write(struct fsg_common *common)

			/* Perform the write */
			file_offset_tmp = file_offset;
			start = ktime_get();
			nwritten = vfs_write(curlun->filp,
					     (char __user *)bh->buf,
					     amount, &file_offset_tmp);
			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
			      (unsigned long long)file_offset, (int)nwritten);
			diff = ktime_sub(ktime_get(), start);
			curlun->perf.wbytes += nwritten;
			curlun->perf.wtime =
					ktime_add(curlun->perf.wtime, diff);
			if (signal_pending(current))
				return -EINTR;		/* Interrupted! */

@@ -2641,6 +2651,7 @@ static ssize_t file_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RW(ro);
static DEVICE_ATTR_RW(nofua);
static DEVICE_ATTR_RW(file);
static DEVICE_ATTR(perf, 0644, fsg_show_perf, fsg_store_perf);

static struct device_attribute dev_attr_ro_cdrom = __ATTR_RO(ro);
static struct device_attribute dev_attr_file_nonremovable = __ATTR_RO(file);
@@ -2785,6 +2796,7 @@ static inline void fsg_common_remove_sysfs(struct fsg_lun *lun)
	 */
	device_remove_file(&lun->dev, &dev_attr_ro);
	device_remove_file(&lun->dev, &dev_attr_file);
	device_remove_file(&lun->dev, &dev_attr_perf);
}

void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
@@ -2918,6 +2930,10 @@ static inline int fsg_common_add_sysfs(struct fsg_common *common,
	if (rc)
		goto error;

	rc = device_create_file(&lun->dev, &dev_attr_perf);
	if (rc)
		pr_err("failed to create sysfs entry: %d\n", rc);

	return 0;

error:
+30 −0
Original line number Diff line number Diff line
@@ -333,6 +333,36 @@ ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf)
}
EXPORT_SYMBOL_GPL(fsg_show_nofua);

ssize_t fsg_show_perf(struct device *dev, struct device_attribute *attr,
				char *buf)
{
	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
	unsigned long rbytes, wbytes;
	int64_t rtime, wtime;

	rbytes = curlun->perf.rbytes;
	wbytes = curlun->perf.wbytes;
	rtime = ktime_to_us(curlun->perf.rtime);
	wtime = ktime_to_us(curlun->perf.wtime);

	return snprintf(buf, PAGE_SIZE,
			"Write performance :%lu bytes in %lld microseconds\n"
			"Read performance : %lu bytes in %lld microseconds\n",
			wbytes, wtime, rbytes, rtime);
}

ssize_t fsg_store_perf(struct device *dev, struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
	int value;

	if (!kstrtoint(buf, 10, &value) && !value)
		memset(&curlun->perf, 0, sizeof(curlun->perf));

	return count;
}

ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
		      char *buf)
{
+11 −0
Original line number Diff line number Diff line
@@ -110,6 +110,13 @@ struct fsg_lun {
						       of bound block device */
	unsigned int	blksize; /* logical block size of bound block device */
	struct device	dev;
	struct {
		unsigned long rbytes;
		unsigned long wbytes;
		ktime_t rtime;
		ktime_t wtime;
	} perf;

	const char	*name;		/* "lun.name" */
	const char	**name_pfx;	/* "function.name" */
};
@@ -227,5 +234,9 @@ ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
			const char *buf, size_t count);
ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
			    size_t count);
ssize_t fsg_show_perf(struct device *dev, struct device_attribute *attr,
				char *buf);
ssize_t fsg_store_perf(struct device *dev, struct device_attribute *attr,
				const char *buf, size_t count);

#endif /* USB_STORAGE_COMMON_H */