diff options
author | Adrian Ambrożewicz <adrian.ambrozewicz@intel.com> | 2019-07-29 11:19:00 +0300 |
---|---|---|
committer | Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> | 2021-11-05 10:22:08 +0300 |
commit | f94395088a335407bbaa24bfb1bd26cc8b838d8e (patch) | |
tree | 5ff78c15b197736fff595b68ed0b62e64d60da46 /drivers | |
parent | f2d3c244755c4cefc8ceebc0cfc5aca4d6c7597e (diff) | |
download | linux-f94395088a335407bbaa24bfb1bd26cc8b838d8e.tar.xz |
Add IO statistics to USB Mass storage gadget
Introduces new attribute to Mass Storage Gadget ConfigFS : stats.
It's read-only attribute which contains statistics of read/write operations
based on LUN transaction counters (IO number and bytes transferred).
Goal is to provide a way to observe whether simulated device is actually
used by host. Statistics on hosted file / nbd level are not always viable
due to page cache having severe impact on actual IO statistics.
This attribute should provide information about host IO on USB Gadget as
close to endpoint as possible.
Attribute is tied completely to configFS implementation and it's lifecycle
is managed by Kernel and user. Driver implements a handler which populates
output buffer on read.
Tests performed:
- mounted USB Mass Storage gadget, new attribute showed up in gadget tree
- attribute was monitored for changes during IO performed on host machine
- removed device, attribute (along with other device attributes) was gone
Signed-off-by: Adrian Ambrożewicz <adrian.ambrozewicz@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/function/f_mass_storage.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/function/storage_common.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/function/storage_common.h | 29 |
3 files changed, 50 insertions, 0 deletions
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 6ad669dde41c..415994077d15 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -679,6 +679,8 @@ static int do_read(struct fsg_common *common) amount_left -= nread; common->residue -= nread; + fsg_stats_rd_attempt(&curlun->stats, nread); + /* * Except at the end of the transfer, nread will be * equal to the buffer size, which is divisible by the @@ -876,6 +878,8 @@ static int do_write(struct fsg_common *common) amount_left_to_write -= nwritten; common->residue -= nwritten; + fsg_stats_wr_attempt(&curlun->stats, nwritten); + /* If an error occurred, report it and its position */ if (nwritten < amount) { curlun->sense_data = SS_WRITE_ERROR; @@ -3090,6 +3094,13 @@ static ssize_t fsg_lun_opts_inquiry_string_store(struct config_item *item, CONFIGFS_ATTR(fsg_lun_opts_, inquiry_string); +static ssize_t fsg_lun_opts_stats_show(struct config_item *item, char *page) +{ + return fsg_show_stats(to_fsg_lun_opts(item)->lun, page); +} + +CONFIGFS_ATTR_RO(fsg_lun_opts_, stats); + static struct configfs_attribute *fsg_lun_attrs[] = { &fsg_lun_opts_attr_file, &fsg_lun_opts_attr_ro, @@ -3097,6 +3108,7 @@ static struct configfs_attribute *fsg_lun_attrs[] = { &fsg_lun_opts_attr_cdrom, &fsg_lun_opts_attr_nofua, &fsg_lun_opts_attr_inquiry_string, + &fsg_lun_opts_attr_stats, NULL, }; diff --git a/drivers/usb/gadget/function/storage_common.c b/drivers/usb/gadget/function/storage_common.c index b859a158a414..197630f38fcb 100644 --- a/drivers/usb/gadget/function/storage_common.c +++ b/drivers/usb/gadget/function/storage_common.c @@ -371,6 +371,15 @@ ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf) } EXPORT_SYMBOL_GPL(fsg_show_inquiry_string); +ssize_t fsg_show_stats(struct fsg_lun *curlun, char *buf) +{ + return sprintf(buf, "read cnt: %u\n" "read sum: %llu\n" + "write cnt: %u\n" "write sum: %llu\n", + curlun->stats.read.count, curlun->stats.read.bytes, + curlun->stats.write.count, curlun->stats.write.bytes); +} +EXPORT_SYMBOL_GPL(fsg_show_stats); + /* * The caller must hold fsg->filesem for reading when calling this function. */ diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h index bdeb1e233fc9..528441480165 100644 --- a/drivers/usb/gadget/function/storage_common.h +++ b/drivers/usb/gadget/function/storage_common.h @@ -95,6 +95,32 @@ do { \ */ #define INQUIRY_STRING_LEN ((size_t) (8 + 16 + 4 + 1)) +struct fsg_stats_cnt { + u64 bytes; + u32 count; +}; + +struct fsg_stats { + struct fsg_stats_cnt read; + struct fsg_stats_cnt write; +}; + +static inline void fsg_stats_update(struct fsg_stats_cnt *cnt, u64 diff) +{ + cnt->count++; + cnt->bytes += diff; +} + +static inline void fsg_stats_wr_attempt(struct fsg_stats *stats, u64 b_written) +{ + fsg_stats_update(&stats->write, b_written); +} + +static inline void fsg_stats_rd_attempt(struct fsg_stats *stats, u64 b_read) +{ + fsg_stats_update(&stats->read, b_read); +} + struct fsg_lun { struct file *filp; loff_t file_length; @@ -120,6 +146,8 @@ struct fsg_lun { const char *name; /* "lun.name" */ const char **name_pfx; /* "function.name" */ char inquiry_string[INQUIRY_STRING_LEN]; + + struct fsg_stats stats; }; static inline bool fsg_lun_is_open(struct fsg_lun *curlun) @@ -208,6 +236,7 @@ ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf); ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf); ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf); +ssize_t fsg_show_stats(struct fsg_lun *curlun, char *buf); ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, const char *buf, size_t count); ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count); |