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@xxxxxxxxxxxx> --- drivers/scsi/scsi_debug.c | 87 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 6 deletions(-) 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)) { -- 2.25.1