]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: scsi_debug: Maintain write statistics per group number
authorBart Van Assche <bvanassche@acm.org>
Tue, 30 Jan 2024 21:48:45 +0000 (13:48 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 27 Feb 2024 02:37:27 +0000 (21:37 -0500)
Track per GROUP NUMBER how many write commands have been processed. Make
this information available in sysfs. Reset these statistics if any data
is written into the sysfs attribute.

Note: SCSI devices should only interpret the information in the GROUP
NUMBER field as a stream identifier if the ST_ENBLE bit has been set to
one. This patch follows a simpler approach: count the number of writes
per GROUP NUMBER whether or not the group number represents a stream
identifier.

Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Douglas Gilbert <dgilbert@interlog.com>
Tested-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20240130214911.1863909-20-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_debug.c

index 497045e54300e56e3b8d8e07c00d88cb9938d4d6..ce52d580d1aa7f9f5ad127ce6ecc35b91257a11c 100644 (file)
@@ -902,6 +902,8 @@ static int sdeb_zbc_nr_conv = DEF_ZBC_NR_CONV_ZONES;
 static int submit_queues = DEF_SUBMIT_QUEUES;  /* > 1 for multi-queue (mq) */
 static int poll_queues; /* iouring iopoll interface.*/
 
+static atomic_long_t writes_by_group_number[64];
+
 static char sdebug_proc_name[] = MY_NAME;
 static const char *my_name = MY_NAME;
 
@@ -3377,7 +3379,8 @@ static inline struct sdeb_store_info *devip2sip(struct sdebug_dev_info *devip,
 
 /* Returns number of bytes copied or -1 if error. */
 static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp,
-                           u32 sg_skip, u64 lba, u32 num, bool do_write)
+                           u32 sg_skip, u64 lba, u32 num, bool do_write,
+                           u8 group_number)
 {
        int ret;
        u64 block, rest = 0;
@@ -3396,6 +3399,10 @@ static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp,
                return 0;
        if (scp->sc_data_direction != dir)
                return -1;
+
+       if (do_write && group_number < ARRAY_SIZE(writes_by_group_number))
+               atomic_long_inc(&writes_by_group_number[group_number]);
+
        fsp = sip->storep;
 
        block = do_div(lba, sdebug_store_sectors);
@@ -3769,7 +3776,7 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
                }
        }
 
-       ret = do_device_access(sip, scp, 0, lba, num, false);
+       ret = do_device_access(sip, scp, 0, lba, num, false, 0);
        sdeb_read_unlock(sip);
        if (unlikely(ret == -1))
                return DID_ERROR << 16;
@@ -3954,6 +3961,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
        bool check_prot;
        u32 num;
+       u8 group = 0;
        u32 ei_lba;
        int ret;
        u64 lba;
@@ -3965,11 +3973,13 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
                ei_lba = 0;
                lba = get_unaligned_be64(cmd + 2);
                num = get_unaligned_be32(cmd + 10);
+               group = cmd[14] & 0x3f;
                check_prot = true;
                break;
        case WRITE_10:
                ei_lba = 0;
                lba = get_unaligned_be32(cmd + 2);
+               group = cmd[6] & 0x3f;
                num = get_unaligned_be16(cmd + 7);
                check_prot = true;
                break;
@@ -3984,15 +3994,18 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
                ei_lba = 0;
                lba = get_unaligned_be32(cmd + 2);
                num = get_unaligned_be32(cmd + 6);
+               group = cmd[6] & 0x3f;
                check_prot = true;
                break;
        case 0x53:      /* XDWRITEREAD(10) */
                ei_lba = 0;
                lba = get_unaligned_be32(cmd + 2);
+               group = cmd[6] & 0x1f;
                num = get_unaligned_be16(cmd + 7);
                check_prot = false;
                break;
        default:        /* assume WRITE(32) */
+               group = cmd[6] & 0x3f;
                lba = get_unaligned_be64(cmd + 12);
                ei_lba = get_unaligned_be32(cmd + 20);
                num = get_unaligned_be32(cmd + 28);
@@ -4047,7 +4060,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
                }
        }
 
-       ret = do_device_access(sip, scp, 0, lba, num, true);
+       ret = do_device_access(sip, scp, 0, lba, num, true, group);
        if (unlikely(scsi_debug_lbp()))
                map_region(sip, lba, num);
        /* If ZBC zone then bump its write pointer */
@@ -4099,12 +4112,14 @@ static int resp_write_scat(struct scsi_cmnd *scp,
        u32 lb_size = sdebug_sector_size;
        u32 ei_lba;
        u64 lba;
+       u8 group;
        int ret, res;
        bool is_16;
        static const u32 lrd_size = 32; /* + parameter list header size */
 
        if (cmd[0] == VARIABLE_LENGTH_CMD) {
                is_16 = false;
+               group = cmd[6] & 0x3f;
                wrprotect = (cmd[10] >> 5) & 0x7;
                lbdof = get_unaligned_be16(cmd + 12);
                num_lrd = get_unaligned_be16(cmd + 16);
@@ -4115,6 +4130,7 @@ static int resp_write_scat(struct scsi_cmnd *scp,
                lbdof = get_unaligned_be16(cmd + 4);
                num_lrd = get_unaligned_be16(cmd + 8);
                bt_len = get_unaligned_be32(cmd + 10);
+               group = cmd[14] & 0x3f;
                if (unlikely(have_dif_prot)) {
                        if (sdebug_dif == T10_PI_TYPE2_PROTECTION &&
                            wrprotect) {
@@ -4203,7 +4219,7 @@ static int resp_write_scat(struct scsi_cmnd *scp,
                        }
                }
 
-               ret = do_device_access(sip, scp, sg_off, lba, num, true);
+               ret = do_device_access(sip, scp, sg_off, lba, num, true, group);
                /* If ZBC zone then bump its write pointer */
                if (sdebug_dev_is_zoned(devip))
                        zbc_inc_wp(devip, lba, num);
@@ -7298,6 +7314,30 @@ static ssize_t tur_ms_to_ready_show(struct device_driver *ddp, char *buf)
 }
 static DRIVER_ATTR_RO(tur_ms_to_ready);
 
+static ssize_t group_number_stats_show(struct device_driver *ddp, char *buf)
+{
+       char *p = buf, *end = buf + PAGE_SIZE;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(writes_by_group_number); i++)
+               p += scnprintf(p, end - p, "%d %ld\n", i,
+                              atomic_long_read(&writes_by_group_number[i]));
+
+       return p - buf;
+}
+
+static ssize_t group_number_stats_store(struct device_driver *ddp,
+                                       const char *buf, size_t count)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(writes_by_group_number); i++)
+               atomic_long_set(&writes_by_group_number[i], 0);
+
+       return count;
+}
+static DRIVER_ATTR_RW(group_number_stats);
+
 /* Note: The following array creates attribute files in the
    /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
    files (over those found in the /sys/module/scsi_debug/parameters
@@ -7344,6 +7384,7 @@ static struct attribute *sdebug_drv_attrs[] = {
        &driver_attr_cdb_len.attr,
        &driver_attr_tur_ms_to_ready.attr,
        &driver_attr_zbc.attr,
+       &driver_attr_group_number_stats.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(sdebug_drv);