diff mbox series

[v4,09/14] scsi_debug: add zbc parameter

Message ID 20200225062351.21267-10-dgilbert@interlog.com (mailing list archive)
State New, archived
Headers show
Series scsi_debug: host managed ZBC + doublestore | expand

Commit Message

Douglas Gilbert Feb. 25, 2020, 6:23 a.m. UTC
Add the zbc module parameter to:
    0: none (probably a convential disk)
    1: host_aware
    2: host_managed

These values are chosen to match 'enum blk_zoned_model' found in
include/linux/blkdev.h . One of the strings 'none', 'aware' or
'managed' can be given instead of a number. Those strings may
be prefixed by 'host_' or 'host-'.

At this time there is no ZBC "host-aware" implementation so that
string (or the value '1') has no effect.

Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
---
 drivers/scsi/scsi_debug.c | 87 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 81 insertions(+), 6 deletions(-)

Comments

Martin K. Petersen April 15, 2020, 2:10 a.m. UTC | #1
Doug,

Forgot to comment on this:

> +MODULE_PARM_DESC(zbc, "'none' [0]; 'aware' [1]; 'managed' [2] (def=0). Can have 'host_' prefix");

[...]

> +static int sdeb_zbc_model_str(const char *cp)
> +{
> +	int res = -EINVAL;
> +
> +	if (isalpha(cp[0])) {
> +		if (strstr(cp, "none"))
> +			res = BLK_ZONED_NONE;
> +		else if (strstr(cp, "aware"))
> +			res = BLK_ZONED_HA;
> +		else if (strstr(cp, "managed"))
> +			res = BLK_ZONED_HM;
> +	} else {
> +		int n, ret;
> +
> +		ret = kstrtoint(cp, 0, &n);
> +		if (ret)
> +			return ret;
> +		if (n >= 0 || n <= 2)
> +			res = n;
> +	}
> +	return res;
> +}
> +
> +static ssize_t zbc_show(struct device_driver *ddp, char *buf)
> +{
> +	switch (sdeb_zbc_model) {
> +	case BLK_ZONED_NONE:	/* 0 */
> +		return scnprintf(buf, PAGE_SIZE, "none\n");
> +	case BLK_ZONED_HA:	/* 1, not yet supported */
> +		return scnprintf(buf, PAGE_SIZE, "host_aware\n");
> +	case BLK_ZONED_HM:	/* 2 */
> +		return scnprintf(buf, PAGE_SIZE, "host_managed\n");
> +	default:
> +		return scnprintf(buf, PAGE_SIZE, "unknown_zbc_model [0x%x]\n",
> +				 (unsigned int)sdeb_zbc_model);
> +	}
> +}

static const char *zbc_model[] = {
	[BLK_ZONED_NONE] = "none",
	[BLK_ZONED_HA]   = "host_aware",
	[BLK_ZONED_HM]   = "host_managed",
};

[...]

And then in parameter parsing you can do:

	sdeb_zbc_model = sysfs_match_string(zbc_model, buf);
	if (sdeb_zbc_model < 0)
		return -EINVAL;

zbc_show() can go away and you can do:

	pr_info(".... %s\n", zbc_model[sdeb_zbc_model]);
diff mbox series

Patch

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 0e2e0d35af7e..ddd8dc784f7e 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -39,6 +39,7 @@ 
 #include <linux/uuid.h>
 #include <linux/t10-pi.h>
 #include <linux/random.h>
+#include <linux/ctype.h>
 
 #include <net/checksum.h>
 
@@ -110,7 +111,9 @@  static const char *sdebug_version_date = "20190125";
 #define DEF_ATO 1
 #define DEF_CDB_LEN 10
 #define DEF_JDELAY   1		/* if > 0 unit is a jiffy */
+#define DEF_DEV_SIZE_PRE_INIT   0
 #define DEF_DEV_SIZE_MB   8
+#define DEF_ZBC_DEV_SIZE_MB   128
 #define DEF_DIF 0
 #define DEF_DIX 0
 #define DEF_DOUBLESTORE false
@@ -713,7 +716,7 @@  static int sdebug_add_host = DEF_NUM_HOST;
 static int sdebug_ato = DEF_ATO;
 static int sdebug_cdb_len = DEF_CDB_LEN;
 static int sdebug_jdelay = DEF_JDELAY;	/* if > 0 then unit is jiffies */
-static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB;
+static int sdebug_dev_size_mb = DEF_DEV_SIZE_PRE_INIT;
 static int sdebug_dif = DEF_DIF;
 static int sdebug_dix = DEF_DIX;
 static int sdebug_dsense = DEF_D_SENSE;
@@ -741,6 +744,8 @@  static int sdebug_scsi_level = DEF_SCSI_LEVEL;
 static int sdebug_sector_size = DEF_SECTOR_SIZE;
 static int sdebug_virtual_gb = DEF_VIRTUAL_GB;
 static int sdebug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
+/* Following enum: 0: no zbc, def; 1: host aware; 2: host managed */
+static enum blk_zoned_model sdeb_zbc_model;
 static unsigned int sdebug_lbpu = DEF_LBPU;
 static unsigned int sdebug_lbpws = DEF_LBPWS;
 static unsigned int sdebug_lbpws10 = DEF_LBPWS10;
@@ -763,6 +768,7 @@  static bool have_dif_prot;
 static bool write_since_sync;
 static bool sdebug_statistics = DEF_STATISTICS;
 static bool sdebug_wp;
+static char *sdeb_zbc_model_s;
 
 static unsigned int sdebug_store_sectors;
 static sector_t sdebug_capacity;	/* in sectors */
@@ -5443,6 +5449,7 @@  module_param_named(vpd_use_hostno, sdebug_vpd_use_hostno, int,
 module_param_named(wp, sdebug_wp, bool, S_IRUGO | S_IWUSR);
 module_param_named(write_same_length, sdebug_write_same_length, int,
 		   S_IRUGO | S_IWUSR);
+module_param_named(zbc, sdeb_zbc_model_s, charp, S_IRUGO);
 
 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
 MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -5504,6 +5511,7 @@  MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size
 MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
 MODULE_PARM_DESC(wp, "Write Protect (def=0)");
 MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
+MODULE_PARM_DESC(zbc, "'none' [0]; 'aware' [1]; 'managed' [2] (def=0). Can have 'host_' prefix");
 
 #define SDEBUG_INFO_LEN 256
 static char sdebug_info[SDEBUG_INFO_LEN];
@@ -5711,8 +5719,16 @@  static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
 	int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+		int prev_pdt = sdebug_ptype;
+
 		sdebug_ptype = n;
-		sdeb_zbc_in_use = (sdebug_ptype == TYPE_ZBC);
+		if (sdebug_ptype == TYPE_ZBC) {
+			sdeb_zbc_in_use = true;
+			sdeb_zbc_model = BLK_ZONED_HM;
+		} else if (prev_pdt == TYPE_ZBC) {
+			sdeb_zbc_in_use = false;
+			sdeb_zbc_model = BLK_ZONED_NONE;
+		}
 		return count;
 	}
 	return -EINVAL;
@@ -6224,6 +6240,44 @@  static ssize_t cdb_len_store(struct device_driver *ddp, const char *buf,
 }
 static DRIVER_ATTR_RW(cdb_len);
 
+static int sdeb_zbc_model_str(const char *cp)
+{
+	int res = -EINVAL;
+
+	if (isalpha(cp[0])) {
+		if (strstr(cp, "none"))
+			res = BLK_ZONED_NONE;
+		else if (strstr(cp, "aware"))
+			res = BLK_ZONED_HA;
+		else if (strstr(cp, "managed"))
+			res = BLK_ZONED_HM;
+	} else {
+		int n, ret;
+
+		ret = kstrtoint(cp, 0, &n);
+		if (ret)
+			return ret;
+		if (n >= 0 || n <= 2)
+			res = n;
+	}
+	return res;
+}
+
+static ssize_t zbc_show(struct device_driver *ddp, char *buf)
+{
+	switch (sdeb_zbc_model) {
+	case BLK_ZONED_NONE:	/* 0 */
+		return scnprintf(buf, PAGE_SIZE, "none\n");
+	case BLK_ZONED_HA:	/* 1, not yet supported */
+		return scnprintf(buf, PAGE_SIZE, "host_aware\n");
+	case BLK_ZONED_HM:	/* 2 */
+		return scnprintf(buf, PAGE_SIZE, "host_managed\n");
+	default:
+		return scnprintf(buf, PAGE_SIZE, "unknown_zbc_model [0x%x]\n",
+				 (unsigned int)sdeb_zbc_model);
+	}
+}
+static DRIVER_ATTR_RO(zbc);
 
 /* Note: The following array creates attribute files in the
    /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
@@ -6266,6 +6320,7 @@  static struct attribute *sdebug_drv_attrs[] = {
 	&driver_attr_strict.attr,
 	&driver_attr_uuid_ctl.attr,
 	&driver_attr_cdb_len.attr,
+	&driver_attr_zbc.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(sdebug_drv);
@@ -6355,7 +6410,30 @@  static int __init scsi_debug_init(void)
 	for (k = 0; k < submit_queues; ++k)
 		spin_lock_init(&sdebug_q_arr[k].qc_lock);
 
-	if (sdebug_dev_size_mb < 1)
+	/* check for host managed zoned block device [ptype=0x14] */
+	if (sdebug_ptype == TYPE_ZBC) {
+		sdeb_zbc_in_use = true;
+		sdeb_zbc_model = BLK_ZONED_HM;
+		if (sdebug_dev_size_mb == DEF_DEV_SIZE_PRE_INIT)
+			sdebug_dev_size_mb = DEF_ZBC_DEV_SIZE_MB;
+	}
+	if (sdeb_zbc_model_s && *sdeb_zbc_model_s) { /* e.g. 'zbc=managed' */
+		k = sdeb_zbc_model_str(sdeb_zbc_model_s);
+		if (k < 0) {
+			ret = k;
+			goto free_vm;
+		}
+		sdeb_zbc_model = k;
+		if (sdeb_zbc_model == BLK_ZONED_HM) {
+			sdeb_zbc_in_use = true;
+			sdebug_ptype = TYPE_ZBC;
+			if (sdebug_dev_size_mb == DEF_DEV_SIZE_PRE_INIT)
+				sdebug_dev_size_mb = DEF_ZBC_DEV_SIZE_MB;
+		}
+	}
+	if (sdebug_dev_size_mb == DEF_DEV_SIZE_PRE_INIT)
+		sdebug_dev_size_mb = DEF_DEV_SIZE_MB;
+	if (sdebug_dev_size_mb < 1)	/* could be negative */
 		sdebug_dev_size_mb = 1;  /* force minimum 1 MB ramdisk */
 	sz = (unsigned long)sdebug_dev_size_mb * 1048576;
 	sdebug_store_sectors = sz / sdebug_sector_size;
@@ -6454,9 +6532,6 @@  static int __init scsi_debug_init(void)
 		if (sdebug_num_parts)
 			map_region(0, 2);
 	}
-	/* check for host managed zoned block device [ptype=0x14] */
-	if (sdebug_ptype == TYPE_ZBC)
-		sdeb_zbc_in_use = true;
 
 	pseudo_primary = root_device_register("pseudo_0");
 	if (IS_ERR(pseudo_primary)) {