All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] scsi_debug: multiple queue support and cleanup
@ 2016-04-25 16:16 Douglas Gilbert
  2016-04-25 16:16 ` [PATCH 01/12] scsi_debug: cleanup naming and bit crunching Douglas Gilbert
                   ` (12 more replies)
  0 siblings, 13 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Primary reason for this patch series is to add multi queue support
modelled on the null_blk driver. Ignore host_lock option but
keep parameter for backward compatibility. Use high resolution
timers to implement both the jiffy and nanosecond delay
parameters. Replace the tasklets with work items. Incorporate
REPORT LUNS patch from Tomas Winkler sent in Febrary 2015. Add
parameter that permits LU names to use UUIDs (spc5r08.pdf).

Douglas Gilbert (12):
  scsi_debug: cleanup naming and bit crunching
  scsi_debug: ignore host lock option
  scsi_debug: replace jiffy timers with hr timers
  scsi_debug: make jiffy delay name clearer
  scsi_debug: replace tasklet with work queue
  scsi_debug: re-order file scope declarations
  scsi_debug: use likely hints on fast path
  scsi_debug: rework resp_report_luns
  scsi_debug: add multiple queue support
  scsi_debug: vpd and mode page work
  scsi_debug: uuid for lu name
  scsi_debug: use locally assigned naa

 drivers/scsi/scsi_debug.c | 2744 +++++++++++++++++++++++----------------------
 1 file changed, 1405 insertions(+), 1339 deletions(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH 01/12] scsi_debug: cleanup naming and bit crunching
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:14   ` Hannes Reinecke
  2016-04-26 18:13   ` Bart Van Assche
  2016-04-25 16:16 ` [PATCH 02/12] scsi_debug: ignore host lock option Douglas Gilbert
                   ` (11 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Shorten file scope static and constant names. Use more
get/put_unaligned calls to hide bit banging. Introduce
sdebug_verbose boolean to replace frequent masking of
option bit flags. Add GPL and bump version.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index f3d69a98..bc586a4 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -6,23 +6,15 @@
  *  anything out of the ordinary is seen.
  * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  *
- *  This version is more generic, simulating a variable number of disk
- *  (or disk like devices) sharing a common amount of RAM. To be more
- *  realistic, the simulated devices have the transport attributes of
- *  SAS disks.
+ * Copyright (C) 2001 - 2016 Douglas Gilbert
  *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
  *
  *  For documentation see http://sg.danny.cz/sg/sdebug26.html
  *
- *   D. Gilbert (dpg) work for Magneto-Optical device test [20010421]
- *   dpg: work for devfs large number of disks [20010809]
- *        forked for lk 2.5 series [20011216, 20020101]
- *        use vmalloc() more inquiry+mode_sense [20020302]
- *        add timers for delayed responses [20020721]
- *   Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031]
- *   Mike Anderson <andmike@us.ibm.com> sysfs work [20021118]
- *   dpg: change style of boot options to "scsi_debug.num_tgts=2" and
- *        module options to "modprobe scsi_debug num_tgts=2" [20021221]
  */
 
 
@@ -66,8 +58,9 @@
 #include "sd.h"
 #include "scsi_logging.h"
 
-#define SCSI_DEBUG_VERSION "1.85"
-static const char *scsi_debug_version_date = "20141022";
+/* make sure inq_product_rev string corresponds to this version */
+#define SCSI_DEBUG_VERSION "1.86"
+static const char *sdebug_version_date = "20160422";
 
 #define MY_NAME "scsi_debug"
 
@@ -145,38 +138,44 @@ static const char *scsi_debug_version_date = "20141022";
 #define DEF_STRICT 0
 #define DELAY_OVERRIDDEN -9999
 
-/* bit mask values for scsi_debug_opts */
-#define SCSI_DEBUG_OPT_NOISE   1
-#define SCSI_DEBUG_OPT_MEDIUM_ERR   2
-#define SCSI_DEBUG_OPT_TIMEOUT   4
-#define SCSI_DEBUG_OPT_RECOVERED_ERR   8
-#define SCSI_DEBUG_OPT_TRANSPORT_ERR   16
-#define SCSI_DEBUG_OPT_DIF_ERR   32
-#define SCSI_DEBUG_OPT_DIX_ERR   64
-#define SCSI_DEBUG_OPT_MAC_TIMEOUT  128
-#define SCSI_DEBUG_OPT_SHORT_TRANSFER	0x100
-#define SCSI_DEBUG_OPT_Q_NOISE	0x200
-#define SCSI_DEBUG_OPT_ALL_TSF	0x400
-#define SCSI_DEBUG_OPT_RARE_TSF	0x800
-#define SCSI_DEBUG_OPT_N_WCE	0x1000
-#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000
-#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000
-#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000)
+/* bit mask values for sdebug_opts */
+#define SDEBUG_OPT_NOISE		1
+#define SDEBUG_OPT_MEDIUM_ERR		2
+#define SDEBUG_OPT_TIMEOUT		4
+#define SDEBUG_OPT_RECOVERED_ERR	8
+#define SDEBUG_OPT_TRANSPORT_ERR	16
+#define SDEBUG_OPT_DIF_ERR		32
+#define SDEBUG_OPT_DIX_ERR		64
+#define SDEBUG_OPT_MAC_TIMEOUT		128
+#define SDEBUG_OPT_SHORT_TRANSFER	0x100
+#define SDEBUG_OPT_Q_NOISE		0x200
+#define SDEBUG_OPT_ALL_TSF		0x400
+#define SDEBUG_OPT_RARE_TSF		0x800
+#define SDEBUG_OPT_N_WCE		0x1000
+#define SDEBUG_OPT_RESET_NOISE		0x2000
+#define SDEBUG_OPT_NO_CDB_NOISE		0x4000
+#define SDEBUG_OPT_ALL_NOISE (SDEBUG_OPT_NOISE | SDEBUG_OPT_Q_NOISE | \
+			      SDEBUG_OPT_RESET_NOISE)
+#define SDEBUG_OPT_ALL_INJECTING (SDEBUG_OPT_RECOVERED_ERR | \
+				  SDEBUG_OPT_TRANSPORT_ERR | \
+				  SDEBUG_OPT_DIF_ERR | SDEBUG_OPT_DIX_ERR | \
+				  SDEBUG_OPT_SHORT_TRANSFER)
 /* When "every_nth" > 0 then modulo "every_nth" commands:
- *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
+ *   - a no response is simulated if SDEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
- *     commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ *     commands if SDEBUG_OPT_RECOVERED_ERR is set.
  *   - a TRANSPORT_ERROR is simulated on successful read and write
- *     commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
+ *     commands if SDEBUG_OPT_TRANSPORT_ERR is set.
  *
  * When "every_nth" < 0 then after "- every_nth" commands:
- *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
+ *   - a no response is simulated if SDEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
- *     commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ *     commands if SDEBUG_OPT_RECOVERED_ERR is set.
  *   - a TRANSPORT_ERROR is simulated on successful read and write
- *     commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
- * This will continue until some other action occurs (e.g. the user
- * writing a new value (other than -1 or 1) to every_nth via sysfs).
+ *     commands if _DEBUG_OPT_TRANSPORT_ERR is set.
+ * This will continue on every subsequent command until some other action
+ * occurs (e.g. the user * writing a new value (other than -1 or 1) to
+ * every_nth via sysfs).
  */
 
 /* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in
@@ -196,7 +195,7 @@ static const char *scsi_debug_version_date = "20141022";
 #define UAS_ONLY 1	/* check for UAs only */
 #define UAS_TUR 0	/* if no UAs then check if media access possible */
 
-/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
+/* when 1==SDEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
  * sector on read commands: */
 #define OPT_MEDIUM_ERR_ADDR   0x1234 /* that's sector 4660 in decimal */
 #define OPT_MEDIUM_ERR_NUM    10     /* number of consecutive medium errs */
@@ -517,47 +516,48 @@ struct sdebug_scmd_extra_t {
 	bool inj_short;
 };
 
-static int scsi_debug_add_host = DEF_NUM_HOST;
-static int scsi_debug_ato = DEF_ATO;
-static int scsi_debug_delay = DEF_DELAY;
-static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
-static int scsi_debug_dif = DEF_DIF;
-static int scsi_debug_dix = DEF_DIX;
-static int scsi_debug_dsense = DEF_D_SENSE;
-static int scsi_debug_every_nth = DEF_EVERY_NTH;
-static int scsi_debug_fake_rw = DEF_FAKE_RW;
-static unsigned int scsi_debug_guard = DEF_GUARD;
-static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
-static int scsi_debug_max_luns = DEF_MAX_LUNS;
-static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
+static int sdebug_add_host = DEF_NUM_HOST;
+static int sdebug_ato = DEF_ATO;
+static int sdebug_delay = DEF_DELAY;
+static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB;
+static int sdebug_dif = DEF_DIF;
+static int sdebug_dix = DEF_DIX;
+static int sdebug_dsense = DEF_D_SENSE;
+static int sdebug_every_nth = DEF_EVERY_NTH;
+static int sdebug_fake_rw = DEF_FAKE_RW;
+static unsigned int sdebug_guard = DEF_GUARD;
+static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED;
+static int sdebug_max_luns = DEF_MAX_LUNS;
+static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE;
 static atomic_t retired_max_queue;	/* if > 0 then was prior max_queue */
-static int scsi_debug_ndelay = DEF_NDELAY;
-static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
-static int scsi_debug_no_uld = 0;
-static int scsi_debug_num_parts = DEF_NUM_PARTS;
-static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
-static int scsi_debug_opt_blks = DEF_OPT_BLKS;
-static int scsi_debug_opts = DEF_OPTS;
-static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
-static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
-static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
-static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
-static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
-static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
-static unsigned int scsi_debug_lbpu = DEF_LBPU;
-static unsigned int scsi_debug_lbpws = DEF_LBPWS;
-static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;
-static unsigned int scsi_debug_lbprz = DEF_LBPRZ;
-static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
-static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
-static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
-static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
-static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
-static bool scsi_debug_removable = DEF_REMOVABLE;
-static bool scsi_debug_clustering;
-static bool scsi_debug_host_lock = DEF_HOST_LOCK;
-static bool scsi_debug_strict = DEF_STRICT;
+static int sdebug_ndelay = DEF_NDELAY;
+static int sdebug_no_lun_0 = DEF_NO_LUN_0;
+static int sdebug_no_uld;
+static int sdebug_num_parts = DEF_NUM_PARTS;
+static int sdebug_num_tgts = DEF_NUM_TGTS; /* targets per host */
+static int sdebug_opt_blks = DEF_OPT_BLKS;
+static int sdebug_opts = DEF_OPTS;
+static int sdebug_physblk_exp = DEF_PHYSBLK_EXP;
+static int sdebug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
+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;
+static unsigned int sdebug_lbpu = DEF_LBPU;
+static unsigned int sdebug_lbpws = DEF_LBPWS;
+static unsigned int sdebug_lbpws10 = DEF_LBPWS10;
+static unsigned int sdebug_lbprz = DEF_LBPRZ;
+static unsigned int sdebug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
+static unsigned int sdebug_unmap_granularity = DEF_UNMAP_GRANULARITY;
+static unsigned int sdebug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
+static unsigned int sdebug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
+static unsigned int sdebug_write_same_length = DEF_WRITESAME_LENGTH;
+static bool sdebug_removable = DEF_REMOVABLE;
+static bool sdebug_clustering;
+static bool sdebug_host_lock = DEF_HOST_LOCK;
+static bool sdebug_strict = DEF_STRICT;
 static bool sdebug_any_injecting_opt;
+static bool sdebug_verbose;
 
 static atomic_t sdebug_cmnd_count;
 static atomic_t sdebug_completions;
@@ -580,8 +580,8 @@ static int sdebug_sectors_per;		/* sectors per cylinder */
 
 static unsigned int scsi_debug_lbp(void)
 {
-	return ((0 == scsi_debug_fake_rw) &&
-		(scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
+	return ((0 == sdebug_fake_rw) &&
+		(sdebug_lbpu | sdebug_lbpws | sdebug_lbpws10));
 }
 
 struct sdebug_dev_info {
@@ -674,7 +674,7 @@ static void *fake_store(unsigned long long lba)
 {
 	lba = do_div(lba, sdebug_store_sectors);
 
-	return fake_storep + lba * scsi_debug_sector_size;
+	return fake_storep + lba * sdebug_sector_size;
 }
 
 static struct sd_dif_tuple *dif_store(sector_t sector)
@@ -696,11 +696,11 @@ static void sdebug_max_tgts_luns(void)
 	list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
 		hpnt = sdbg_host->shost;
 		if ((hpnt->this_id >= 0) &&
-		    (scsi_debug_num_tgts > hpnt->this_id))
-			hpnt->max_id = scsi_debug_num_tgts + 1;
+		    (sdebug_num_tgts > hpnt->this_id))
+			hpnt->max_id = sdebug_num_tgts + 1;
 		else
-			hpnt->max_id = scsi_debug_num_tgts;
-		/* scsi_debug_max_luns; */
+			hpnt->max_id = sdebug_num_tgts;
+		/* sdebug_max_luns; */
 		hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
 	}
 	spin_unlock(&sdebug_host_list_lock);
@@ -725,8 +725,7 @@ mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
 	}
 	asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST;
 	memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
-	scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST,
-				asc, 0);
+	scsi_build_sense_buffer(sdebug_dsense, sbuff, ILLEGAL_REQUEST, asc, 0);
 	memset(sks, 0, sizeof(sks));
 	sks[0] = 0x80;
 	if (c_d)
@@ -736,7 +735,7 @@ mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
 		sks[0] |= 0x7 & in_bit;
 	}
 	put_unaligned_be16(in_byte, sks + 1);
-	if (scsi_debug_dsense) {
+	if (sdebug_dsense) {
 		sl = sbuff[7] + 8;
 		sbuff[7] = sl;
 		sbuff[sl] = 0x2;
@@ -744,7 +743,7 @@ mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
 		memcpy(sbuff + sl + 4, sks, 3);
 	} else
 		memcpy(sbuff + 15, sks, 3);
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+	if (sdebug_verbose)
 		sdev_printk(KERN_INFO, scp->device, "%s:  [sense_key,asc,ascq"
 			    "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n",
 			    my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit);
@@ -762,9 +761,9 @@ static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
 	}
 	memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
 
-	scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
+	scsi_build_sense_buffer(sdebug_dsense, sbuff, key, asc, asq);
 
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+	if (sdebug_verbose)
 		sdev_printk(KERN_INFO, scp->device,
 			    "%s:  [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n",
 			    my_name, key, asc, asq);
@@ -778,7 +777,7 @@ mk_sense_invalid_opcode(struct scsi_cmnd *scp)
 
 static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
 {
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
+	if (sdebug_verbose) {
 		if (0x1261 == cmd)
 			sdev_printk(KERN_INFO, dev,
 				    "%s: BLKFLSBUF [0x1261]\n", __func__);
@@ -814,7 +813,6 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
 			   struct sdebug_dev_info * devip)
 {
 	int k;
-	bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
 
 	k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS);
 	if (k != SDEBUG_NUM_UAS) {
@@ -824,38 +822,38 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
 		case SDEBUG_UA_POR:
 			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
 					UA_RESET_ASC, POWER_ON_RESET_ASCQ);
-			if (debug)
+			if (sdebug_verbose)
 				cp = "power on reset";
 			break;
 		case SDEBUG_UA_BUS_RESET:
 			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
 					UA_RESET_ASC, BUS_RESET_ASCQ);
-			if (debug)
+			if (sdebug_verbose)
 				cp = "bus reset";
 			break;
 		case SDEBUG_UA_MODE_CHANGED:
 			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
 					UA_CHANGED_ASC, MODE_CHANGED_ASCQ);
-			if (debug)
+			if (sdebug_verbose)
 				cp = "mode parameters changed";
 			break;
 		case SDEBUG_UA_CAPACITY_CHANGED:
 			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
 					UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
-			if (debug)
+			if (sdebug_verbose)
 				cp = "capacity data changed";
 			break;
 		case SDEBUG_UA_MICROCODE_CHANGED:
 			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
 				 TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ);
-			if (debug)
+			if (sdebug_verbose)
 				cp = "microcode has been changed";
 			break;
 		case SDEBUG_UA_MICROCODE_CHANGED_WO_RESET:
 			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
 					TARGET_CHANGED_ASC,
 					MICROCODE_CHANGED_WO_RESET_ASCQ);
-			if (debug)
+			if (sdebug_verbose)
 				cp = "microcode has been changed without reset";
 			break;
 		case SDEBUG_UA_LUNS_CHANGED:
@@ -864,26 +862,25 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
 			 * ASC/ASCQ REPORTED LUNS DATA HAS CHANGED on every LUN
 			 * on the target, until a REPORT LUNS command is
 			 * received.  SPC-4 behavior is to report it only once.
-			 * NOTE:  scsi_debug_scsi_level does not use the same
+			 * NOTE:  sdebug_scsi_level does not use the same
 			 * values as struct scsi_device->scsi_level.
 			 */
-			if (scsi_debug_scsi_level >= 6)	/* SPC-4 and above */
+			if (sdebug_scsi_level >= 6)	/* SPC-4 and above */
 				clear_luns_changed_on_target(devip);
 			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
 					TARGET_CHANGED_ASC,
 					LUNS_CHANGED_ASCQ);
-			if (debug)
+			if (sdebug_verbose)
 				cp = "reported luns data has changed";
 			break;
 		default:
-			pr_warn("%s: unexpected unit attention code=%d\n",
-				__func__, k);
-			if (debug)
+			pr_warn("unexpected unit attention code=%d\n", k);
+			if (sdebug_verbose)
 				cp = "unknown";
 			break;
 		}
 		clear_bit(k, devip->uas_bm);
-		if (debug)
+		if (sdebug_verbose)
 			sdev_printk(KERN_INFO, SCpnt->device,
 				   "%s reports: Unit attention: %s\n",
 				   my_name, cp);
@@ -892,7 +889,7 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
 	if ((UAS_TUR == uas_only) && devip->stopped) {
 		mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY,
 				0x2);
-		if (debug)
+		if (sdebug_verbose)
 			sdev_printk(KERN_INFO, SCpnt->device,
 				    "%s reports: Not ready: %s\n", my_name,
 				    "initializing command required");
@@ -911,7 +908,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
 	if (!sdb->length)
 		return 0;
 	if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
-		return (DID_ERROR << 16);
+		return DID_ERROR << 16;
 
 	act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
 				      arr, arr_len);
@@ -935,7 +932,10 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
 
 static const char * inq_vendor_id = "Linux   ";
 static const char * inq_product_id = "scsi_debug      ";
-static const char *inq_product_rev = "0184";	/* version less '.' */
+static const char *inq_product_rev = "0186";	/* version less '.' */
+static const u64 naa5_comp_a = 0x5222222000000000ULL;
+static const u64 naa5_comp_b = 0x5333333000000000ULL;
+static const u64 naa5_comp_c = 0x5111111000000000ULL;
 
 /* Device identification VPD page. Returns number of bytes placed in arr */
 static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
@@ -963,14 +963,8 @@ static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
 		arr[num++] = 0x3;	/* PIV=0, lu, naa */
 		arr[num++] = 0x0;
 		arr[num++] = 0x8;
-		arr[num++] = 0x53;  /* naa-5 ieee company id=0x333333 (fake) */
-		arr[num++] = 0x33;
-		arr[num++] = 0x33;
-		arr[num++] = 0x30;
-		arr[num++] = (dev_id_num >> 24);
-		arr[num++] = (dev_id_num >> 16) & 0xff;
-		arr[num++] = (dev_id_num >> 8) & 0xff;
-		arr[num++] = dev_id_num & 0xff;
+		put_unaligned_be64(naa5_comp_b + dev_id_num, arr + num);
+		num += 8;
 		/* Target relative port number */
 		arr[num++] = 0x61;	/* proto=sas, binary */
 		arr[num++] = 0x94;	/* PIV=1, target port, rel port */
@@ -986,14 +980,8 @@ static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
 	arr[num++] = 0x93;	/* piv=1, target port, naa */
 	arr[num++] = 0x0;
 	arr[num++] = 0x8;
-	arr[num++] = 0x52;	/* naa-5, company id=0x222222 (fake) */
-	arr[num++] = 0x22;
-	arr[num++] = 0x22;
-	arr[num++] = 0x20;
-	arr[num++] = (port_a >> 24);
-	arr[num++] = (port_a >> 16) & 0xff;
-	arr[num++] = (port_a >> 8) & 0xff;
-	arr[num++] = port_a & 0xff;
+	put_unaligned_be64(naa5_comp_a + port_a, arr + num);
+	num += 8;
 	/* NAA-5, Target port group identifier */
 	arr[num++] = 0x61;	/* proto=sas, binary */
 	arr[num++] = 0x95;	/* piv=1, target port group id */
@@ -1001,21 +989,15 @@ static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
 	arr[num++] = 0x4;
 	arr[num++] = 0;
 	arr[num++] = 0;
-	arr[num++] = (port_group_id >> 8) & 0xff;
-	arr[num++] = port_group_id & 0xff;
+	put_unaligned_be16(port_group_id, arr + num);
+	num += 2;
 	/* NAA-5, Target device identifier */
 	arr[num++] = 0x61;	/* proto=sas, binary */
 	arr[num++] = 0xa3;	/* piv=1, target device, naa */
 	arr[num++] = 0x0;
 	arr[num++] = 0x8;
-	arr[num++] = 0x52;	/* naa-5, company id=0x222222 (fake) */
-	arr[num++] = 0x22;
-	arr[num++] = 0x22;
-	arr[num++] = 0x20;
-	arr[num++] = (target_dev_id >> 24);
-	arr[num++] = (target_dev_id >> 16) & 0xff;
-	arr[num++] = (target_dev_id >> 8) & 0xff;
-	arr[num++] = target_dev_id & 0xff;
+	put_unaligned_be64(naa5_comp_a + target_dev_id, arr + num);
+	num += 8;
 	/* SCSI name string: Target device identifier */
 	arr[num++] = 0x63;	/* proto=sas, UTF-8 */
 	arr[num++] = 0xa8;	/* piv=1, target device, SCSI name string */
@@ -1031,7 +1013,6 @@ static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
 	return num;
 }
 
-
 static unsigned char vpd84_data[] = {
 /* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0,
     0x22,0x22,0x22,0x0,0xbb,0x1,
@@ -1101,15 +1082,8 @@ static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
 	arr[num++] = 0x93;	/* PIV=1, target port, NAA */
 	arr[num++] = 0x0;	/* reserved */
 	arr[num++] = 0x8;	/* length */
-	arr[num++] = 0x52;	/* NAA-5, company_id=0x222222 (fake) */
-	arr[num++] = 0x22;
-	arr[num++] = 0x22;
-	arr[num++] = 0x20;
-	arr[num++] = (port_a >> 24);
-	arr[num++] = (port_a >> 16) & 0xff;
-	arr[num++] = (port_a >> 8) & 0xff;
-	arr[num++] = port_a & 0xff;
-
+	put_unaligned_be64(naa5_comp_a + port_a, arr + num);
+	num += 8;
 	arr[num++] = 0x0;	/* reserved */
 	arr[num++] = 0x0;	/* reserved */
 	arr[num++] = 0x0;
@@ -1123,14 +1097,8 @@ static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
 	arr[num++] = 0x93;	/* PIV=1, target port, NAA */
 	arr[num++] = 0x0;	/* reserved */
 	arr[num++] = 0x8;	/* length */
-	arr[num++] = 0x52;	/* NAA-5, company_id=0x222222 (fake) */
-	arr[num++] = 0x22;
-	arr[num++] = 0x22;
-	arr[num++] = 0x20;
-	arr[num++] = (port_b >> 24);
-	arr[num++] = (port_b >> 16) & 0xff;
-	arr[num++] = (port_b >> 8) & 0xff;
-	arr[num++] = port_b & 0xff;
+	put_unaligned_be64(naa5_comp_a + port_b, arr + num);
+	num += 8;
 
 	return num;
 }
@@ -1203,40 +1171,35 @@ static int inquiry_evpd_b0(unsigned char * arr)
 	memcpy(arr, vpdb0_data, sizeof(vpdb0_data));
 
 	/* Optimal transfer length granularity */
-	gran = 1 << scsi_debug_physblk_exp;
-	arr[2] = (gran >> 8) & 0xff;
-	arr[3] = gran & 0xff;
+	gran = 1 << sdebug_physblk_exp;
+	put_unaligned_be16(gran, arr + 2);
 
 	/* Maximum Transfer Length */
-	if (sdebug_store_sectors > 0x400) {
-		arr[4] = (sdebug_store_sectors >> 24) & 0xff;
-		arr[5] = (sdebug_store_sectors >> 16) & 0xff;
-		arr[6] = (sdebug_store_sectors >> 8) & 0xff;
-		arr[7] = sdebug_store_sectors & 0xff;
-	}
+	if (sdebug_store_sectors > 0x400)
+		put_unaligned_be32(sdebug_store_sectors, arr + 4);
 
 	/* Optimal Transfer Length */
-	put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
+	put_unaligned_be32(sdebug_opt_blks, &arr[8]);
 
-	if (scsi_debug_lbpu) {
+	if (sdebug_lbpu) {
 		/* Maximum Unmap LBA Count */
-		put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
+		put_unaligned_be32(sdebug_unmap_max_blocks, &arr[16]);
 
 		/* Maximum Unmap Block Descriptor Count */
-		put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
+		put_unaligned_be32(sdebug_unmap_max_desc, &arr[20]);
 	}
 
 	/* Unmap Granularity Alignment */
-	if (scsi_debug_unmap_alignment) {
-		put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]);
+	if (sdebug_unmap_alignment) {
+		put_unaligned_be32(sdebug_unmap_alignment, &arr[28]);
 		arr[28] |= 0x80; /* UGAVALID */
 	}
 
 	/* Optimal Unmap Granularity */
-	put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
+	put_unaligned_be32(sdebug_unmap_granularity, &arr[24]);
 
 	/* Maximum WRITE SAME Length */
-	put_unaligned_be64(scsi_debug_write_same_length, &arr[32]);
+	put_unaligned_be64(sdebug_write_same_length, &arr[32]);
 
 	return 0x3c; /* Mandatory page length for Logical Block Provisioning */
 
@@ -1261,16 +1224,16 @@ static int inquiry_evpd_b2(unsigned char *arr)
 	memset(arr, 0, 0x4);
 	arr[0] = 0;			/* threshold exponent */
 
-	if (scsi_debug_lbpu)
+	if (sdebug_lbpu)
 		arr[1] = 1 << 7;
 
-	if (scsi_debug_lbpws)
+	if (sdebug_lbpws)
 		arr[1] |= 1 << 6;
 
-	if (scsi_debug_lbpws10)
+	if (sdebug_lbpws10)
 		arr[1] |= 1 << 5;
 
-	if (scsi_debug_lbprz)
+	if (sdebug_lbprz)
 		arr[1] |= 1 << 2;
 
 	return 0x4;
@@ -1287,17 +1250,17 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	int alloc_len, n, ret;
 	bool have_wlun;
 
-	alloc_len = (cmd[3] << 8) + cmd[4];
+	alloc_len = get_unaligned_be16(cmd + 3);
 	arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
 	if (! arr)
 		return DID_REQUEUE << 16;
 	have_wlun = (scp->device->lun == SCSI_W_LUN_REPORT_LUNS);
 	if (have_wlun)
 		pq_pdt = 0x1e;	/* present, wlun */
-	else if (scsi_debug_no_lun_0 && (0 == devip->lun))
+	else if (sdebug_no_lun_0 && (0 == devip->lun))
 		pq_pdt = 0x7f;	/* not present, no device type */
 	else
-		pq_pdt = (scsi_debug_ptype & 0x1f);
+		pq_pdt = (sdebug_ptype & 0x1f);
 	arr[0] = pq_pdt;
 	if (0x2 & cmd[1]) {  /* CMDDT bit set */
 		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
@@ -1310,7 +1273,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		
 		port_group_id = (((host_no + 1) & 0x7f) << 8) +
 		    (devip->channel & 0x7f);
-		if (0 == scsi_debug_vpd_use_hostno)
+		if (0 == sdebug_vpd_use_hostno)
 			host_no = 0;
 		lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) +
 			    (devip->target * 1000) + devip->lun);
@@ -1352,9 +1315,9 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		} else if (0x86 == cmd[2]) { /* extended inquiry */
 			arr[1] = cmd[2];	/*sanity */
 			arr[3] = 0x3c;	/* number of following entries */
-			if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION)
+			if (sdebug_dif == SD_DIF_TYPE3_PROTECTION)
 				arr[4] = 0x4;	/* SPT: GRD_CHK:1 */
-			else if (scsi_debug_dif)
+			else if (sdebug_dif)
 				arr[4] = 0x5;   /* SPT: GRD_CHK:1, REF_CHK:1 */
 			else
 				arr[4] = 0x0;   /* no protection stuff */
@@ -1372,8 +1335,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		} else if (0x89 == cmd[2]) { /* ATA information */
 			arr[1] = cmd[2];        /*sanity */
 			n = inquiry_evpd_89(&arr[4]);
-			arr[2] = (n >> 8);
-			arr[3] = (n & 0xff);
+			put_unaligned_be16(n, arr + 2);
 		} else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
 			arr[1] = cmd[2];        /*sanity */
 			arr[3] = inquiry_evpd_b0(&arr[4]);
@@ -1388,19 +1350,19 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 			kfree(arr);
 			return check_condition_result;
 		}
-		len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
+		len = min(get_unaligned_be16(arr + 2) + 4, alloc_len);
 		ret = fill_from_dev_buffer(scp, arr,
 			    min(len, SDEBUG_MAX_INQ_ARR_SZ));
 		kfree(arr);
 		return ret;
 	}
 	/* drops through here for a standard inquiry */
-	arr[1] = scsi_debug_removable ? 0x80 : 0;	/* Removable disk */
-	arr[2] = scsi_debug_scsi_level;
+	arr[1] = sdebug_removable ? 0x80 : 0;	/* Removable disk */
+	arr[2] = sdebug_scsi_level;
 	arr[3] = 2;    /* response_data_format==2 */
 	arr[4] = SDEBUG_LONG_INQ_SZ - 5;
-	arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */
-	if (0 == scsi_debug_vpd_use_hostno)
+	arr[5] = sdebug_dif ? 1 : 0; /* PROTECT bit */
+	if (0 == sdebug_vpd_use_hostno)
 		arr[5] = 0x10; /* claim: implicit TGPS */
 	arr[6] = 0x10; /* claim: MultiP */
 	/* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
@@ -1412,9 +1374,9 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	arr[58] = 0x0; arr[59] = 0xa2;  /* SAM-5 rev 4 */
 	arr[60] = 0x4; arr[61] = 0x68;  /* SPC-4 rev 37 */
 	n = 62;
-	if (scsi_debug_ptype == 0) {
+	if (sdebug_ptype == 0) {
 		arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */
-	} else if (scsi_debug_ptype == 1) {
+	} else if (sdebug_ptype == 1) {
 		arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */
 	}
 	arr[n++] = 0x20; arr[n++] = 0xe6;  /* SPL-3 rev 7 */
@@ -1452,7 +1414,7 @@ static int resp_requests(struct scsi_cmnd * scp,
 		}
 	} else {
 		memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
-		if (arr[0] >= 0x70 && dsense == scsi_debug_dsense)
+		if (arr[0] >= 0x70 && dsense == sdebug_dsense)
 			;	/* have sense and formats match */
 		else if (arr[0] <= 0x70) {
 			if (dsense) {
@@ -1504,9 +1466,11 @@ static int resp_start_stop(struct scsi_cmnd * scp,
 
 static sector_t get_sdebug_capacity(void)
 {
-	if (scsi_debug_virtual_gb > 0)
-		return (sector_t)scsi_debug_virtual_gb *
-			(1073741824 / scsi_debug_sector_size);
+	static const unsigned int gibibyte = 1073741824;
+
+	if (sdebug_virtual_gb > 0)
+		return (sector_t)sdebug_virtual_gb *
+			(gibibyte / sdebug_sector_size);
 	else
 		return sdebug_store_sectors;
 }
@@ -1523,18 +1487,10 @@ static int resp_readcap(struct scsi_cmnd * scp,
 	memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
 	if (sdebug_capacity < 0xffffffff) {
 		capac = (unsigned int)sdebug_capacity - 1;
-		arr[0] = (capac >> 24);
-		arr[1] = (capac >> 16) & 0xff;
-		arr[2] = (capac >> 8) & 0xff;
-		arr[3] = capac & 0xff;
-	} else {
-		arr[0] = 0xff;
-		arr[1] = 0xff;
-		arr[2] = 0xff;
-		arr[3] = 0xff;
-	}
-	arr[6] = (scsi_debug_sector_size >> 8) & 0xff;
-	arr[7] = scsi_debug_sector_size & 0xff;
+		put_unaligned_be32(capac, arr + 0);
+	} else
+		put_unaligned_be32(0xffffffff, arr + 0);
+	put_unaligned_be16(sdebug_sector_size, arr + 6);
 	return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
 }
 
@@ -1544,34 +1500,27 @@ static int resp_readcap16(struct scsi_cmnd * scp,
 {
 	unsigned char *cmd = scp->cmnd;
 	unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
-	unsigned long long capac;
-	int k, alloc_len;
+	int alloc_len;
 
-	alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
-		     + cmd[13]);
+	alloc_len = get_unaligned_be32(cmd + 10);
 	/* following just in case virtual_gb changed */
 	sdebug_capacity = get_sdebug_capacity();
 	memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
-	capac = sdebug_capacity - 1;
-	for (k = 0; k < 8; ++k, capac >>= 8)
-		arr[7 - k] = capac & 0xff;
-	arr[8] = (scsi_debug_sector_size >> 24) & 0xff;
-	arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
-	arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
-	arr[11] = scsi_debug_sector_size & 0xff;
-	arr[13] = scsi_debug_physblk_exp & 0xf;
-	arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
+	put_unaligned_be64((u64)(sdebug_capacity - 1), arr + 0);
+	put_unaligned_be32(sdebug_sector_size, arr + 8);
+	arr[13] = sdebug_physblk_exp & 0xf;
+	arr[14] = (sdebug_lowest_aligned >> 8) & 0x3f;
 
 	if (scsi_debug_lbp()) {
 		arr[14] |= 0x80; /* LBPME */
-		if (scsi_debug_lbprz)
+		if (sdebug_lbprz)
 			arr[14] |= 0x40; /* LBPRZ */
 	}
 
-	arr[15] = scsi_debug_lowest_aligned & 0xff;
+	arr[15] = sdebug_lowest_aligned & 0xff;
 
-	if (scsi_debug_dif) {
-		arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */
+	if (sdebug_dif) {
+		arr[12] = (sdebug_dif - 1) << 1; /* P_TYPE */
 		arr[12] |= 1; /* PROT_EN */
 	}
 
@@ -1590,9 +1539,7 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp,
 	int n, ret, alen, rlen;
 	int port_group_a, port_group_b, port_a, port_b;
 
-	alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
-		+ cmd[9]);
-
+	alen = get_unaligned_be32(cmd + 6);
 	arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
 	if (! arr)
 		return DID_REQUEUE << 16;
@@ -1605,49 +1552,46 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp,
 	port_a = 0x1; /* relative port A */
 	port_b = 0x2; /* relative port B */
 	port_group_a = (((host_no + 1) & 0x7f) << 8) +
-	    (devip->channel & 0x7f);
+			(devip->channel & 0x7f);
 	port_group_b = (((host_no + 1) & 0x7f) << 8) +
-	    (devip->channel & 0x7f) + 0x80;
+			(devip->channel & 0x7f) + 0x80;
 
 	/*
 	 * The asymmetric access state is cycled according to the host_id.
 	 */
 	n = 4;
-	if (0 == scsi_debug_vpd_use_hostno) {
-	    arr[n++] = host_no % 3; /* Asymm access state */
-	    arr[n++] = 0x0F; /* claim: all states are supported */
+	if (0 == sdebug_vpd_use_hostno) {
+		arr[n++] = host_no % 3; /* Asymm access state */
+		arr[n++] = 0x0F; /* claim: all states are supported */
 	} else {
-	    arr[n++] = 0x0; /* Active/Optimized path */
-	    arr[n++] = 0x01; /* claim: only support active/optimized paths */
+		arr[n++] = 0x0; /* Active/Optimized path */
+		arr[n++] = 0x01; /* only support active/optimized paths */
 	}
-	arr[n++] = (port_group_a >> 8) & 0xff;
-	arr[n++] = port_group_a & 0xff;
+	put_unaligned_be16(port_group_a, arr + n);
+	n += 2;
 	arr[n++] = 0;    /* Reserved */
 	arr[n++] = 0;    /* Status code */
 	arr[n++] = 0;    /* Vendor unique */
 	arr[n++] = 0x1;  /* One port per group */
 	arr[n++] = 0;    /* Reserved */
 	arr[n++] = 0;    /* Reserved */
-	arr[n++] = (port_a >> 8) & 0xff;
-	arr[n++] = port_a & 0xff;
+	put_unaligned_be16(port_a, arr + n);
+	n += 2;
 	arr[n++] = 3;    /* Port unavailable */
 	arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */
-	arr[n++] = (port_group_b >> 8) & 0xff;
-	arr[n++] = port_group_b & 0xff;
+	put_unaligned_be16(port_group_b, arr + n);
+	n += 2;
 	arr[n++] = 0;    /* Reserved */
 	arr[n++] = 0;    /* Status code */
 	arr[n++] = 0;    /* Vendor unique */
 	arr[n++] = 0x1;  /* One port per group */
 	arr[n++] = 0;    /* Reserved */
 	arr[n++] = 0;    /* Reserved */
-	arr[n++] = (port_b >> 8) & 0xff;
-	arr[n++] = port_b & 0xff;
+	put_unaligned_be16(port_b, arr + n);
+	n += 2;
 
 	rlen = n - 4;
-	arr[0] = (rlen >> 24) & 0xff;
-	arr[1] = (rlen >> 16) & 0xff;
-	arr[2] = (rlen >> 8) & 0xff;
-	arr[3] = rlen & 0xff;
+	put_unaligned_be32(rlen, arr + 0);
 
 	/*
 	 * Return the smallest value of either
@@ -1871,11 +1815,9 @@ static int resp_format_pg(unsigned char * p, int pcontrol, int target)
 				     0, 0, 0, 0, 0x40, 0, 0, 0};
 
 	memcpy(p, format_pg, sizeof(format_pg));
-	p[10] = (sdebug_sectors_per >> 8) & 0xff;
-	p[11] = sdebug_sectors_per & 0xff;
-	p[12] = (scsi_debug_sector_size >> 8) & 0xff;
-	p[13] = scsi_debug_sector_size & 0xff;
-	if (scsi_debug_removable)
+	put_unaligned_be16(sdebug_sectors_per, p + 10);
+	put_unaligned_be16(sdebug_sector_size, p + 12);
+	if (sdebug_removable)
 		p[20] |= 0x20; /* should agree with INQUIRY */
 	if (1 == pcontrol)
 		memset(p + 2, 0, sizeof(format_pg) - 2);
@@ -1889,7 +1831,7 @@ static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
 	unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
 		0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,     0, 0, 0, 0};
 
-	if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts)
+	if (SDEBUG_OPT_N_WCE & sdebug_opts)
 		caching_pg[2] &= ~0x4;	/* set WCE=0 (default WCE=1) */
 	memcpy(p, caching_pg, sizeof(caching_pg));
 	if (1 == pcontrol)
@@ -1906,12 +1848,12 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
 	unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
 				     0, 0, 0x2, 0x4b};
 
-	if (scsi_debug_dsense)
+	if (sdebug_dsense)
 		ctrl_m_pg[2] |= 0x4;
 	else
 		ctrl_m_pg[2] &= ~0x4;
 
-	if (scsi_debug_ato)
+	if (sdebug_ato)
 		ctrl_m_pg[5] |= 0x80; /* ATO=1 */
 
 	memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
@@ -1955,31 +1897,29 @@ static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target,
 {	/* SAS phy control and discover mode page for mode_sense */
 	unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2,
 		    0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0,
-		    0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
-		    0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
+		    0, 0, 0, 0, 0, 0, 0, 0,	/* insert SAS addr */
+		    0, 0, 0, 0, 0, 0, 0, 0,	/* insert SAS addr */
 		    0x2, 0, 0, 0, 0, 0, 0, 0,
 		    0x88, 0x99, 0, 0, 0, 0, 0, 0,
 		    0, 0, 0, 0, 0, 0, 0, 0,
 		    0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0,
-		    0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
-		    0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
+		    0, 0, 0, 0, 0, 0, 0, 0,	/* insert SAS addr */
+		    0, 0, 0, 0, 0, 0, 0, 0,	/* insert SAS addr */
 		    0x3, 0, 0, 0, 0, 0, 0, 0,
 		    0x88, 0x99, 0, 0, 0, 0, 0, 0,
 		    0, 0, 0, 0, 0, 0, 0, 0,
 		};
 	int port_a, port_b;
 
+	put_unaligned_be64(naa5_comp_a, sas_pcd_m_pg + 16);
+	put_unaligned_be64(naa5_comp_c + 1, sas_pcd_m_pg + 24);
+	put_unaligned_be64(naa5_comp_a, sas_pcd_m_pg + 64);
+	put_unaligned_be64(naa5_comp_c + 1, sas_pcd_m_pg + 72);
 	port_a = target_dev_id + 1;
 	port_b = port_a + 1;
 	memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg));
-	p[20] = (port_a >> 24);
-	p[21] = (port_a >> 16) & 0xff;
-	p[22] = (port_a >> 8) & 0xff;
-	p[23] = port_a & 0xff;
-	p[48 + 20] = (port_b >> 24);
-	p[48 + 21] = (port_b >> 16) & 0xff;
-	p[48 + 22] = (port_b >> 8) & 0xff;
-	p[48 + 23] = port_b & 0xff;
+	put_unaligned_be32(port_a, p + 20);
+	put_unaligned_be32(port_b, p + 48 + 20);
 	if (1 == pcontrol)
 		memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4);
 	return sizeof(sas_pcd_m_pg);
@@ -2005,7 +1945,7 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	unsigned char dbd, llbaa;
 	int pcontrol, pcode, subpcode, bd_len;
 	unsigned char dev_spec;
-	int k, alloc_len, msense_6, offset, len, target_dev_id;
+	int alloc_len, msense_6, offset, len, target_dev_id;
 	int target = scp->device->id;
 	unsigned char * ap;
 	unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
@@ -2017,11 +1957,11 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	subpcode = cmd[3];
 	msense_6 = (MODE_SENSE == cmd[0]);
 	llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10);
-	if ((0 == scsi_debug_ptype) && (0 == dbd))
+	if ((0 == sdebug_ptype) && (0 == dbd))
 		bd_len = llbaa ? 16 : 8;
 	else
 		bd_len = 0;
-	alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
+	alloc_len = msense_6 ? cmd[4] : get_unaligned_be16(cmd + 7);
 	memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
 	if (0x3 == pcontrol) {  /* Saving values not supported */
 		mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0);
@@ -2030,7 +1970,7 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
 			(devip->target * 1000) - 3;
 	/* set DPOFUA bit for disks */
-	if (0 == scsi_debug_ptype)
+	if (0 == sdebug_ptype)
 		dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
 	else
 		dev_spec = 0x0;
@@ -2050,30 +1990,16 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		sdebug_capacity = get_sdebug_capacity();
 
 	if (8 == bd_len) {
-		if (sdebug_capacity > 0xfffffffe) {
-			ap[0] = 0xff;
-			ap[1] = 0xff;
-			ap[2] = 0xff;
-			ap[3] = 0xff;
-		} else {
-			ap[0] = (sdebug_capacity >> 24) & 0xff;
-			ap[1] = (sdebug_capacity >> 16) & 0xff;
-			ap[2] = (sdebug_capacity >> 8) & 0xff;
-			ap[3] = sdebug_capacity & 0xff;
-		}
-		ap[6] = (scsi_debug_sector_size >> 8) & 0xff;
-		ap[7] = scsi_debug_sector_size & 0xff;
+		if (sdebug_capacity > 0xfffffffe)
+			put_unaligned_be32(0xffffffff, ap + 0);
+		else
+			put_unaligned_be32(sdebug_capacity, ap + 0);
+		put_unaligned_be16(sdebug_sector_size, ap + 6);
 		offset += bd_len;
 		ap = arr + offset;
 	} else if (16 == bd_len) {
-		unsigned long long capac = sdebug_capacity;
-
-        	for (k = 0; k < 8; ++k, capac >>= 8)
-                	ap[7 - k] = capac & 0xff;
-		ap[12] = (scsi_debug_sector_size >> 24) & 0xff;
-		ap[13] = (scsi_debug_sector_size >> 16) & 0xff;
-		ap[14] = (scsi_debug_sector_size >> 8) & 0xff;
-		ap[15] = scsi_debug_sector_size & 0xff;
+		put_unaligned_be64((u64)sdebug_capacity, ap + 0);
+		put_unaligned_be32(sdebug_sector_size, ap + 12);
 		offset += bd_len;
 		ap = arr + offset;
 	}
@@ -2149,10 +2075,8 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	}
 	if (msense_6)
 		arr[0] = offset - 1;
-	else {
-		arr[0] = ((offset - 2) >> 8) & 0xff;
-		arr[1] = (offset - 2) & 0xff;
-	}
+	else
+		put_unaligned_be16((offset - 2), arr + 0);
 	return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
 }
 
@@ -2170,21 +2094,20 @@ resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	memset(arr, 0, sizeof(arr));
 	pf = cmd[1] & 0x10;
 	sp = cmd[1] & 0x1;
-	param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
+	param_len = mselect6 ? cmd[4] : get_unaligned_be16(cmd + 7);
 	if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
 		mk_sense_invalid_fld(scp, SDEB_IN_CDB, mselect6 ? 4 : 7, -1);
 		return check_condition_result;
 	}
         res = fetch_to_dev_buffer(scp, arr, param_len);
         if (-1 == res)
-                return (DID_ERROR << 16);
-        else if ((res < param_len) &&
-                 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+		return DID_ERROR << 16;
+	else if (sdebug_verbose && (res < param_len))
 		sdev_printk(KERN_INFO, scp->device,
 			    "%s: cdb indicated=%d, IO sent=%d bytes\n",
 			    __func__, param_len, res);
-	md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
-	bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
+	md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2);
+	bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6);
 	if (md_len > 2) {
 		mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1);
 		return check_condition_result;
@@ -2197,7 +2120,7 @@ resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		return check_condition_result;
 	}
 	spf = !!(arr[off] & 0x40);
-	pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
+	pg_len = spf ? (get_unaligned_be16(arr + off + 2) + 4) :
 		       (arr[off + 1] + 2);
 	if ((pg_len + off) > param_len) {
 		mk_sense_buffer(scp, ILLEGAL_REQUEST,
@@ -2216,7 +2139,7 @@ resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		if (ctrl_m_pg[1] == arr[off + 1]) {
 			memcpy(ctrl_m_pg + 2, arr + off + 2,
 			       sizeof(ctrl_m_pg) - 2);
-			scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
+			sdebug_dsense = !!(ctrl_m_pg[2] & 0x4);
 			goto set_mode_changed_ua;
 		}
 		break;
@@ -2279,7 +2202,7 @@ static int resp_log_sense(struct scsi_cmnd * scp,
 	pcontrol = (cmd[2] & 0xc0) >> 6;
 	pcode = cmd[2] & 0x3f;
 	subpcode = cmd[3] & 0xff;
-	alloc_len = (cmd[7] << 8) + cmd[8];
+	alloc_len = get_unaligned_be16(cmd + 7);
 	arr[0] = pcode;
 	if (0 == subpcode) {
 		switch (pcode) {
@@ -2336,7 +2259,7 @@ static int resp_log_sense(struct scsi_cmnd * scp,
 		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
 		return check_condition_result;
 	}
-	len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
+	len = min(get_unaligned_be16(arr + 2) + 4, alloc_len);
 	return fill_from_dev_buffer(scp, arr,
 		    min(len, SDEBUG_MAX_INQ_ARR_SZ));
 }
@@ -2384,15 +2307,15 @@ do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
 		rest = block + num - sdebug_store_sectors;
 
 	ret = sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
-		   fake_storep + (block * scsi_debug_sector_size),
-		   (num - rest) * scsi_debug_sector_size, 0, do_write);
-	if (ret != (num - rest) * scsi_debug_sector_size)
+		   fake_storep + (block * sdebug_sector_size),
+		   (num - rest) * sdebug_sector_size, 0, do_write);
+	if (ret != (num - rest) * sdebug_sector_size)
 		return ret;
 
 	if (rest) {
 		ret += sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
-			    fake_storep, rest * scsi_debug_sector_size,
-			    (num - rest) * scsi_debug_sector_size, do_write);
+			    fake_storep, rest * sdebug_sector_size,
+			    (num - rest) * sdebug_sector_size, do_write);
 	}
 
 	return ret;
@@ -2407,7 +2330,7 @@ comp_write_worker(u64 lba, u32 num, const u8 *arr)
 	bool res;
 	u64 block, rest = 0;
 	u32 store_blks = sdebug_store_sectors;
-	u32 lb_size = scsi_debug_sector_size;
+	u32 lb_size = sdebug_sector_size;
 
 	block = do_div(lba, store_blks);
 	if (block + num > store_blks)
@@ -2434,7 +2357,7 @@ static __be16 dif_compute_csum(const void *buf, int len)
 {
 	__be16 csum;
 
-	if (scsi_debug_guard)
+	if (sdebug_guard)
 		csum = (__force __be16)ip_compute_csum(buf, len);
 	else
 		csum = cpu_to_be16(crc_t10dif(buf, len));
@@ -2445,7 +2368,7 @@ static __be16 dif_compute_csum(const void *buf, int len)
 static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
 		      sector_t sector, u32 ei_lba)
 {
-	__be16 csum = dif_compute_csum(data, scsi_debug_sector_size);
+	__be16 csum = dif_compute_csum(data, sdebug_sector_size);
 
 	if (sdt->guard_tag != csum) {
 		pr_err("GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n",
@@ -2454,13 +2377,13 @@ static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
 			be16_to_cpu(csum));
 		return 0x01;
 	}
-	if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
+	if (sdebug_dif == SD_DIF_TYPE1_PROTECTION &&
 	    be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
 		pr_err("REF check failed on sector %lu\n",
 			(unsigned long)sector);
 		return 0x03;
 	}
-	if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+	if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
 	    be32_to_cpu(sdt->ref_tag) != ei_lba) {
 		pr_err("REF check failed on sector %lu\n",
 			(unsigned long)sector);
@@ -2592,13 +2515,13 @@ resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		break;
 	}
 	if (check_prot) {
-		if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+		if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
 		    (cmd[1] & 0xe0)) {
 			mk_sense_invalid_opcode(scp);
 			return check_condition_result;
 		}
-		if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
-		     scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
+		if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION ||
+		     sdebug_dif == SD_DIF_TYPE3_PROTECTION) &&
 		    (cmd[1] & 0xe0) == 0)
 			sdev_printk(KERN_ERR, scp->device, "Unprotected RD "
 				    "to DIF device\n");
@@ -2622,7 +2545,7 @@ resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		return check_condition_result;
 	}
 
-	if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
+	if ((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&
 	    (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
 	    ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
 		/* claim unrecoverable read error */
@@ -2641,7 +2564,7 @@ resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	read_lock_irqsave(&atomic_rw, iflags);
 
 	/* DIX + T10 DIF */
-	if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
+	if (sdebug_dix && scsi_prot_sg_count(scp)) {
 		int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
 
 		if (prot_ret) {
@@ -2750,13 +2673,13 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
 
 			ret = dif_verify(sdt, daddr, sector, ei_lba);
 			if (ret) {
-				dump_sector(daddr, scsi_debug_sector_size);
+				dump_sector(daddr, sdebug_sector_size);
 				goto out;
 			}
 
 			sector++;
 			ei_lba++;
-			dpage_offset += scsi_debug_sector_size;
+			dpage_offset += sdebug_sector_size;
 		}
 		diter.consumed = dpage_offset;
 		sg_miter_stop(&diter);
@@ -2777,24 +2700,18 @@ out:
 
 static unsigned long lba_to_map_index(sector_t lba)
 {
-	if (scsi_debug_unmap_alignment) {
-		lba += scsi_debug_unmap_granularity -
-			scsi_debug_unmap_alignment;
-	}
-	sector_div(lba, scsi_debug_unmap_granularity);
-
+	if (sdebug_unmap_alignment)
+		lba += sdebug_unmap_granularity - sdebug_unmap_alignment;
+	sector_div(lba, sdebug_unmap_granularity);
 	return lba;
 }
 
 static sector_t map_index_to_lba(unsigned long index)
 {
-	sector_t lba = index * scsi_debug_unmap_granularity;
-
-	if (scsi_debug_unmap_alignment) {
-		lba -= scsi_debug_unmap_granularity -
-			scsi_debug_unmap_alignment;
-	}
+	sector_t lba = index * sdebug_unmap_granularity;
 
+	if (sdebug_unmap_alignment)
+		lba -= sdebug_unmap_granularity - sdebug_unmap_alignment;
 	return lba;
 }
 
@@ -2815,7 +2732,6 @@ static unsigned int map_state(sector_t lba, unsigned int *num)
 
 	end = min_t(sector_t, sdebug_store_sectors,  map_index_to_lba(next));
 	*num = end - lba;
-
 	return mapped;
 }
 
@@ -2841,19 +2757,19 @@ static void unmap_region(sector_t lba, unsigned int len)
 		unsigned long index = lba_to_map_index(lba);
 
 		if (lba == map_index_to_lba(index) &&
-		    lba + scsi_debug_unmap_granularity <= end &&
+		    lba + sdebug_unmap_granularity <= end &&
 		    index < map_size) {
 			clear_bit(index, map_storep);
-			if (scsi_debug_lbprz) {
+			if (sdebug_lbprz) {
 				memset(fake_storep +
-				       lba * scsi_debug_sector_size, 0,
-				       scsi_debug_sector_size *
-				       scsi_debug_unmap_granularity);
+				       lba * sdebug_sector_size, 0,
+				       sdebug_sector_size *
+				       sdebug_unmap_granularity);
 			}
 			if (dif_storep) {
 				memset(dif_storep + lba, 0xff,
 				       sizeof(*dif_storep) *
-				       scsi_debug_unmap_granularity);
+				       sdebug_unmap_granularity);
 			}
 		}
 		lba = map_index_to_lba(index + 1);
@@ -2911,13 +2827,13 @@ resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		break;
 	}
 	if (check_prot) {
-		if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+		if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
 		    (cmd[1] & 0xe0)) {
 			mk_sense_invalid_opcode(scp);
 			return check_condition_result;
 		}
-		if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
-		     scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
+		if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION ||
+		     sdebug_dif == SD_DIF_TYPE3_PROTECTION) &&
 		    (cmd[1] & 0xe0) == 0)
 			sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
 				    "to DIF device\n");
@@ -2938,7 +2854,7 @@ resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	write_lock_irqsave(&atomic_rw, iflags);
 
 	/* DIX + T10 DIF */
-	if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
+	if (sdebug_dix && scsi_prot_sg_count(scp)) {
 		int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
 
 		if (prot_ret) {
@@ -2953,12 +2869,11 @@ resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		map_region(lba, num);
 	write_unlock_irqrestore(&atomic_rw, iflags);
 	if (-1 == ret)
-		return (DID_ERROR << 16);
-	else if ((ret < (num * scsi_debug_sector_size)) &&
-		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+		return DID_ERROR << 16;
+	else if (sdebug_verbose && (ret < (num * sdebug_sector_size)))
 		sdev_printk(KERN_INFO, scp->device,
 			    "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
-			    my_name, num * scsi_debug_sector_size, ret);
+			    my_name, num * sdebug_sector_size, ret);
 
 	if (sdebug_any_injecting_opt) {
 		struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
@@ -2986,6 +2901,7 @@ resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba,
 	unsigned long iflags;
 	unsigned long long i;
 	int ret;
+	u64 lba_off;
 
 	ret = check_device_access_params(scp, lba, num);
 	if (ret)
@@ -2998,31 +2914,29 @@ resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba,
 		goto out;
 	}
 
+	lba_off = lba * sdebug_sector_size;
 	/* if ndob then zero 1 logical block, else fetch 1 logical block */
 	if (ndob) {
-		memset(fake_storep + (lba * scsi_debug_sector_size), 0,
-		       scsi_debug_sector_size);
+		memset(fake_storep + lba_off, 0, sdebug_sector_size);
 		ret = 0;
 	} else
-		ret = fetch_to_dev_buffer(scp, fake_storep +
-					       (lba * scsi_debug_sector_size),
-					  scsi_debug_sector_size);
+		ret = fetch_to_dev_buffer(scp, fake_storep + lba_off,
+					  sdebug_sector_size);
 
 	if (-1 == ret) {
 		write_unlock_irqrestore(&atomic_rw, iflags);
-		return (DID_ERROR << 16);
-	} else if ((ret < (num * scsi_debug_sector_size)) &&
-		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+		return DID_ERROR << 16;
+	} else if (sdebug_verbose && (ret < (num * sdebug_sector_size)))
 		sdev_printk(KERN_INFO, scp->device,
 			    "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
 			    my_name, "write same",
-			    num * scsi_debug_sector_size, ret);
+			    num * sdebug_sector_size, ret);
 
 	/* Copy first sector to remaining blocks */
 	for (i = 1 ; i < num ; i++)
-		memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size),
-		       fake_storep + (lba * scsi_debug_sector_size),
-		       scsi_debug_sector_size);
+		memcpy(fake_storep + ((lba + i) * sdebug_sector_size),
+		       fake_storep + lba_off,
+		       sdebug_sector_size);
 
 	if (scsi_debug_lbp())
 		map_region(lba, num);
@@ -3042,7 +2956,7 @@ resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	bool unmap = false;
 
 	if (cmd[1] & 0x8) {
-		if (scsi_debug_lbpws10 == 0) {
+		if (sdebug_lbpws10 == 0) {
 			mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
 			return check_condition_result;
 		} else
@@ -3050,7 +2964,7 @@ resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	}
 	lba = get_unaligned_be32(cmd + 2);
 	num = get_unaligned_be16(cmd + 7);
-	if (num > scsi_debug_write_same_length) {
+	if (num > sdebug_write_same_length) {
 		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
 		return check_condition_result;
 	}
@@ -3068,7 +2982,7 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	bool ndob = false;
 
 	if (cmd[1] & 0x8) {	/* UNMAP */
-		if (scsi_debug_lbpws == 0) {
+		if (sdebug_lbpws == 0) {
 			mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
 			return check_condition_result;
 		} else
@@ -3078,7 +2992,7 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		ndob = true;
 	lba = get_unaligned_be64(cmd + 2);
 	num = get_unaligned_be32(cmd + 10);
-	if (num > scsi_debug_write_same_length) {
+	if (num > sdebug_write_same_length) {
 		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1);
 		return check_condition_result;
 	}
@@ -3142,7 +3056,7 @@ resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	u8 *fake_storep_hold;
 	u64 lba;
 	u32 dnum;
-	u32 lb_size = scsi_debug_sector_size;
+	u32 lb_size = sdebug_sector_size;
 	u8 num;
 	unsigned long iflags;
 	int ret;
@@ -3152,13 +3066,13 @@ resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	num = cmd[13];		/* 1 to a maximum of 255 logical blocks */
 	if (0 == num)
 		return 0;	/* degenerate case, not an error */
-	if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+	if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
 	    (cmd[1] & 0xe0)) {
 		mk_sense_invalid_opcode(scp);
 		return check_condition_result;
 	}
-	if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
-	     scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
+	if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION ||
+	     sdebug_dif == SD_DIF_TYPE3_PROTECTION) &&
 	    (cmd[1] & 0xe0) == 0)
 		sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
 			    "to DIF device\n");
@@ -3193,8 +3107,7 @@ resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	if (ret == -1) {
 		retval = DID_ERROR << 16;
 		goto cleanup;
-	} else if ((ret < (dnum * lb_size)) &&
-		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+	} else if (sdebug_verbose && (ret < (dnum * lb_size)))
 		sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb "
 			    "indicated=%u, IO sent=%d bytes\n", my_name,
 			    dnum * lb_size, ret);
@@ -3233,7 +3146,7 @@ resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	BUG_ON(scsi_bufflen(scp) != payload_len);
 
 	descriptors = (payload_len - 8) / 16;
-	if (descriptors > scsi_debug_unmap_max_desc) {
+	if (descriptors > sdebug_unmap_max_desc) {
 		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
 		return check_condition_result;
 	}
@@ -3339,10 +3252,10 @@ static int resp_report_luns(struct scsi_cmnd * scp,
 	}
 	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
 	memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
-	lun_cnt = scsi_debug_max_luns;
+	lun_cnt = sdebug_max_luns;
 	if (1 == select_report)
 		lun_cnt = 0;
-	else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
+	else if (sdebug_no_lun_0 && (lun_cnt > 0))
 		--lun_cnt;
 	want_wlun = (select_report > 0) ? 1 : 0;
 	num = lun_cnt + want_wlun;
@@ -3356,7 +3269,7 @@ static int resp_report_luns(struct scsi_cmnd * scp,
 	}
 	one_lun = (struct scsi_lun *) &arr[8];
 	max_addr = arr + SDEBUG_RLUN_ARR_SZ;
-	for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
+	for (i = 0, lun = (sdebug_no_lun_0 ? 1 : 0);
              ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
 	     i++, lun++) {
 		upper = (lun >> 8) & 0x3f;
@@ -3486,7 +3399,7 @@ static void sdebug_q_cmd_complete(unsigned long indx)
 			return;
 		}
 		k = find_last_bit(queued_in_use_bm, retval);
-		if ((k < scsi_debug_max_queue) || (k == retval))
+		if ((k < sdebug_max_queue) || (k == retval))
 			atomic_set(&retired_max_queue, 0);
 		else
 			atomic_set(&retired_max_queue, k + 1);
@@ -3546,7 +3459,7 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
 			goto the_end;
 		}
 		k = find_last_bit(queued_in_use_bm, retval);
-		if ((k < scsi_debug_max_queue) || (k == retval))
+		if ((k < sdebug_max_queue) || (k == retval))
 			atomic_set(&retired_max_queue, 0);
 		else
 			atomic_set(&retired_max_queue, k + 1);
@@ -3614,7 +3527,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
 
 static int scsi_debug_slave_alloc(struct scsi_device *sdp)
 {
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+	if (sdebug_verbose)
 		pr_info("slave_alloc <%u %u %u %llu>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
@@ -3625,7 +3538,7 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp)
 {
 	struct sdebug_dev_info *devip;
 
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+	if (sdebug_verbose)
 		pr_info("slave_configure <%u %u %u %llu>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
@@ -3635,7 +3548,7 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp)
 		return 1;	/* no resources, will be marked offline */
 	sdp->hostdata = devip;
 	blk_queue_max_segment_size(sdp->request_queue, -1U);
-	if (scsi_debug_no_uld)
+	if (sdebug_no_uld)
 		sdp->no_uld_attach = 1;
 	return 0;
 }
@@ -3645,7 +3558,7 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp)
 	struct sdebug_dev_info *devip =
 		(struct sdebug_dev_info *)sdp->hostdata;
 
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+	if (sdebug_verbose)
 		pr_info("slave_destroy <%u %u %u %llu>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (devip) {
@@ -3664,7 +3577,7 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
 	struct sdebug_dev_info *devip;
 
 	spin_lock_irqsave(&queued_arr_lock, iflags);
-	qmax = scsi_debug_max_queue;
+	qmax = sdebug_max_queue;
 	r_qmax = atomic_read(&retired_max_queue);
 	if (r_qmax > qmax)
 		qmax = r_qmax;
@@ -3679,15 +3592,15 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
 				sqcp->a_cmnd = NULL;
 				spin_unlock_irqrestore(&queued_arr_lock,
 						       iflags);
-				if (scsi_debug_ndelay > 0) {
+				if (sdebug_ndelay > 0) {
 					if (sqcp->sd_hrtp)
 						hrtimer_cancel(
 							&sqcp->sd_hrtp->hrt);
-				} else if (scsi_debug_delay > 0) {
+				} else if (sdebug_delay > 0) {
 					if (sqcp->cmnd_timerp)
 						del_timer_sync(
 							sqcp->cmnd_timerp);
-				} else if (scsi_debug_delay < 0) {
+				} else if (sdebug_delay < 0) {
 					if (sqcp->tletp)
 						tasklet_kill(sqcp->tletp);
 				}
@@ -3720,15 +3633,15 @@ static void stop_all_queued(void)
 				sqcp->a_cmnd = NULL;
 				spin_unlock_irqrestore(&queued_arr_lock,
 						       iflags);
-				if (scsi_debug_ndelay > 0) {
+				if (sdebug_ndelay > 0) {
 					if (sqcp->sd_hrtp)
 						hrtimer_cancel(
 							&sqcp->sd_hrtp->hrt);
-				} else if (scsi_debug_delay > 0) {
+				} else if (sdebug_delay > 0) {
 					if (sqcp->cmnd_timerp)
 						del_timer_sync(
 							sqcp->cmnd_timerp);
-				} else if (scsi_debug_delay < 0) {
+				} else if (sdebug_delay < 0) {
 					if (sqcp->tletp)
 						tasklet_kill(sqcp->tletp);
 				}
@@ -3765,7 +3678,7 @@ static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
 	++num_aborts;
 	if (SCpnt) {
 		if (SCpnt->device &&
-		    (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
+		    (SDEBUG_OPT_ALL_NOISE & sdebug_opts))
 			sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
 				    __func__);
 		stop_queued_cmnd(SCpnt);
@@ -3781,7 +3694,7 @@ static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
 	if (SCpnt && SCpnt->device) {
 		struct scsi_device *sdp = SCpnt->device;
 
-		if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
+		if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
 			sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
 		devip = devInfoReg(sdp);
 		if (devip)
@@ -3804,7 +3717,7 @@ static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
 	sdp = SCpnt->device;
 	if (!sdp)
 		goto lie;
-	if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
+	if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
 		sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
 	hp = sdp->host;
 	if (!hp)
@@ -3819,7 +3732,7 @@ static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
 				++k;
 			}
 	}
-	if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
+	if (SDEBUG_OPT_RESET_NOISE & sdebug_opts)
 		sdev_printk(KERN_INFO, sdp,
 			    "%s: %d device(s) found in target\n", __func__, k);
 lie:
@@ -3838,7 +3751,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
 	if (!(SCpnt && SCpnt->device))
 		goto lie;
 	sdp = SCpnt->device;
-	if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)
+	if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
 		sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
 	hp = sdp->host;
 	if (hp) {
@@ -3852,7 +3765,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
 			}
 		}
 	}
-	if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
+	if (SDEBUG_OPT_RESET_NOISE & sdebug_opts)
 		sdev_printk(KERN_INFO, sdp,
 			    "%s: %d device(s) found in host\n", __func__, k);
 lie:
@@ -3866,7 +3779,7 @@ static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
 	int k = 0;
 
 	++num_host_resets;
-	if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts))
+	if ((SCpnt->device) && (SDEBUG_OPT_ALL_NOISE & sdebug_opts))
 		sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
         spin_lock(&sdebug_host_list_lock);
         list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
@@ -3878,7 +3791,7 @@ static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
         }
         spin_unlock(&sdebug_host_list_lock);
 	stop_all_queued();
-	if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts)
+	if (SDEBUG_OPT_RESET_NOISE & sdebug_opts)
 		sdev_printk(KERN_INFO, SCpnt->device,
 			    "%s: %d device(s) found\n", __func__, k);
 	return SUCCESS;
@@ -3893,22 +3806,22 @@ static void __init sdebug_build_parts(unsigned char *ramp,
 	int heads_by_sects, start_sec, end_sec;
 
 	/* assume partition table already zeroed */
-	if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
+	if ((sdebug_num_parts < 1) || (store_size < 1048576))
 		return;
-	if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
-		scsi_debug_num_parts = SDEBUG_MAX_PARTS;
+	if (sdebug_num_parts > SDEBUG_MAX_PARTS) {
+		sdebug_num_parts = SDEBUG_MAX_PARTS;
 		pr_warn("reducing partitions to %d\n", SDEBUG_MAX_PARTS);
 	}
 	num_sectors = (int)sdebug_store_sectors;
 	sectors_per_part = (num_sectors - sdebug_sectors_per)
-			   / scsi_debug_num_parts;
+			   / sdebug_num_parts;
 	heads_by_sects = sdebug_heads * sdebug_sectors_per;
         starts[0] = sdebug_sectors_per;
-	for (k = 1; k < scsi_debug_num_parts; ++k)
+	for (k = 1; k < sdebug_num_parts; ++k)
 		starts[k] = ((k * sectors_per_part) / heads_by_sects)
 			    * heads_by_sects;
-	starts[scsi_debug_num_parts] = num_sectors;
-	starts[scsi_debug_num_parts + 1] = 0;
+	starts[sdebug_num_parts] = num_sectors;
+	starts[sdebug_num_parts + 1] = 0;
 
 	ramp[510] = 0x55;	/* magic partition markings */
 	ramp[511] = 0xAA;
@@ -3955,7 +3868,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 
 	sdp = cmnd->device;
 
-	if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+	if (sdebug_verbose && scsi_result)
 		sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
 			    __func__, scsi_result);
 	if (delta_jiff == 0)
@@ -3972,29 +3885,29 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 			goto respond_in_thread;
 		} else
 			scsi_result = device_qfull_result;
-	} else if ((scsi_debug_every_nth != 0) &&
-		   (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) &&
+	} else if ((sdebug_every_nth != 0) &&
+		   (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
 		   (scsi_result == 0)) {
 		if ((num_in_q == (qdepth - 1)) &&
 		    (atomic_inc_return(&sdebug_a_tsf) >=
-		     abs(scsi_debug_every_nth))) {
+		     abs(sdebug_every_nth))) {
 			atomic_set(&sdebug_a_tsf, 0);
 			inject = 1;
 			scsi_result = device_qfull_result;
 		}
 	}
 
-	k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue);
-	if (k >= scsi_debug_max_queue) {
+	k = find_first_zero_bit(queued_in_use_bm, sdebug_max_queue);
+	if (k >= sdebug_max_queue) {
 		spin_unlock_irqrestore(&queued_arr_lock, iflags);
 		if (scsi_result)
 			goto respond_in_thread;
-		else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts)
+		else if (SDEBUG_OPT_ALL_TSF & sdebug_opts)
 			scsi_result = device_qfull_result;
-		if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)
+		if (SDEBUG_OPT_Q_NOISE & sdebug_opts)
 			sdev_printk(KERN_INFO, sdp,
 				    "%s: max_queue=%d exceeded, %s\n",
-				    __func__, scsi_debug_max_queue,
+				    __func__, sdebug_max_queue,
 				    (scsi_result ?  "status: TASK SET FULL" :
 						    "report: host busy"));
 		if (scsi_result)
@@ -4020,8 +3933,8 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 		sqcp->cmnd_timerp->data = k;
 		sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
 		add_timer(sqcp->cmnd_timerp);
-	} else if (scsi_debug_ndelay > 0) {
-		ktime_t kt = ktime_set(0, scsi_debug_ndelay);
+	} else if (sdebug_ndelay > 0) {
+		ktime_t kt = ktime_set(0, sdebug_ndelay);
 		struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
 
 		if (NULL == sd_hp) {
@@ -4049,7 +3962,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 		else
 			tasklet_schedule(sqcp->tletp);
 	}
-	if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) &&
+	if ((SDEBUG_OPT_Q_NOISE & sdebug_opts) &&
 	    (scsi_result == device_qfull_result))
 		sdev_printk(KERN_INFO, sdp,
 			    "%s: num_in_q=%d +1, %s%s\n", __func__,
@@ -4069,46 +3982,46 @@ respond_in_thread:	/* call back to mid-layer using invocation thread */
    as it can when the corresponding attribute in the
    /sys/bus/pseudo/drivers/scsi_debug directory is changed.
  */
-module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
-module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
-module_param_named(clustering, scsi_debug_clustering, bool, S_IRUGO | S_IWUSR);
-module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
-module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
-module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
-module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
-module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
-module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
-module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
-module_param_named(guard, scsi_debug_guard, uint, S_IRUGO);
-module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR);
-module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
-module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
-module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
-module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO);
-module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
-module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
-module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
-module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR);
-module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
-module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
-module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
-module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
-module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
-module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
-module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
-module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
-module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR);
-module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
-module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
-module_param_named(strict, scsi_debug_strict, bool, S_IRUGO | S_IWUSR);
-module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
-module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
-module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
-module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
-module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
-module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
+module_param_named(add_host, sdebug_add_host, int, S_IRUGO | S_IWUSR);
+module_param_named(ato, sdebug_ato, int, S_IRUGO);
+module_param_named(clustering, sdebug_clustering, bool, S_IRUGO | S_IWUSR);
+module_param_named(delay, sdebug_delay, int, S_IRUGO | S_IWUSR);
+module_param_named(dev_size_mb, sdebug_dev_size_mb, int, S_IRUGO);
+module_param_named(dif, sdebug_dif, int, S_IRUGO);
+module_param_named(dix, sdebug_dix, int, S_IRUGO);
+module_param_named(dsense, sdebug_dsense, int, S_IRUGO | S_IWUSR);
+module_param_named(every_nth, sdebug_every_nth, int, S_IRUGO | S_IWUSR);
+module_param_named(fake_rw, sdebug_fake_rw, int, S_IRUGO | S_IWUSR);
+module_param_named(guard, sdebug_guard, uint, S_IRUGO);
+module_param_named(host_lock, sdebug_host_lock, bool, S_IRUGO | S_IWUSR);
+module_param_named(lbpu, sdebug_lbpu, int, S_IRUGO);
+module_param_named(lbpws, sdebug_lbpws, int, S_IRUGO);
+module_param_named(lbpws10, sdebug_lbpws10, int, S_IRUGO);
+module_param_named(lbprz, sdebug_lbprz, int, S_IRUGO);
+module_param_named(lowest_aligned, sdebug_lowest_aligned, int, S_IRUGO);
+module_param_named(max_luns, sdebug_max_luns, int, S_IRUGO | S_IWUSR);
+module_param_named(max_queue, sdebug_max_queue, int, S_IRUGO | S_IWUSR);
+module_param_named(ndelay, sdebug_ndelay, int, S_IRUGO | S_IWUSR);
+module_param_named(no_lun_0, sdebug_no_lun_0, int, S_IRUGO | S_IWUSR);
+module_param_named(no_uld, sdebug_no_uld, int, S_IRUGO);
+module_param_named(num_parts, sdebug_num_parts, int, S_IRUGO);
+module_param_named(num_tgts, sdebug_num_tgts, int, S_IRUGO | S_IWUSR);
+module_param_named(opt_blks, sdebug_opt_blks, int, S_IRUGO);
+module_param_named(opts, sdebug_opts, int, S_IRUGO | S_IWUSR);
+module_param_named(physblk_exp, sdebug_physblk_exp, int, S_IRUGO);
+module_param_named(ptype, sdebug_ptype, int, S_IRUGO | S_IWUSR);
+module_param_named(removable, sdebug_removable, bool, S_IRUGO | S_IWUSR);
+module_param_named(scsi_level, sdebug_scsi_level, int, S_IRUGO);
+module_param_named(sector_size, sdebug_sector_size, int, S_IRUGO);
+module_param_named(strict, sdebug_strict, bool, S_IRUGO | S_IWUSR);
+module_param_named(unmap_alignment, sdebug_unmap_alignment, int, S_IRUGO);
+module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO);
+module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO);
+module_param_named(unmap_max_desc, sdebug_unmap_max_desc, int, S_IRUGO);
+module_param_named(virtual_gb, sdebug_virtual_gb, int, S_IRUGO | S_IWUSR);
+module_param_named(vpd_use_hostno, sdebug_vpd_use_hostno, int,
 		   S_IRUGO | S_IWUSR);
-module_param_named(write_same_length, scsi_debug_write_same_length, int,
+module_param_named(write_same_length, sdebug_write_same_length, int,
 		   S_IRUGO | S_IWUSR);
 
 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
@@ -4162,8 +4075,7 @@ static const char * scsi_debug_info(struct Scsi_Host * shp)
 {
 	sprintf(sdebug_info, "scsi_debug, version %s [%s], "
 		"dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
-		scsi_debug_version_date, scsi_debug_dev_size_mb,
-		scsi_debug_opts);
+		sdebug_version_date, sdebug_dev_size_mb, sdebug_opts);
 	return sdebug_info;
 }
 
@@ -4180,8 +4092,10 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int lengt
 	arr[minLen] = '\0';
 	if (1 != sscanf(arr, "%d", &opts))
 		return -EINVAL;
-	scsi_debug_opts = opts;
-	if (scsi_debug_every_nth != 0)
+	sdebug_opts = opts;
+	sdebug_verbose = !!(SDEBUG_OPT_NOISE & opts);
+	sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & opts);
+	if (sdebug_every_nth != 0)
 		atomic_set(&sdebug_cmnd_count, 0);
 	return length;
 }
@@ -4194,9 +4108,9 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
 	int f, l;
 	char b[32];
 
-	if (scsi_debug_every_nth > 0)
+	if (sdebug_every_nth > 0)
 		snprintf(b, sizeof(b), " (curr:%d)",
-			 ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ?
+			 ((SDEBUG_OPT_RARE_TSF & sdebug_opts) ?
 				atomic_read(&sdebug_a_tsf) :
 				atomic_read(&sdebug_cmnd_count)));
 	else
@@ -4210,18 +4124,18 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
 		"command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
 		"host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
 		"usec_in_jiffy=%lu\n",
-		SCSI_DEBUG_VERSION, scsi_debug_version_date,
-		scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts,
-		scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay,
-		scsi_debug_max_luns, atomic_read(&sdebug_completions),
-		scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
+		SCSI_DEBUG_VERSION, sdebug_version_date,
+		sdebug_num_tgts, sdebug_dev_size_mb, sdebug_opts,
+		sdebug_every_nth, b, sdebug_delay, sdebug_ndelay,
+		sdebug_max_luns, atomic_read(&sdebug_completions),
+		sdebug_sector_size, sdebug_cylinders_per, sdebug_heads,
 		sdebug_sectors_per, num_aborts, num_dev_resets,
 		num_target_resets, num_bus_resets, num_host_resets,
 		dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
 
-	f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue);
-	if (f != scsi_debug_max_queue) {
-		l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue);
+	f = find_first_bit(queued_in_use_bm, sdebug_max_queue);
+	if (f != sdebug_max_queue) {
+		l = find_last_bit(queued_in_use_bm, sdebug_max_queue);
 		seq_printf(m, "   %s BUSY: first,last bits set: %d,%d\n",
 			   "queued_in_use_bm", f, l);
 	}
@@ -4230,7 +4144,7 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
 
 static ssize_t delay_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_delay);
 }
 /* Returns -EBUSY if delay is being changed and commands are queued */
 static ssize_t delay_store(struct device_driver *ddp, const char *buf,
@@ -4240,18 +4154,17 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf,
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
 		res = count;
-		if (scsi_debug_delay != delay) {
+		if (sdebug_delay != delay) {
 			unsigned long iflags;
 			int k;
 
 			spin_lock_irqsave(&queued_arr_lock, iflags);
-			k = find_first_bit(queued_in_use_bm,
-					   scsi_debug_max_queue);
-			if (k != scsi_debug_max_queue)
+			k = find_first_bit(queued_in_use_bm, sdebug_max_queue);
+			if (k != sdebug_max_queue)
 				res = -EBUSY;	/* have queued commands */
 			else {
-				scsi_debug_delay = delay;
-				scsi_debug_ndelay = 0;
+				sdebug_delay = delay;
+				sdebug_ndelay = 0;
 			}
 			spin_unlock_irqrestore(&queued_arr_lock, iflags);
 		}
@@ -4263,10 +4176,10 @@ static DRIVER_ATTR_RW(delay);
 
 static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_ndelay);
 }
 /* Returns -EBUSY if ndelay is being changed and commands are queued */
-/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */
+/* If > 0 and accepted then sdebug_delay is set to DELAY_OVERRIDDEN */
 static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
 			   size_t count)
 {
@@ -4276,15 +4189,14 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
 	if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
 	    (ndelay >= 0) && (ndelay < 1000000000)) {
 		res = count;
-		if (scsi_debug_ndelay != ndelay) {
+		if (sdebug_ndelay != ndelay) {
 			spin_lock_irqsave(&queued_arr_lock, iflags);
-			k = find_first_bit(queued_in_use_bm,
-					   scsi_debug_max_queue);
-			if (k != scsi_debug_max_queue)
+			k = find_first_bit(queued_in_use_bm, sdebug_max_queue);
+			if (k != sdebug_max_queue)
 				res = -EBUSY;	/* have queued commands */
 			else {
-				scsi_debug_ndelay = ndelay;
-				scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN
+				sdebug_ndelay = ndelay;
+				sdebug_delay = ndelay ? DELAY_OVERRIDDEN
 							  : DEF_DELAY;
 			}
 			spin_unlock_irqrestore(&queued_arr_lock, iflags);
@@ -4297,7 +4209,7 @@ static DRIVER_ATTR_RW(ndelay);
 
 static ssize_t opts_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
+	return scnprintf(buf, PAGE_SIZE, "0x%x\n", sdebug_opts);
 }
 
 static ssize_t opts_store(struct device_driver *ddp, const char *buf,
@@ -4317,17 +4229,9 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf,
 	}
 	return -EINVAL;
 opts_done:
-	scsi_debug_opts = opts;
-	if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
-		sdebug_any_injecting_opt = true;
-	else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
-		sdebug_any_injecting_opt = true;
-	else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
-		sdebug_any_injecting_opt = true;
-	else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
-		sdebug_any_injecting_opt = true;
-	else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
-		sdebug_any_injecting_opt = true;
+	sdebug_opts = opts;
+	sdebug_verbose = !!(SDEBUG_OPT_NOISE & opts);
+	sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & opts);
 	atomic_set(&sdebug_cmnd_count, 0);
 	atomic_set(&sdebug_a_tsf, 0);
 	return count;
@@ -4336,7 +4240,7 @@ static DRIVER_ATTR_RW(opts);
 
 static ssize_t ptype_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_ptype);
 }
 static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
 			   size_t count)
@@ -4344,7 +4248,7 @@ static ssize_t ptype_store(struct device_driver *ddp, const char *buf,
         int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		scsi_debug_ptype = n;
+		sdebug_ptype = n;
 		return count;
 	}
 	return -EINVAL;
@@ -4353,7 +4257,7 @@ static DRIVER_ATTR_RW(ptype);
 
 static ssize_t dsense_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dsense);
 }
 static ssize_t dsense_store(struct device_driver *ddp, const char *buf,
 			    size_t count)
@@ -4361,7 +4265,7 @@ static ssize_t dsense_store(struct device_driver *ddp, const char *buf,
         int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		scsi_debug_dsense = n;
+		sdebug_dsense = n;
 		return count;
 	}
 	return -EINVAL;
@@ -4370,7 +4274,7 @@ static DRIVER_ATTR_RW(dsense);
 
 static ssize_t fake_rw_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_fake_rw);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_fake_rw);
 }
 static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
 			     size_t count)
@@ -4379,11 +4283,11 @@ static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
 		n = (n > 0);
-		scsi_debug_fake_rw = (scsi_debug_fake_rw > 0);
-		if (scsi_debug_fake_rw != n) {
+		sdebug_fake_rw = (sdebug_fake_rw > 0);
+		if (sdebug_fake_rw != n) {
 			if ((0 == n) && (NULL == fake_storep)) {
 				unsigned long sz =
-					(unsigned long)scsi_debug_dev_size_mb *
+					(unsigned long)sdebug_dev_size_mb *
 					1048576;
 
 				fake_storep = vmalloc(sz);
@@ -4393,7 +4297,7 @@ static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
 				}
 				memset(fake_storep, 0, sz);
 			}
-			scsi_debug_fake_rw = n;
+			sdebug_fake_rw = n;
 		}
 		return count;
 	}
@@ -4403,7 +4307,7 @@ static DRIVER_ATTR_RW(fake_rw);
 
 static ssize_t no_lun_0_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_no_lun_0);
 }
 static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf,
 			      size_t count)
@@ -4411,7 +4315,7 @@ static ssize_t no_lun_0_store(struct device_driver *ddp, const char *buf,
         int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		scsi_debug_no_lun_0 = n;
+		sdebug_no_lun_0 = n;
 		return count;
 	}
 	return -EINVAL;
@@ -4420,7 +4324,7 @@ static DRIVER_ATTR_RW(no_lun_0);
 
 static ssize_t num_tgts_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_num_tgts);
 }
 static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf,
 			      size_t count)
@@ -4428,7 +4332,7 @@ static ssize_t num_tgts_store(struct device_driver *ddp, const char *buf,
         int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		scsi_debug_num_tgts = n;
+		sdebug_num_tgts = n;
 		sdebug_max_tgts_luns();
 		return count;
 	}
@@ -4438,19 +4342,19 @@ static DRIVER_ATTR_RW(num_tgts);
 
 static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dev_size_mb);
 }
 static DRIVER_ATTR_RO(dev_size_mb);
 
 static ssize_t num_parts_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_num_parts);
 }
 static DRIVER_ATTR_RO(num_parts);
 
 static ssize_t every_nth_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_every_nth);
 }
 static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
 			       size_t count)
@@ -4458,7 +4362,7 @@ static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
         int nth;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
-		scsi_debug_every_nth = nth;
+		sdebug_every_nth = nth;
 		atomic_set(&sdebug_cmnd_count, 0);
 		return count;
 	}
@@ -4468,7 +4372,7 @@ static DRIVER_ATTR_RW(every_nth);
 
 static ssize_t max_luns_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_max_luns);
 }
 static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
 			      size_t count)
@@ -4477,10 +4381,10 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
 	bool changed;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		changed = (scsi_debug_max_luns != n);
-		scsi_debug_max_luns = n;
+		changed = (sdebug_max_luns != n);
+		sdebug_max_luns = n;
 		sdebug_max_tgts_luns();
-		if (changed && (scsi_debug_scsi_level >= 5)) {	/* >= SPC-3 */
+		if (changed && (sdebug_scsi_level >= 5)) {	/* >= SPC-3 */
 			struct sdebug_host_info *sdhp;
 			struct sdebug_dev_info *dp;
 
@@ -4503,7 +4407,7 @@ static DRIVER_ATTR_RW(max_luns);
 
 static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_max_queue);
 }
 /* N.B. max_queue can be changed while there are queued commands. In flight
  * commands beyond the new max_queue will be completed. */
@@ -4517,7 +4421,7 @@ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
 	    (n <= SCSI_DEBUG_CANQUEUE)) {
 		spin_lock_irqsave(&queued_arr_lock, iflags);
 		k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
-		scsi_debug_max_queue = n;
+		sdebug_max_queue = n;
 		if (SCSI_DEBUG_CANQUEUE == k)
 			atomic_set(&retired_max_queue, 0);
 		else if (k >= n)
@@ -4533,19 +4437,19 @@ static DRIVER_ATTR_RW(max_queue);
 
 static ssize_t no_uld_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_uld);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_no_uld);
 }
 static DRIVER_ATTR_RO(no_uld);
 
 static ssize_t scsi_level_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_scsi_level);
 }
 static DRIVER_ATTR_RO(scsi_level);
 
 static ssize_t virtual_gb_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_virtual_gb);
 }
 static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
 				size_t count)
@@ -4554,8 +4458,8 @@ static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
 	bool changed;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		changed = (scsi_debug_virtual_gb != n);
-		scsi_debug_virtual_gb = n;
+		changed = (sdebug_virtual_gb != n);
+		sdebug_virtual_gb = n;
 		sdebug_capacity = get_sdebug_capacity();
 		if (changed) {
 			struct sdebug_host_info *sdhp;
@@ -4580,7 +4484,7 @@ static DRIVER_ATTR_RW(virtual_gb);
 
 static ssize_t add_host_show(struct device_driver *ddp, char *buf)
 {
-        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_add_host);
 }
 
 static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
@@ -4605,7 +4509,7 @@ static DRIVER_ATTR_RW(add_host);
 
 static ssize_t vpd_use_hostno_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_vpd_use_hostno);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_vpd_use_hostno);
 }
 static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
 				    size_t count)
@@ -4613,7 +4517,7 @@ static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
 	int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		scsi_debug_vpd_use_hostno = n;
+		sdebug_vpd_use_hostno = n;
 		return count;
 	}
 	return -EINVAL;
@@ -4622,31 +4526,31 @@ static DRIVER_ATTR_RW(vpd_use_hostno);
 
 static ssize_t sector_size_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", sdebug_sector_size);
 }
 static DRIVER_ATTR_RO(sector_size);
 
 static ssize_t dix_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dix);
 }
 static DRIVER_ATTR_RO(dix);
 
 static ssize_t dif_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dif);
 }
 static DRIVER_ATTR_RO(dif);
 
 static ssize_t guard_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", sdebug_guard);
 }
 static DRIVER_ATTR_RO(guard);
 
 static ssize_t ato_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_ato);
 }
 static DRIVER_ATTR_RO(ato);
 
@@ -4669,7 +4573,7 @@ static DRIVER_ATTR_RO(map);
 
 static ssize_t removable_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_removable ? 1 : 0);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_removable ? 1 : 0);
 }
 static ssize_t removable_store(struct device_driver *ddp, const char *buf,
 			       size_t count)
@@ -4677,7 +4581,7 @@ static ssize_t removable_store(struct device_driver *ddp, const char *buf,
 	int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		scsi_debug_removable = (n > 0);
+		sdebug_removable = (n > 0);
 		return count;
 	}
 	return -EINVAL;
@@ -4686,7 +4590,7 @@ static DRIVER_ATTR_RW(removable);
 
 static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", !!sdebug_host_lock);
 }
 /* Returns -EBUSY if host_lock is being changed and commands are queued */
 static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
@@ -4698,17 +4602,17 @@ static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
 		bool new_host_lock = (n > 0);
 
 		res = count;
-		if (new_host_lock != scsi_debug_host_lock) {
+		if (new_host_lock != sdebug_host_lock) {
 			unsigned long iflags;
 			int k;
 
 			spin_lock_irqsave(&queued_arr_lock, iflags);
 			k = find_first_bit(queued_in_use_bm,
-					   scsi_debug_max_queue);
-			if (k != scsi_debug_max_queue)
+					   sdebug_max_queue);
+			if (k != sdebug_max_queue)
 				res = -EBUSY;	/* have queued commands */
 			else
-				scsi_debug_host_lock = new_host_lock;
+				sdebug_host_lock = new_host_lock;
 			spin_unlock_irqrestore(&queued_arr_lock, iflags);
 		}
 		return res;
@@ -4719,7 +4623,7 @@ static DRIVER_ATTR_RW(host_lock);
 
 static ssize_t strict_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_strict);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", !!sdebug_strict);
 }
 static ssize_t strict_store(struct device_driver *ddp, const char *buf,
 			    size_t count)
@@ -4727,7 +4631,7 @@ static ssize_t strict_store(struct device_driver *ddp, const char *buf,
 	int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		scsi_debug_strict = (n > 0);
+		sdebug_strict = (n > 0);
 		return count;
 	}
 	return -EINVAL;
@@ -4787,24 +4691,24 @@ static int __init scsi_debug_init(void)
 	atomic_set(&sdebug_completions, 0);
 	atomic_set(&retired_max_queue, 0);
 
-	if (scsi_debug_ndelay >= 1000000000) {
+	if (sdebug_ndelay >= 1000 * 1000 * 1000) {
 		pr_warn("ndelay must be less than 1 second, ignored\n");
-		scsi_debug_ndelay = 0;
-	} else if (scsi_debug_ndelay > 0)
-		scsi_debug_delay = DELAY_OVERRIDDEN;
+		sdebug_ndelay = 0;
+	} else if (sdebug_ndelay > 0)
+		sdebug_delay = DELAY_OVERRIDDEN;
 
-	switch (scsi_debug_sector_size) {
+	switch (sdebug_sector_size) {
 	case  512:
 	case 1024:
 	case 2048:
 	case 4096:
 		break;
 	default:
-		pr_err("invalid sector_size %d\n", scsi_debug_sector_size);
+		pr_err("invalid sector_size %d\n", sdebug_sector_size);
 		return -EINVAL;
 	}
 
-	switch (scsi_debug_dif) {
+	switch (sdebug_dif) {
 
 	case SD_DIF_TYPE0_PROTECTION:
 	case SD_DIF_TYPE1_PROTECTION:
@@ -4817,39 +4721,38 @@ static int __init scsi_debug_init(void)
 		return -EINVAL;
 	}
 
-	if (scsi_debug_guard > 1) {
+	if (sdebug_guard > 1) {
 		pr_err("guard must be 0 or 1\n");
 		return -EINVAL;
 	}
 
-	if (scsi_debug_ato > 1) {
+	if (sdebug_ato > 1) {
 		pr_err("ato must be 0 or 1\n");
 		return -EINVAL;
 	}
 
-	if (scsi_debug_physblk_exp > 15) {
-		pr_err("invalid physblk_exp %u\n", scsi_debug_physblk_exp);
+	if (sdebug_physblk_exp > 15) {
+		pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp);
 		return -EINVAL;
 	}
 
-	if (scsi_debug_lowest_aligned > 0x3fff) {
-		pr_err("lowest_aligned too big: %u\n",
-			scsi_debug_lowest_aligned);
+	if (sdebug_lowest_aligned > 0x3fff) {
+		pr_err("lowest_aligned too big: %u\n", sdebug_lowest_aligned);
 		return -EINVAL;
 	}
 
-	if (scsi_debug_dev_size_mb < 1)
-		scsi_debug_dev_size_mb = 1;  /* force minimum 1 MB ramdisk */
-	sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
-	sdebug_store_sectors = sz / scsi_debug_sector_size;
+	if (sdebug_dev_size_mb < 1)
+		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;
 	sdebug_capacity = get_sdebug_capacity();
 
 	/* play around with geometry, don't waste too much on track 0 */
 	sdebug_heads = 8;
 	sdebug_sectors_per = 32;
-	if (scsi_debug_dev_size_mb >= 256)
+	if (sdebug_dev_size_mb >= 256)
 		sdebug_heads = 64;
-	else if (scsi_debug_dev_size_mb >= 16)
+	else if (sdebug_dev_size_mb >= 16)
 		sdebug_heads = 32;
 	sdebug_cylinders_per = (unsigned long)sdebug_capacity /
 			       (sdebug_sectors_per * sdebug_heads);
@@ -4861,18 +4764,18 @@ static int __init scsi_debug_init(void)
 			       (sdebug_sectors_per * sdebug_heads);
 	}
 
-	if (0 == scsi_debug_fake_rw) {
+	if (0 == sdebug_fake_rw) {
 		fake_storep = vmalloc(sz);
 		if (NULL == fake_storep) {
 			pr_err("out of memory, 1\n");
 			return -ENOMEM;
 		}
 		memset(fake_storep, 0, sz);
-		if (scsi_debug_num_parts > 0)
+		if (sdebug_num_parts > 0)
 			sdebug_build_parts(fake_storep, sz);
 	}
 
-	if (scsi_debug_dix) {
+	if (sdebug_dix) {
 		int dif_size;
 
 		dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
@@ -4891,18 +4794,18 @@ static int __init scsi_debug_init(void)
 
 	/* Logical Block Provisioning */
 	if (scsi_debug_lbp()) {
-		scsi_debug_unmap_max_blocks =
-			clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
+		sdebug_unmap_max_blocks =
+			clamp(sdebug_unmap_max_blocks, 0U, 0xffffffffU);
 
-		scsi_debug_unmap_max_desc =
-			clamp(scsi_debug_unmap_max_desc, 0U, 256U);
+		sdebug_unmap_max_desc =
+			clamp(sdebug_unmap_max_desc, 0U, 256U);
 
-		scsi_debug_unmap_granularity =
-			clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
+		sdebug_unmap_granularity =
+			clamp(sdebug_unmap_granularity, 1U, 0xffffffffU);
 
-		if (scsi_debug_unmap_alignment &&
-		    scsi_debug_unmap_granularity <=
-		    scsi_debug_unmap_alignment) {
+		if (sdebug_unmap_alignment &&
+		    sdebug_unmap_granularity <=
+		    sdebug_unmap_alignment) {
 			pr_err("ERR: unmap_granularity <= unmap_alignment\n");
 			return -EINVAL;
 		}
@@ -4921,7 +4824,7 @@ static int __init scsi_debug_init(void)
 		bitmap_zero(map_storep, map_size);
 
 		/* Map first 1KB for partition table */
-		if (scsi_debug_num_parts)
+		if (sdebug_num_parts)
 			map_region(0, 2);
 	}
 
@@ -4942,8 +4845,8 @@ static int __init scsi_debug_init(void)
 		goto bus_unreg;
 	}
 
-	host_to_add = scsi_debug_add_host;
-        scsi_debug_add_host = 0;
+	host_to_add = sdebug_add_host;
+	sdebug_add_host = 0;
 
         for (k = 0; k < host_to_add; k++) {
                 if (sdebug_add_adapter()) {
@@ -4952,8 +4855,8 @@ static int __init scsi_debug_init(void)
                 }
         }
 
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		pr_info("built %d host(s)\n", scsi_debug_add_host);
+	if (sdebug_verbose)
+		pr_info("built %d host(s)\n", sdebug_add_host);
 
 	return 0;
 
@@ -4971,7 +4874,7 @@ free_vm:
 
 static void __exit scsi_debug_exit(void)
 {
-	int k = scsi_debug_add_host;
+	int k = sdebug_add_host;
 
 	stop_all_queued();
 	free_all_queued();
@@ -5011,7 +4914,7 @@ static int sdebug_add_adapter(void)
 
         INIT_LIST_HEAD(&sdbg_host->dev_info_list);
 
-	devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
+	devs_per_host = sdebug_num_tgts * sdebug_max_luns;
         for (k = 0; k < devs_per_host; k++) {
 		sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
 		if (!sdbg_devinfo) {
@@ -5028,14 +4931,14 @@ static int sdebug_add_adapter(void)
         sdbg_host->dev.bus = &pseudo_lld_bus;
         sdbg_host->dev.parent = pseudo_primary;
         sdbg_host->dev.release = &sdebug_release_adapter;
-        dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
+	dev_set_name(&sdbg_host->dev, "adapter%d", sdebug_add_host);
 
         error = device_register(&sdbg_host->dev);
 
         if (error)
 		goto clean;
 
-	++scsi_debug_add_host;
+	++sdebug_add_host;
         return error;
 
 clean:
@@ -5064,8 +4967,8 @@ static void sdebug_remove_adapter(void)
 	if (!sdbg_host)
 		return;
 
-        device_unregister(&sdbg_host->dev);
-        --scsi_debug_add_host;
+	device_unregister(&sdbg_host->dev);
+	--sdebug_add_host;
 }
 
 static int
@@ -5091,7 +4994,7 @@ sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
 		qdepth = SCSI_DEBUG_CANQUEUE + 10;
 	scsi_change_queue_depth(sdev, qdepth);
 
-	if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
+	if (SDEBUG_OPT_Q_NOISE & sdebug_opts) {
 		sdev_printk(KERN_INFO, sdev,
 			    "%s: qdepth=%d, num_in_q=%d\n",
 			    __func__, qdepth, num_in_q);
@@ -5106,28 +5009,25 @@ check_inject(struct scsi_cmnd *scp)
 
 	memset(ep, 0, sizeof(struct sdebug_scmd_extra_t));
 
-	if (atomic_inc_return(&sdebug_cmnd_count) >=
-	    abs(scsi_debug_every_nth)) {
+	if (atomic_inc_return(&sdebug_cmnd_count) >= abs(sdebug_every_nth)) {
 		atomic_set(&sdebug_cmnd_count, 0);
-		if (scsi_debug_every_nth < -1)
-			scsi_debug_every_nth = -1;
-		if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
+		if (sdebug_every_nth < -1)
+			sdebug_every_nth = -1;
+		if (SDEBUG_OPT_TIMEOUT & sdebug_opts)
 			return 1; /* ignore command causing timeout */
-		else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
+		else if (SDEBUG_OPT_MAC_TIMEOUT & sdebug_opts &&
 			 scsi_medium_access_command(scp))
 			return 1; /* time out reads and writes */
 		if (sdebug_any_injecting_opt) {
-			int opts = scsi_debug_opts;
-
-			if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
+			if (SDEBUG_OPT_RECOVERED_ERR & sdebug_opts)
 				ep->inj_recovered = true;
-			else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
+			if (SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts)
 				ep->inj_transport = true;
-			else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
+			if (SDEBUG_OPT_DIF_ERR & sdebug_opts)
 				ep->inj_dif = true;
-			else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
+			if (SDEBUG_OPT_DIX_ERR & sdebug_opts)
 				ep->inj_dix = true;
-			else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
+			if (SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts)
 				ep->inj_short = true;
 		}
 	}
@@ -5146,15 +5046,13 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
 	int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
 	int k, na;
 	int errsts = 0;
-	int errsts_no_connect = DID_NO_CONNECT << 16;
 	u32 flags;
 	u16 sa;
 	u8 opcode = cmd[0];
 	bool has_wlun_rl;
-	bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
 
 	scsi_set_resid(scp, 0);
-	if (debug && !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) {
+	if (sdebug_verbose && !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts)) {
 		char b[120];
 		int n, len, sb;
 
@@ -5170,8 +5068,8 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
 		sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
 	}
 	has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS);
-	if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl)
-		return schedule_resp(scp, NULL, errsts_no_connect, 0);
+	if ((sdp->lun >= sdebug_max_luns) && !has_wlun_rl)
+		return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, 0);
 
 	sdeb_i = opcode_ind_arr[opcode];	/* fully mapped */
 	oip = &opcode_info_arr[sdeb_i];		/* safe if table consistent */
@@ -5179,7 +5077,8 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
 	if (!devip) {
 		devip = devInfoReg(sdp);
 		if (NULL == devip)
-			return schedule_resp(scp, NULL, errsts_no_connect, 0);
+			return schedule_resp(scp, NULL, DID_NO_CONNECT << 16,
+					     0);
 	}
 	na = oip->num_attached;
 	r_pfp = oip->pfp;
@@ -5216,13 +5115,13 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
 		goto check_cond;
 	}
 	if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) {
-		if (debug)
-			sdev_printk(KERN_INFO, sdp, "scsi_debug: Opcode: "
-				    "0x%x not supported for wlun\n", opcode);
+		if (sdebug_verbose)
+			sdev_printk(KERN_INFO, sdp, "%s: Opcode 0x%x not%s\n",
+				    my_name, opcode, " supported for wlun");
 		mk_sense_invalid_opcode(scp);
 		goto check_cond;
 	}
-	if (scsi_debug_strict) {	/* check cdb against mask */
+	if (sdebug_strict) {	/* check cdb against mask */
 		u8 rem;
 		int j;
 
@@ -5246,16 +5145,16 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
 	}
 	if ((F_M_ACCESS & flags) && devip->stopped) {
 		mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
-		if (debug)
+		if (sdebug_verbose)
 			sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
 				    "%s\n", my_name, "initializing command "
 				    "required");
 		errsts = check_condition_result;
 		goto fini;
 	}
-	if (scsi_debug_fake_rw && (F_FAKE_RW & flags))
+	if (sdebug_fake_rw && (F_FAKE_RW & flags))
 		goto fini;
-	if (scsi_debug_every_nth) {
+	if (sdebug_every_nth) {
 		if (check_inject(scp))
 			return 0;	/* ignore command: make trouble */
 	}
@@ -5266,7 +5165,7 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
 
 fini:
 	return schedule_resp(scp, devip, errsts,
-			     ((F_DELAY_OVERR & flags) ? 0 : scsi_debug_delay));
+			     ((F_DELAY_OVERR & flags) ? 0 : sdebug_delay));
 check_cond:
 	return schedule_resp(scp, devip, check_condition_result, 0);
 }
@@ -5274,7 +5173,7 @@ check_cond:
 static int
 sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
 {
-	if (scsi_debug_host_lock) {
+	if (sdebug_host_lock) {
 		unsigned long iflags;
 		int rc;
 
@@ -5317,15 +5216,14 @@ static struct scsi_host_template sdebug_driver_template = {
 static int sdebug_driver_probe(struct device * dev)
 {
 	int error = 0;
-	int opts;
 	struct sdebug_host_info *sdbg_host;
 	struct Scsi_Host *hpnt;
 	int host_prot;
 
 	sdbg_host = to_sdebug_host(dev);
 
-	sdebug_driver_template.can_queue = scsi_debug_max_queue;
-	if (scsi_debug_clustering)
+	sdebug_driver_template.can_queue = sdebug_max_queue;
+	if (sdebug_clustering)
 		sdebug_driver_template.use_clustering = ENABLE_CLUSTERING;
 	hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
 	if (NULL == hpnt) {
@@ -5336,37 +5234,37 @@ static int sdebug_driver_probe(struct device * dev)
 
         sdbg_host->shost = hpnt;
 	*((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
-	if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
-		hpnt->max_id = scsi_debug_num_tgts + 1;
+	if ((hpnt->this_id >= 0) && (sdebug_num_tgts > hpnt->this_id))
+		hpnt->max_id = sdebug_num_tgts + 1;
 	else
-		hpnt->max_id = scsi_debug_num_tgts;
-	/* = scsi_debug_max_luns; */
+		hpnt->max_id = sdebug_num_tgts;
+	/* = sdebug_max_luns; */
 	hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
 
 	host_prot = 0;
 
-	switch (scsi_debug_dif) {
+	switch (sdebug_dif) {
 
 	case SD_DIF_TYPE1_PROTECTION:
 		host_prot = SHOST_DIF_TYPE1_PROTECTION;
-		if (scsi_debug_dix)
+		if (sdebug_dix)
 			host_prot |= SHOST_DIX_TYPE1_PROTECTION;
 		break;
 
 	case SD_DIF_TYPE2_PROTECTION:
 		host_prot = SHOST_DIF_TYPE2_PROTECTION;
-		if (scsi_debug_dix)
+		if (sdebug_dix)
 			host_prot |= SHOST_DIX_TYPE2_PROTECTION;
 		break;
 
 	case SD_DIF_TYPE3_PROTECTION:
 		host_prot = SHOST_DIF_TYPE3_PROTECTION;
-		if (scsi_debug_dix)
+		if (sdebug_dix)
 			host_prot |= SHOST_DIX_TYPE3_PROTECTION;
 		break;
 
 	default:
-		if (scsi_debug_dix)
+		if (sdebug_dix)
 			host_prot |= SHOST_DIX_TYPE0_PROTECTION;
 		break;
 	}
@@ -5382,23 +5280,13 @@ static int sdebug_driver_probe(struct device * dev)
 	       (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
 	       (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
 
-	if (scsi_debug_guard == 1)
+	if (sdebug_guard == 1)
 		scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
 	else
 		scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
 
-	opts = scsi_debug_opts;
-	if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
-		sdebug_any_injecting_opt = true;
-	else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
-		sdebug_any_injecting_opt = true;
-	else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
-		sdebug_any_injecting_opt = true;
-	else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
-		sdebug_any_injecting_opt = true;
-	else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
-		sdebug_any_injecting_opt = true;
-
+	sdebug_verbose = !!(SDEBUG_OPT_NOISE & sdebug_opts);
+	sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & sdebug_opts);
         error = scsi_add_host(hpnt, &sdbg_host->dev);
         if (error) {
 		pr_err("scsi_add_host failed\n");
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 02/12] scsi_debug: ignore host lock option
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
  2016-04-25 16:16 ` [PATCH 01/12] scsi_debug: cleanup naming and bit crunching Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:15   ` Hannes Reinecke
  2016-04-25 16:16 ` [PATCH 03/12] scsi_debug: replace jiffy timers with hr timers Douglas Gilbert
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Remove logic to optionally hold host_lock while each command is
queued. Keep module and sysfs host_lock parameters for backward
compatibility. Note in module parameter description that host_lock
is ignored.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index bc586a4..42e5c37 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -4040,7 +4040,7 @@ MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
 MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
 MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
 MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
-MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)");
+MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)");
 MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
 MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
 MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
@@ -4592,30 +4592,15 @@ static ssize_t host_lock_show(struct device_driver *ddp, char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%d\n", !!sdebug_host_lock);
 }
-/* Returns -EBUSY if host_lock is being changed and commands are queued */
+/* N.B. sdebug_host_lock does nothing, kept for backward compatibility */
 static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
 			       size_t count)
 {
-	int n, res;
+	int n;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
-		bool new_host_lock = (n > 0);
-
-		res = count;
-		if (new_host_lock != sdebug_host_lock) {
-			unsigned long iflags;
-			int k;
-
-			spin_lock_irqsave(&queued_arr_lock, iflags);
-			k = find_first_bit(queued_in_use_bm,
-					   sdebug_max_queue);
-			if (k != sdebug_max_queue)
-				res = -EBUSY;	/* have queued commands */
-			else
-				sdebug_host_lock = new_host_lock;
-			spin_unlock_irqrestore(&queued_arr_lock, iflags);
-		}
-		return res;
+		sdebug_host_lock = (n > 0);
+		return count;
 	}
 	return -EINVAL;
 }
@@ -5035,7 +5020,7 @@ check_inject(struct scsi_cmnd *scp)
 }
 
 static int
-scsi_debug_queuecommand(struct scsi_cmnd *scp)
+scsi_debug_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scp)
 {
 	u8 sdeb_i;
 	struct scsi_device *sdp = scp->device;
@@ -5170,21 +5155,6 @@ check_cond:
 	return schedule_resp(scp, devip, check_condition_result, 0);
 }
 
-static int
-sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
-{
-	if (sdebug_host_lock) {
-		unsigned long iflags;
-		int rc;
-
-		spin_lock_irqsave(shost->host_lock, iflags);
-		rc = scsi_debug_queuecommand(cmd);
-		spin_unlock_irqrestore(shost->host_lock, iflags);
-		return rc;
-	} else
-		return scsi_debug_queuecommand(cmd);
-}
-
 static struct scsi_host_template sdebug_driver_template = {
 	.show_info =		scsi_debug_show_info,
 	.write_info =		scsi_debug_write_info,
@@ -5195,7 +5165,7 @@ static struct scsi_host_template sdebug_driver_template = {
 	.slave_configure =	scsi_debug_slave_configure,
 	.slave_destroy =	scsi_debug_slave_destroy,
 	.ioctl =		scsi_debug_ioctl,
-	.queuecommand =		sdebug_queuecommand_lock_or_not,
+	.queuecommand =		scsi_debug_queuecommand,
 	.change_queue_depth =	sdebug_change_qdepth,
 	.eh_abort_handler =	scsi_debug_abort,
 	.eh_device_reset_handler = scsi_debug_device_reset,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 03/12] scsi_debug: replace jiffy timers with hr timers
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
  2016-04-25 16:16 ` [PATCH 01/12] scsi_debug: cleanup naming and bit crunching Douglas Gilbert
  2016-04-25 16:16 ` [PATCH 02/12] scsi_debug: ignore host lock option Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:17   ` Hannes Reinecke
  2016-04-26 18:38   ` Bart Van Assche
  2016-04-25 16:16 ` [PATCH 04/12] scsi_debug: make jiffy delay name clearer Douglas Gilbert
                   ` (9 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

The driver supports two command delay interfaces, the
original one whose unit is a jiffy, and a newer one whose
unit is a nanosecond. Each had different implementations.
Keep both interfaces but simplify the implemenation to use a
single delay mechanism based on high resolution timers.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 42e5c37..9dc0349 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -24,7 +24,7 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/timer.h>
+#include <linux/jiffies.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -518,7 +518,7 @@ struct sdebug_scmd_extra_t {
 
 static int sdebug_add_host = DEF_NUM_HOST;
 static int sdebug_ato = DEF_ATO;
-static int sdebug_delay = DEF_DELAY;
+static int sdebug_delay = DEF_DELAY;	/* in jiffies */
 static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB;
 static int sdebug_dif = DEF_DIF;
 static int sdebug_dix = DEF_DIX;
@@ -530,7 +530,7 @@ static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED;
 static int sdebug_max_luns = DEF_MAX_LUNS;
 static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE;
 static atomic_t retired_max_queue;	/* if > 0 then was prior max_queue */
-static int sdebug_ndelay = DEF_NDELAY;
+static int sdebug_ndelay = DEF_NDELAY;	/* in nanoseconds */
 static int sdebug_no_lun_0 = DEF_NO_LUN_0;
 static int sdebug_no_uld;
 static int sdebug_num_parts = DEF_NUM_PARTS;
@@ -617,7 +617,6 @@ struct sdebug_hrtimer {		/* ... is derived from hrtimer */
 
 struct sdebug_queued_cmd {
 	/* in_use flagged by a bit in queued_in_use_bm[] */
-	struct timer_list *cmnd_timerp;
 	struct tasklet_struct *tletp;
 	struct sdebug_hrtimer *sd_hrtp;
 	struct scsi_cmnd * a_cmnd;
@@ -3151,7 +3150,7 @@ resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		return check_condition_result;
 	}
 
-	buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
+	buf = kzalloc(scsi_bufflen(scp), GFP_ATOMIC);
 	if (!buf) {
 		mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
 				INSUFF_RES_ASCQ);
@@ -3298,7 +3297,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
 	struct sg_mapping_iter miter;
 
 	/* better not to use temporary buffer. */
-	buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
+	buf = kzalloc(scsi_bufflen(scp), GFP_ATOMIC);
 	if (!buf) {
 		mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
 				INSUFF_RES_ASCQ);
@@ -3350,7 +3349,7 @@ resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	return resp_xdwriteread(scp, lba, num, devip);
 }
 
-/* When timer or tasklet goes off this function is called. */
+/* When tasklet goes off this function is called. */
 static void sdebug_q_cmd_complete(unsigned long indx)
 {
 	int qa_indx;
@@ -3592,14 +3591,11 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
 				sqcp->a_cmnd = NULL;
 				spin_unlock_irqrestore(&queued_arr_lock,
 						       iflags);
-				if (sdebug_ndelay > 0) {
+				if ((sdebug_delay > 0) ||
+				    (sdebug_ndelay > 0)) {
 					if (sqcp->sd_hrtp)
 						hrtimer_cancel(
 							&sqcp->sd_hrtp->hrt);
-				} else if (sdebug_delay > 0) {
-					if (sqcp->cmnd_timerp)
-						del_timer_sync(
-							sqcp->cmnd_timerp);
 				} else if (sdebug_delay < 0) {
 					if (sqcp->tletp)
 						tasklet_kill(sqcp->tletp);
@@ -3633,14 +3629,11 @@ static void stop_all_queued(void)
 				sqcp->a_cmnd = NULL;
 				spin_unlock_irqrestore(&queued_arr_lock,
 						       iflags);
-				if (sdebug_ndelay > 0) {
+				if ((sdebug_delay > 0) ||
+				    (sdebug_ndelay > 0)) {
 					if (sqcp->sd_hrtp)
 						hrtimer_cancel(
 							&sqcp->sd_hrtp->hrt);
-				} else if (sdebug_delay > 0) {
-					if (sqcp->cmnd_timerp)
-						del_timer_sync(
-							sqcp->cmnd_timerp);
 				} else if (sdebug_delay < 0) {
 					if (sqcp->tletp)
 						tasklet_kill(sqcp->tletp);
@@ -3663,8 +3656,6 @@ static void free_all_queued(void)
 	spin_lock_irqsave(&queued_arr_lock, iflags);
 	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
 		sqcp = &queued_arr[k];
-		kfree(sqcp->cmnd_timerp);
-		sqcp->cmnd_timerp = NULL;
 		kfree(sqcp->tletp);
 		sqcp->tletp = NULL;
 		kfree(sqcp->sd_hrtp);
@@ -3921,24 +3912,19 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 	sqcp->a_cmnd = cmnd;
 	cmnd->result = scsi_result;
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
-	if (delta_jiff > 0) {
-		if (NULL == sqcp->cmnd_timerp) {
-			sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list),
-						    GFP_ATOMIC);
-			if (NULL == sqcp->cmnd_timerp)
-				return SCSI_MLQUEUE_HOST_BUSY;
-			init_timer(sqcp->cmnd_timerp);
-		}
-		sqcp->cmnd_timerp->function = sdebug_q_cmd_complete;
-		sqcp->cmnd_timerp->data = k;
-		sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff;
-		add_timer(sqcp->cmnd_timerp);
-	} else if (sdebug_ndelay > 0) {
-		ktime_t kt = ktime_set(0, sdebug_ndelay);
+	if ((delta_jiff > 0) || (sdebug_ndelay > 0)) {
 		struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
+		ktime_t kt;
 
+		if (delta_jiff > 0) {
+			struct timespec ts;
+
+			jiffies_to_timespec(delta_jiff, &ts);
+			kt = ktime_set(ts.tv_sec, ts.tv_nsec);
+		} else
+			kt = ktime_set(0, sdebug_ndelay);
 		if (NULL == sd_hp) {
-			sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC);
+			sd_hp = kzalloc(sizeof(*sd_hp), GFP_ATOMIC);
 			if (NULL == sd_hp)
 				return SCSI_MLQUEUE_HOST_BUSY;
 			sqcp->sd_hrtp = sd_hp;
@@ -3950,7 +3936,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 		hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
 	} else {	/* delay < 0 */
 		if (NULL == sqcp->tletp) {
-			sqcp->tletp = kmalloc(sizeof(*sqcp->tletp),
+			sqcp->tletp = kzalloc(sizeof(*sqcp->tletp),
 					      GFP_ATOMIC);
 			if (NULL == sqcp->tletp)
 				return SCSI_MLQUEUE_HOST_BUSY;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 04/12] scsi_debug: make jiffy delay name clearer
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (2 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 03/12] scsi_debug: replace jiffy timers with hr timers Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:17   ` Hannes Reinecke
  2016-04-25 16:16 ` [PATCH 05/12] scsi_debug: replace tasklet with work queue Douglas Gilbert
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Add 'j' to delay names to make it clearer that its unit is
jiffies and to differentiate it from sdebug_ndelay whose unit is
nanoseconds.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 9dc0349..5ad16e6 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -104,7 +104,7 @@ static const char *sdebug_version_date = "20160422";
  * (id 0) containing 1 logical unit (lun 0). That is 1 device.
  */
 #define DEF_ATO 1
-#define DEF_DELAY   1		/* if > 0 unit is a jiffy */
+#define DEF_JDELAY   1		/* if > 0 unit is a jiffy */
 #define DEF_DEV_SIZE_MB   8
 #define DEF_DIF 0
 #define DEF_DIX 0
@@ -136,7 +136,7 @@ static const char *sdebug_version_date = "20160422";
 #define DEF_VPD_USE_HOSTNO 1
 #define DEF_WRITESAME_LENGTH 0xFFFF
 #define DEF_STRICT 0
-#define DELAY_OVERRIDDEN -9999
+#define JDELAY_OVERRIDDEN -9999
 
 /* bit mask values for sdebug_opts */
 #define SDEBUG_OPT_NOISE		1
@@ -206,7 +206,7 @@ static const char *sdebug_version_date = "20160422";
 
 /* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
  * (for response) at one time. Can be reduced by max_queue option. Command
- * responses are not queued when delay=0 and ndelay=0. The per-device
+ * responses are not queued when jdelay=0 and ndelay=0. The per-device
  * DEF_CMD_PER_LUN can be changed via sysfs:
  * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
  * SCSI_DEBUG_CANQUEUE. */
@@ -518,7 +518,7 @@ struct sdebug_scmd_extra_t {
 
 static int sdebug_add_host = DEF_NUM_HOST;
 static int sdebug_ato = DEF_ATO;
-static int sdebug_delay = DEF_DELAY;	/* in jiffies */
+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_dif = DEF_DIF;
 static int sdebug_dix = DEF_DIX;
@@ -530,7 +530,7 @@ static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED;
 static int sdebug_max_luns = DEF_MAX_LUNS;
 static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE;
 static atomic_t retired_max_queue;	/* if > 0 then was prior max_queue */
-static int sdebug_ndelay = DEF_NDELAY;	/* in nanoseconds */
+static int sdebug_ndelay = DEF_NDELAY;	/* if > 0 then unit is nanoseconds */
 static int sdebug_no_lun_0 = DEF_NO_LUN_0;
 static int sdebug_no_uld;
 static int sdebug_num_parts = DEF_NUM_PARTS;
@@ -3591,12 +3591,12 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
 				sqcp->a_cmnd = NULL;
 				spin_unlock_irqrestore(&queued_arr_lock,
 						       iflags);
-				if ((sdebug_delay > 0) ||
+				if ((sdebug_jdelay > 0) ||
 				    (sdebug_ndelay > 0)) {
 					if (sqcp->sd_hrtp)
 						hrtimer_cancel(
 							&sqcp->sd_hrtp->hrt);
-				} else if (sdebug_delay < 0) {
+				} else if (sdebug_jdelay < 0) {
 					if (sqcp->tletp)
 						tasklet_kill(sqcp->tletp);
 				}
@@ -3629,12 +3629,12 @@ static void stop_all_queued(void)
 				sqcp->a_cmnd = NULL;
 				spin_unlock_irqrestore(&queued_arr_lock,
 						       iflags);
-				if ((sdebug_delay > 0) ||
+				if ((sdebug_jdelay > 0) ||
 				    (sdebug_ndelay > 0)) {
 					if (sqcp->sd_hrtp)
 						hrtimer_cancel(
 							&sqcp->sd_hrtp->hrt);
-				} else if (sdebug_delay < 0) {
+				} else if (sdebug_jdelay < 0) {
 					if (sqcp->tletp)
 						tasklet_kill(sqcp->tletp);
 				}
@@ -3934,7 +3934,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 			sd_hp->qa_indx = k;
 		}
 		hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
-	} else {	/* delay < 0 */
+	} else {	/* jdelay < 0 */
 		if (NULL == sqcp->tletp) {
 			sqcp->tletp = kzalloc(sizeof(*sqcp->tletp),
 					      GFP_ATOMIC);
@@ -3971,7 +3971,7 @@ respond_in_thread:	/* call back to mid-layer using invocation thread */
 module_param_named(add_host, sdebug_add_host, int, S_IRUGO | S_IWUSR);
 module_param_named(ato, sdebug_ato, int, S_IRUGO);
 module_param_named(clustering, sdebug_clustering, bool, S_IRUGO | S_IWUSR);
-module_param_named(delay, sdebug_delay, int, S_IRUGO | S_IWUSR);
+module_param_named(delay, sdebug_jdelay, int, S_IRUGO | S_IWUSR);
 module_param_named(dev_size_mb, sdebug_dev_size_mb, int, S_IRUGO);
 module_param_named(dif, sdebug_dif, int, S_IRUGO);
 module_param_named(dix, sdebug_dix, int, S_IRUGO);
@@ -4112,7 +4112,7 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
 		"usec_in_jiffy=%lu\n",
 		SCSI_DEBUG_VERSION, sdebug_version_date,
 		sdebug_num_tgts, sdebug_dev_size_mb, sdebug_opts,
-		sdebug_every_nth, b, sdebug_delay, sdebug_ndelay,
+		sdebug_every_nth, b, sdebug_jdelay, sdebug_ndelay,
 		sdebug_max_luns, atomic_read(&sdebug_completions),
 		sdebug_sector_size, sdebug_cylinders_per, sdebug_heads,
 		sdebug_sectors_per, num_aborts, num_dev_resets,
@@ -4130,17 +4130,17 @@ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
 
 static ssize_t delay_show(struct device_driver *ddp, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_delay);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_jdelay);
 }
-/* Returns -EBUSY if delay is being changed and commands are queued */
+/* Returns -EBUSY if jdelay is being changed and commands are queued */
 static ssize_t delay_store(struct device_driver *ddp, const char *buf,
 			   size_t count)
 {
-	int delay, res;
+	int jdelay, res;
 
-	if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) {
+	if ((count > 0) && (1 == sscanf(buf, "%d", &jdelay))) {
 		res = count;
-		if (sdebug_delay != delay) {
+		if (sdebug_jdelay != jdelay) {
 			unsigned long iflags;
 			int k;
 
@@ -4149,7 +4149,7 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf,
 			if (k != sdebug_max_queue)
 				res = -EBUSY;	/* have queued commands */
 			else {
-				sdebug_delay = delay;
+				sdebug_jdelay = jdelay;
 				sdebug_ndelay = 0;
 			}
 			spin_unlock_irqrestore(&queued_arr_lock, iflags);
@@ -4165,7 +4165,7 @@ static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
 	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_ndelay);
 }
 /* Returns -EBUSY if ndelay is being changed and commands are queued */
-/* If > 0 and accepted then sdebug_delay is set to DELAY_OVERRIDDEN */
+/* If > 0 and accepted then sdebug_jdelay is set to JDELAY_OVERRIDDEN */
 static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
 			   size_t count)
 {
@@ -4182,8 +4182,8 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
 				res = -EBUSY;	/* have queued commands */
 			else {
 				sdebug_ndelay = ndelay;
-				sdebug_delay = ndelay ? DELAY_OVERRIDDEN
-							  : DEF_DELAY;
+				sdebug_jdelay = ndelay  ? JDELAY_OVERRIDDEN
+							: DEF_JDELAY;
 			}
 			spin_unlock_irqrestore(&queued_arr_lock, iflags);
 		}
@@ -4666,7 +4666,7 @@ static int __init scsi_debug_init(void)
 		pr_warn("ndelay must be less than 1 second, ignored\n");
 		sdebug_ndelay = 0;
 	} else if (sdebug_ndelay > 0)
-		sdebug_delay = DELAY_OVERRIDDEN;
+		sdebug_jdelay = JDELAY_OVERRIDDEN;
 
 	switch (sdebug_sector_size) {
 	case  512:
@@ -5136,7 +5136,7 @@ scsi_debug_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scp)
 
 fini:
 	return schedule_resp(scp, devip, errsts,
-			     ((F_DELAY_OVERR & flags) ? 0 : sdebug_delay));
+			     ((F_DELAY_OVERR & flags) ? 0 : sdebug_jdelay));
 check_cond:
 	return schedule_resp(scp, devip, check_condition_result, 0);
 }
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 05/12] scsi_debug: replace tasklet with work queue
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (3 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 04/12] scsi_debug: make jiffy delay name clearer Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:20   ` Hannes Reinecke
  2016-04-25 16:16 ` [PATCH 06/12] scsi_debug: re-order file scope declarations Douglas Gilbert
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

When a negative value was placed in the delay parameter, a tasklet
was scheduled. Change the tasklet to a work queue. Previously a
delay of -1 scheduled a high priority tasklet; since there are no
high priority work queues, treat -1 like other negative values
in delay and schedule a work item.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 5ad16e6..8ee9df6 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -610,15 +610,15 @@ static LIST_HEAD(sdebug_host_list);
 static DEFINE_SPINLOCK(sdebug_host_list_lock);
 
 
-struct sdebug_hrtimer {		/* ... is derived from hrtimer */
-	struct hrtimer hrt;	/* must be first element */
+struct sdebug_defer {
+	struct hrtimer hrt;
+	struct execute_work ew;
 	int qa_indx;
 };
 
 struct sdebug_queued_cmd {
 	/* in_use flagged by a bit in queued_in_use_bm[] */
-	struct tasklet_struct *tletp;
-	struct sdebug_hrtimer *sd_hrtp;
+	struct sdebug_defer *sd_dp;
 	struct scsi_cmnd * a_cmnd;
 };
 static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
@@ -3349,8 +3349,9 @@ resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	return resp_xdwriteread(scp, lba, num, devip);
 }
 
-/* When tasklet goes off this function is called. */
-static void sdebug_q_cmd_complete(unsigned long indx)
+/* Queued command completions converge here. */
+static void
+sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
 {
 	int qa_indx;
 	int retiring = 0;
@@ -3360,7 +3361,7 @@ static void sdebug_q_cmd_complete(unsigned long indx)
 	struct sdebug_dev_info *devip;
 
 	atomic_inc(&sdebug_completions);
-	qa_indx = indx;
+	qa_indx = sd_dp->qa_indx;
 	if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
 		pr_err("wild qa_indx=%d\n", qa_indx);
 		return;
@@ -3411,64 +3412,21 @@ static void sdebug_q_cmd_complete(unsigned long indx)
 static enum hrtimer_restart
 sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
 {
-	int qa_indx;
-	int retiring = 0;
-	unsigned long iflags;
-	struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer;
-	struct sdebug_queued_cmd *sqcp;
-	struct scsi_cmnd *scp;
-	struct sdebug_dev_info *devip;
-
-	atomic_inc(&sdebug_completions);
-	qa_indx = sd_hrtp->qa_indx;
-	if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
-		pr_err("wild qa_indx=%d\n", qa_indx);
-		goto the_end;
-	}
-	spin_lock_irqsave(&queued_arr_lock, iflags);
-	sqcp = &queued_arr[qa_indx];
-	scp = sqcp->a_cmnd;
-	if (NULL == scp) {
-		spin_unlock_irqrestore(&queued_arr_lock, iflags);
-		pr_err("scp is NULL\n");
-		goto the_end;
-	}
-	devip = (struct sdebug_dev_info *)scp->device->hostdata;
-	if (devip)
-		atomic_dec(&devip->num_in_q);
-	else
-		pr_err("devip=NULL\n");
-	if (atomic_read(&retired_max_queue) > 0)
-		retiring = 1;
-
-	sqcp->a_cmnd = NULL;
-	if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
-		spin_unlock_irqrestore(&queued_arr_lock, iflags);
-		pr_err("Unexpected completion\n");
-		goto the_end;
-	}
-
-	if (unlikely(retiring)) {	/* user has reduced max_queue */
-		int k, retval;
-
-		retval = atomic_read(&retired_max_queue);
-		if (qa_indx >= retval) {
-			spin_unlock_irqrestore(&queued_arr_lock, iflags);
-			pr_err("index %d too large\n", retval);
-			goto the_end;
-		}
-		k = find_last_bit(queued_in_use_bm, retval);
-		if ((k < sdebug_max_queue) || (k == retval))
-			atomic_set(&retired_max_queue, 0);
-		else
-			atomic_set(&retired_max_queue, k + 1);
-	}
-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
-	scp->scsi_done(scp); /* callback to mid level */
-the_end:
+	struct sdebug_defer *sd_dp = container_of(timer, struct sdebug_defer,
+						  hrt);
+	sdebug_q_cmd_complete(sd_dp);
 	return HRTIMER_NORESTART;
 }
 
+/* When work queue schedules work, it calls this function. */
+static void
+sdebug_q_cmd_wq_complete(struct work_struct *work)
+{
+	struct sdebug_defer *sd_dp = container_of(work, struct sdebug_defer,
+						  ew.work);
+	sdebug_q_cmd_complete(sd_dp);
+}
+
 static struct sdebug_dev_info *
 sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
 {
@@ -3567,13 +3525,15 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp)
 	}
 }
 
-/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */
-static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
+/* If @cmnd found deletes its timer or work queue and returns true; else
+   returns false */
+static bool stop_queued_cmnd(struct scsi_cmnd *cmnd)
 {
 	unsigned long iflags;
 	int k, qmax, r_qmax;
 	struct sdebug_queued_cmd *sqcp;
 	struct sdebug_dev_info *devip;
+	struct sdebug_defer *sd_dp;
 
 	spin_lock_irqsave(&queued_arr_lock, iflags);
 	qmax = sdebug_max_queue;
@@ -3583,64 +3543,63 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
 	for (k = 0; k < qmax; ++k) {
 		if (test_bit(k, queued_in_use_bm)) {
 			sqcp = &queued_arr[k];
-			if (cmnd == sqcp->a_cmnd) {
-				devip = (struct sdebug_dev_info *)
-					cmnd->device->hostdata;
-				if (devip)
-					atomic_dec(&devip->num_in_q);
-				sqcp->a_cmnd = NULL;
-				spin_unlock_irqrestore(&queued_arr_lock,
-						       iflags);
-				if ((sdebug_jdelay > 0) ||
-				    (sdebug_ndelay > 0)) {
-					if (sqcp->sd_hrtp)
-						hrtimer_cancel(
-							&sqcp->sd_hrtp->hrt);
-				} else if (sdebug_jdelay < 0) {
-					if (sqcp->tletp)
-						tasklet_kill(sqcp->tletp);
-				}
-				clear_bit(k, queued_in_use_bm);
-				return 1;
+			if (cmnd != sqcp->a_cmnd)
+				continue;
+			/* found command */
+			devip = (struct sdebug_dev_info *)
+				cmnd->device->hostdata;
+			if (devip)
+				atomic_dec(&devip->num_in_q);
+			sqcp->a_cmnd = NULL;
+			sd_dp = sqcp->sd_dp;
+			spin_unlock_irqrestore(&queued_arr_lock,
+					       iflags);
+			if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) {
+				if (sd_dp)
+					hrtimer_cancel(&sd_dp->hrt);
+			} else if (sdebug_jdelay < 0) {
+				if (sd_dp)
+					cancel_work_sync(&sd_dp->ew.work);
 			}
+			clear_bit(k, queued_in_use_bm);
+			return true;
 		}
 	}
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
-	return 0;
+	return false;
 }
 
-/* Deletes (stops) timers or tasklets of all queued commands */
+/* Deletes (stops) timers or work queues of all queued commands */
 static void stop_all_queued(void)
 {
 	unsigned long iflags;
 	int k;
 	struct sdebug_queued_cmd *sqcp;
 	struct sdebug_dev_info *devip;
+	struct sdebug_defer *sd_dp;
 
 	spin_lock_irqsave(&queued_arr_lock, iflags);
 	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
 		if (test_bit(k, queued_in_use_bm)) {
 			sqcp = &queued_arr[k];
-			if (sqcp->a_cmnd) {
-				devip = (struct sdebug_dev_info *)
-					sqcp->a_cmnd->device->hostdata;
-				if (devip)
-					atomic_dec(&devip->num_in_q);
-				sqcp->a_cmnd = NULL;
-				spin_unlock_irqrestore(&queued_arr_lock,
-						       iflags);
-				if ((sdebug_jdelay > 0) ||
-				    (sdebug_ndelay > 0)) {
-					if (sqcp->sd_hrtp)
-						hrtimer_cancel(
-							&sqcp->sd_hrtp->hrt);
-				} else if (sdebug_jdelay < 0) {
-					if (sqcp->tletp)
-						tasklet_kill(sqcp->tletp);
-				}
-				clear_bit(k, queued_in_use_bm);
-				spin_lock_irqsave(&queued_arr_lock, iflags);
+			if (NULL == sqcp->a_cmnd)
+				continue;
+			devip = (struct sdebug_dev_info *)
+				sqcp->a_cmnd->device->hostdata;
+			if (devip)
+				atomic_dec(&devip->num_in_q);
+			sqcp->a_cmnd = NULL;
+			sd_dp = sqcp->sd_dp;
+			spin_unlock_irqrestore(&queued_arr_lock, iflags);
+			if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) {
+				if (sd_dp)
+					hrtimer_cancel(&sd_dp->hrt);
+			} else if (sdebug_jdelay < 0) {
+				if (sd_dp)
+					cancel_work_sync(&sd_dp->ew.work);
 			}
+			clear_bit(k, queued_in_use_bm);
+			spin_lock_irqsave(&queued_arr_lock, iflags);
 		}
 	}
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
@@ -3649,30 +3608,27 @@ static void stop_all_queued(void)
 /* Free queued command memory on heap */
 static void free_all_queued(void)
 {
-	unsigned long iflags;
 	int k;
 	struct sdebug_queued_cmd *sqcp;
 
-	spin_lock_irqsave(&queued_arr_lock, iflags);
 	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
 		sqcp = &queued_arr[k];
-		kfree(sqcp->tletp);
-		sqcp->tletp = NULL;
-		kfree(sqcp->sd_hrtp);
-		sqcp->sd_hrtp = NULL;
+		kfree(sqcp->sd_dp);
+		sqcp->sd_dp = NULL;
 	}
-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
 static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
 {
+	bool ok;
+
 	++num_aborts;
 	if (SCpnt) {
-		if (SCpnt->device &&
-		    (SDEBUG_OPT_ALL_NOISE & sdebug_opts))
-			sdev_printk(KERN_INFO, SCpnt->device, "%s\n",
-				    __func__);
-		stop_queued_cmnd(SCpnt);
+		ok = stop_queued_cmnd(SCpnt);
+		if (SCpnt->device && (SDEBUG_OPT_ALL_NOISE & sdebug_opts))
+			sdev_printk(KERN_INFO, SCpnt->device,
+				    "%s: command%s found\n", __func__,
+				    ok ? "" : " not");
 	}
 	return SUCCESS;
 }
@@ -3846,6 +3802,7 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 	int k, num_in_q, qdepth, inject;
 	struct sdebug_queued_cmd *sqcp = NULL;
 	struct scsi_device *sdp;
+	struct sdebug_defer *sd_dp;
 
 	/* this should never happen */
 	if (WARN_ON(!cmnd))
@@ -3912,8 +3869,8 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 	sqcp->a_cmnd = cmnd;
 	cmnd->result = scsi_result;
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+	sd_dp = sqcp->sd_dp;
 	if ((delta_jiff > 0) || (sdebug_ndelay > 0)) {
-		struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp;
 		ktime_t kt;
 
 		if (delta_jiff > 0) {
@@ -3923,30 +3880,27 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 			kt = ktime_set(ts.tv_sec, ts.tv_nsec);
 		} else
 			kt = ktime_set(0, sdebug_ndelay);
-		if (NULL == sd_hp) {
-			sd_hp = kzalloc(sizeof(*sd_hp), GFP_ATOMIC);
-			if (NULL == sd_hp)
+		if (NULL == sd_dp) {
+			sd_dp = kzalloc(sizeof(*sd_dp), GFP_ATOMIC);
+			if (NULL == sd_dp)
 				return SCSI_MLQUEUE_HOST_BUSY;
-			sqcp->sd_hrtp = sd_hp;
-			hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC,
+			sqcp->sd_dp = sd_dp;
+			hrtimer_init(&sd_dp->hrt, CLOCK_MONOTONIC,
 				     HRTIMER_MODE_REL);
-			sd_hp->hrt.function = sdebug_q_cmd_hrt_complete;
-			sd_hp->qa_indx = k;
+			sd_dp->hrt.function = sdebug_q_cmd_hrt_complete;
+			sd_dp->qa_indx = k;
 		}
-		hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL);
+		hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL);
 	} else {	/* jdelay < 0 */
-		if (NULL == sqcp->tletp) {
-			sqcp->tletp = kzalloc(sizeof(*sqcp->tletp),
-					      GFP_ATOMIC);
-			if (NULL == sqcp->tletp)
+		if (NULL == sd_dp) {
+			sd_dp = kzalloc(sizeof(*sqcp->sd_dp), GFP_ATOMIC);
+			if (NULL == sd_dp)
 				return SCSI_MLQUEUE_HOST_BUSY;
-			tasklet_init(sqcp->tletp,
-				     sdebug_q_cmd_complete, k);
+			sqcp->sd_dp = sd_dp;
+			sd_dp->qa_indx = k;
+			INIT_WORK(&sd_dp->ew.work, sdebug_q_cmd_wq_complete);
 		}
-		if (-1 == delta_jiff)
-			tasklet_hi_schedule(sqcp->tletp);
-		else
-			tasklet_schedule(sqcp->tletp);
+		schedule_work(&sd_dp->ew.work);
 	}
 	if ((SDEBUG_OPT_Q_NOISE & sdebug_opts) &&
 	    (scsi_result == device_qfull_result))
@@ -4149,6 +4103,9 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf,
 			if (k != sdebug_max_queue)
 				res = -EBUSY;	/* have queued commands */
 			else {
+				/* make sure sdebug_defer instances get
+				 * re-allocated for new delay variant */
+				free_all_queued();
 				sdebug_jdelay = jdelay;
 				sdebug_ndelay = 0;
 			}
@@ -4181,6 +4138,9 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
 			if (k != sdebug_max_queue)
 				res = -EBUSY;	/* have queued commands */
 			else {
+				/* make sure sdebug_defer instances get
+				 * re-allocated for new delay variant */
+				free_all_queued();
 				sdebug_ndelay = ndelay;
 				sdebug_jdelay = ndelay  ? JDELAY_OVERRIDDEN
 							: DEF_JDELAY;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 06/12] scsi_debug: re-order file scope declarations
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (4 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 05/12] scsi_debug: replace tasklet with work queue Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:21   ` Hannes Reinecke
  2016-04-26 20:55   ` Bart Van Assche
  2016-04-25 16:16 ` [PATCH 07/12] scsi_debug: use likely hints on fast path Douglas Gilbert
                   ` (6 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Group most defines together first; followed by struct definitions
and then table and variable definitions. Normalize all function
headers.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 8ee9df6..349eaeb 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -95,7 +95,6 @@ static const char *sdebug_version_date = "20160422";
 /* Additional Sense Code Qualifier (ASCQ) */
 #define ACK_NAK_TO 0x3
 
-
 /* Default values for driver parameters */
 #define DEF_NUM_HOST   1
 #define DEF_NUM_TGTS   1
@@ -161,14 +160,14 @@ static const char *sdebug_version_date = "20160422";
 				  SDEBUG_OPT_DIF_ERR | SDEBUG_OPT_DIX_ERR | \
 				  SDEBUG_OPT_SHORT_TRANSFER)
 /* When "every_nth" > 0 then modulo "every_nth" commands:
- *   - a no response is simulated if SDEBUG_OPT_TIMEOUT is set
+ *   - a missing response is simulated if SDEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
  *     commands if SDEBUG_OPT_RECOVERED_ERR is set.
  *   - a TRANSPORT_ERROR is simulated on successful read and write
  *     commands if SDEBUG_OPT_TRANSPORT_ERR is set.
  *
  * When "every_nth" < 0 then after "- every_nth" commands:
- *   - a no response is simulated if SDEBUG_OPT_TIMEOUT is set
+ *   - a missing response is simulated if SDEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
  *     commands if SDEBUG_OPT_RECOVERED_ERR is set.
  *   - a TRANSPORT_ERROR is simulated on successful read and write
@@ -178,7 +177,7 @@ static const char *sdebug_version_date = "20160422";
  * every_nth via sysfs).
  */
 
-/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in
+/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs) are returned in
  * priority order. In the subset implemented here lower numbers have higher
  * priority. The UA numbers should be a sequence starting from 0 with
  * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */
@@ -218,7 +217,83 @@ static const char *sdebug_version_date = "20160422";
 #warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
 #endif
 
-/* SCSI opcodes (first byte of cdb) mapped onto these indexes */
+#define F_D_IN			1
+#define F_D_OUT			2
+#define F_D_OUT_MAYBE		4	/* WRITE SAME, NDOB bit */
+#define F_D_UNKN		8
+#define F_RL_WLUN_OK		0x10
+#define F_SKIP_UA		0x20
+#define F_DELAY_OVERR		0x40
+#define F_SA_LOW		0x80	/* cdb byte 1, bits 4 to 0 */
+#define F_SA_HIGH		0x100	/* as used by variable length cdbs */
+#define F_INV_OP		0x200
+#define F_FAKE_RW		0x400
+#define F_M_ACCESS		0x800	/* media access */
+
+#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
+#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW)
+#define FF_SA (F_SA_HIGH | F_SA_LOW)
+
+#define SDEBUG_MAX_PARTS 4
+
+#define SCSI_DEBUG_MAX_CMD_LEN 32
+
+
+struct sdebug_dev_info {
+	struct list_head dev_list;
+	unsigned int channel;
+	unsigned int target;
+	u64 lun;
+	struct sdebug_host_info *sdbg_host;
+	unsigned long uas_bm[1];
+	atomic_t num_in_q;
+	char stopped;		/* TODO: should be atomic */
+	bool used;
+};
+
+struct sdebug_host_info {
+	struct list_head host_list;
+	struct Scsi_Host *shost;
+	struct device dev;
+	struct list_head dev_info_list;
+};
+
+#define to_sdebug_host(d)	\
+	container_of(d, struct sdebug_host_info, dev)
+
+struct sdebug_defer {
+	struct hrtimer hrt;
+	struct execute_work ew;
+	int qa_indx;
+};
+
+struct sdebug_queued_cmd {
+	/* in_use flagged by a bit in queued_in_use_bm[] */
+	struct sdebug_defer *sd_dp;
+	struct scsi_cmnd *a_cmnd;
+};
+
+struct sdebug_scmd_extra_t {
+	bool inj_recovered;
+	bool inj_transport;
+	bool inj_dif;
+	bool inj_dix;
+	bool inj_short;
+};
+
+struct opcode_info_t {
+	u8 num_attached;	/* 0 if this is it (i.e. a leaf); use 0xff
+				 * for terminating element */
+	u8 opcode;		/* if num_attached > 0, preferred */
+	u16 sa;			/* service action */
+	u32 flags;		/* OR-ed set of SDEB_F_* */
+	int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
+	const struct opcode_info_t *arrp;  /* num_attached elements or NULL */
+	u8 len_mask[16];	/* len=len_mask[0], then mask for cdb[1]... */
+				/* ignore cdb bytes after position 15 */
+};
+
+/* SCSI opcodes (first byte of cdb) of interest mapped onto these indexes */
 enum sdeb_opcode_index {
 	SDEB_I_INVALID_OPCODE =	0,
 	SDEB_I_INQUIRY = 1,
@@ -273,7 +348,7 @@ static const unsigned char opcode_ind_arr[256] = {
 	0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
 	    SDEB_I_RELEASE,
 	0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0,
-/* 0x60; 0x60->0x7d are reserved */
+/* 0x60; 0x60->0x7d are reserved, 0x7e is "extended cdb" */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, SDEB_I_VARIABLE_LEN,
@@ -296,24 +371,6 @@ static const unsigned char opcode_ind_arr[256] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 };
 
-#define F_D_IN			1
-#define F_D_OUT			2
-#define F_D_OUT_MAYBE		4	/* WRITE SAME, NDOB bit */
-#define F_D_UNKN		8
-#define F_RL_WLUN_OK		0x10
-#define F_SKIP_UA		0x20
-#define F_DELAY_OVERR		0x40
-#define F_SA_LOW		0x80	/* cdb byte 1, bits 4 to 0 */
-#define F_SA_HIGH		0x100	/* as used by variable length cdbs */
-#define F_INV_OP		0x200
-#define F_FAKE_RW		0x400
-#define F_M_ACCESS		0x800	/* media access */
-
-#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
-#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW)
-#define FF_SA (F_SA_HIGH | F_SA_LOW)
-
-struct sdebug_dev_info;
 static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
@@ -336,18 +393,6 @@ static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *);
 
-struct opcode_info_t {
-	u8 num_attached;	/* 0 if this is it (i.e. a leaf); use 0xff
-				 * for terminating element */
-	u8 opcode;		/* if num_attached > 0, preferred */
-	u16 sa;			/* service action */
-	u32 flags;		/* OR-ed set of SDEB_F_* */
-	int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
-	const struct opcode_info_t *arrp;  /* num_attached elements or NULL */
-	u8 len_mask[16];	/* len=len_mask[0], then mask for cdb[1]... */
-				/* ignore cdb bytes after position 15 */
-};
-
 static const struct opcode_info_t msense_iarr[1] = {
 	{0, 0x1a, 0, F_D_IN, NULL, NULL,
 	    {6,  0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
@@ -508,14 +553,6 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
 	    {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
 };
 
-struct sdebug_scmd_extra_t {
-	bool inj_recovered;
-	bool inj_transport;
-	bool inj_dif;
-	bool inj_dix;
-	bool inj_short;
-};
-
 static int sdebug_add_host = DEF_NUM_HOST;
 static int sdebug_ato = DEF_ATO;
 static int sdebug_jdelay = DEF_JDELAY;	/* if > 0 then unit is jiffies */
@@ -563,8 +600,6 @@ static atomic_t sdebug_cmnd_count;
 static atomic_t sdebug_completions;
 static atomic_t sdebug_a_tsf;		/* counter of 'almost' TSFs */
 
-#define DEV_READONLY(TGT)      (0)
-
 static unsigned int sdebug_store_sectors;
 static sector_t sdebug_capacity;	/* in sectors */
 
@@ -574,58 +609,10 @@ static int sdebug_heads;		/* heads per disk */
 static int sdebug_cylinders_per;	/* cylinders per surface */
 static int sdebug_sectors_per;		/* sectors per cylinder */
 
-#define SDEBUG_MAX_PARTS 4
-
-#define SCSI_DEBUG_MAX_CMD_LEN 32
-
-static unsigned int scsi_debug_lbp(void)
-{
-	return ((0 == sdebug_fake_rw) &&
-		(sdebug_lbpu | sdebug_lbpws | sdebug_lbpws10));
-}
-
-struct sdebug_dev_info {
-	struct list_head dev_list;
-	unsigned int channel;
-	unsigned int target;
-	u64 lun;
-	struct sdebug_host_info *sdbg_host;
-	unsigned long uas_bm[1];
-	atomic_t num_in_q;
-	char stopped;		/* TODO: should be atomic */
-	bool used;
-};
-
-struct sdebug_host_info {
-	struct list_head host_list;
-	struct Scsi_Host *shost;
-	struct device dev;
-	struct list_head dev_info_list;
-};
-
-#define to_sdebug_host(d)	\
-	container_of(d, struct sdebug_host_info, dev)
-
 static LIST_HEAD(sdebug_host_list);
 static DEFINE_SPINLOCK(sdebug_host_list_lock);
 
-
-struct sdebug_defer {
-	struct hrtimer hrt;
-	struct execute_work ew;
-	int qa_indx;
-};
-
-struct sdebug_queued_cmd {
-	/* in_use flagged by a bit in queued_in_use_bm[] */
-	struct sdebug_defer *sd_dp;
-	struct scsi_cmnd * a_cmnd;
-};
-static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
-static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
-
-
-static unsigned char * fake_storep;	/* ramdisk storage */
+static unsigned char *fake_storep;	/* ramdisk storage */
 static struct sd_dif_tuple *dif_storep;	/* protection info */
 static void *map_storep;		/* provisioning map */
 
@@ -639,6 +626,9 @@ static int dix_writes;
 static int dix_reads;
 static int dif_errors;
 
+static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
+static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
+
 static DEFINE_SPINLOCK(queued_arr_lock);
 static DEFINE_RWLOCK(atomic_rw);
 
@@ -661,13 +651,12 @@ static const int illegal_condition_result =
 static const int device_qfull_result =
 	(DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
 
-static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
-				     0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,
-				     0, 0, 0, 0};
-static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
-				    0, 0, 0x2, 0x4b};
-static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
-			           0, 0, 0x0, 0x0};
+
+static unsigned int scsi_debug_lbp(void)
+{
+	return ((0 == sdebug_fake_rw) &&
+		(sdebug_lbpu | sdebug_lbpws | sdebug_lbpws10));
+}
 
 static void *fake_store(unsigned long long lba)
 {
@@ -683,9 +672,6 @@ static struct sd_dif_tuple *dif_store(sector_t sector)
 	return dif_storep + sector;
 }
 
-static int sdebug_add_adapter(void);
-static void sdebug_remove_adapter(void);
-
 static void sdebug_max_tgts_luns(void)
 {
 	struct sdebug_host_info *sdbg_host;
@@ -708,9 +694,9 @@ static void sdebug_max_tgts_luns(void)
 enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1};
 
 /* Set in_bit to -1 to indicate no bit position of invalid field */
-static void
-mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
-		     int in_byte, int in_bit)
+static void mk_sense_invalid_fld(struct scsi_cmnd *scp,
+				 enum sdeb_cmd_data c_d,
+				 int in_byte, int in_bit)
 {
 	unsigned char *sbuff;
 	u8 sks[4];
@@ -768,8 +754,7 @@ static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
 			    my_name, key, asc, asq);
 }
 
-static void
-mk_sense_invalid_opcode(struct scsi_cmnd *scp)
+static void mk_sense_invalid_opcode(struct scsi_cmnd *scp)
 {
 	mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
 }
@@ -1385,6 +1370,9 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	return ret;
 }
 
+static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
+				   0, 0, 0x0, 0x0};
+
 static int resp_requests(struct scsi_cmnd * scp,
 			 struct sdebug_dev_info * devip)
 {
@@ -1605,8 +1593,8 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp,
 	return ret;
 }
 
-static int
-resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_rsup_opcodes(struct scsi_cmnd *scp,
+			     struct sdebug_dev_info *devip)
 {
 	bool rctd;
 	u8 reporting_opts, req_opcode, sdeb_i, supp;
@@ -1756,8 +1744,8 @@ resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	return errsts;
 }
 
-static int
-resp_rsup_tmfs(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_rsup_tmfs(struct scsi_cmnd *scp,
+			  struct sdebug_dev_info *devip)
 {
 	bool repd;
 	u32 alloc_len, len;
@@ -1823,6 +1811,10 @@ static int resp_format_pg(unsigned char * p, int pcontrol, int target)
 	return sizeof(format_pg);
 }
 
+static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0,
+				     0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0,
+				     0, 0, 0, 0};
+
 static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
 { 	/* Caching page for mode_sense */
 	unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0,
@@ -1840,6 +1832,9 @@ static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
 	return sizeof(caching_pg);
 }
 
+static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
+				    0, 0, 0x2, 0x4b};
+
 static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
 { 	/* Control mode page for mode_sense */
 	unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0,
@@ -1938,8 +1933,8 @@ static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
 
 #define SDEBUG_MAX_MSENSE_SZ 256
 
-static int
-resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_mode_sense(struct scsi_cmnd *scp,
+			   struct sdebug_dev_info *devip)
 {
 	unsigned char dbd, llbaa;
 	int pcontrol, pcode, subpcode, bd_len;
@@ -1970,7 +1965,7 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 			(devip->target * 1000) - 3;
 	/* set DPOFUA bit for disks */
 	if (0 == sdebug_ptype)
-		dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
+		dev_spec = 0x10;	/* would be 0x81 if read-only */
 	else
 		dev_spec = 0x0;
 	if (msense_6) {
@@ -2081,8 +2076,8 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 
 #define SDEBUG_MAX_MSELECT_SZ 512
 
-static int
-resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_mode_select(struct scsi_cmnd *scp,
+			    struct sdebug_dev_info *devip)
 {
 	int pf, sp, ps, md_len, bd_len, off, spf, pg_len;
 	int param_len, res, mpage;
@@ -2280,8 +2275,8 @@ static int check_device_access_params(struct scsi_cmnd *scp,
 }
 
 /* Returns number of bytes copied or -1 if error. */
-static int
-do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
+static int do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num,
+			    bool do_write)
 {
 	int ret;
 	u64 block, rest = 0;
@@ -2323,8 +2318,7 @@ do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
 /* If fake_store(lba,num) compares equal to arr(num), then copy top half of
  * arr into fake_store(lba,num) and return true. If comparison fails then
  * return false. */
-static bool
-comp_write_worker(u64 lba, u32 num, const u8 *arr)
+static bool comp_write_worker(u64 lba, u32 num, const u8 *arr)
 {
 	bool res;
 	u64 block, rest = 0;
@@ -2463,8 +2457,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
 	return 0;
 }
 
-static int
-resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
 	u8 *cmd = scp->cmnd;
 	u64 lba;
@@ -2775,8 +2768,7 @@ static void unmap_region(sector_t lba, unsigned int len)
 	}
 }
 
-static int
-resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
 	u8 *cmd = scp->cmnd;
 	u64 lba;
@@ -2893,9 +2885,8 @@ resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	return 0;
 }
 
-static int
-resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba,
-		bool unmap, bool ndob)
+static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
+			   u32 ei_lba, bool unmap, bool ndob)
 {
 	unsigned long iflags;
 	unsigned long long i;
@@ -2945,8 +2936,8 @@ out:
 	return 0;
 }
 
-static int
-resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_write_same_10(struct scsi_cmnd *scp,
+			      struct sdebug_dev_info *devip)
 {
 	u8 *cmd = scp->cmnd;
 	u32 lba;
@@ -2970,8 +2961,8 @@ resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	return resp_write_same(scp, lba, num, ei_lba, unmap, false);
 }
 
-static int
-resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_write_same_16(struct scsi_cmnd *scp,
+			      struct sdebug_dev_info *devip)
 {
 	u8 *cmd = scp->cmnd;
 	u64 lba;
@@ -3001,8 +2992,8 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 /* Note the mode field is in the same position as the (lower) service action
  * field. For the Report supported operation codes command, SPC-4 suggests
  * each mode of this command should be reported separately; for future. */
-static int
-resp_write_buffer(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_write_buffer(struct scsi_cmnd *scp,
+			     struct sdebug_dev_info *devip)
 {
 	u8 *cmd = scp->cmnd;
 	struct scsi_device *sdp = scp->device;
@@ -3047,8 +3038,8 @@ resp_write_buffer(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	return 0;
 }
 
-static int
-resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_comp_write(struct scsi_cmnd *scp,
+			   struct sdebug_dev_info *devip)
 {
 	u8 *cmd = scp->cmnd;
 	u8 *arr;
@@ -3129,8 +3120,7 @@ struct unmap_block_desc {
 	__be32	__reserved;
 };
 
-static int
-resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
 	unsigned char *buf;
 	struct unmap_block_desc *desc;
@@ -3188,8 +3178,8 @@ out:
 
 #define SDEBUG_GET_LBA_STATUS_LEN 32
 
-static int
-resp_get_lba_status(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_get_lba_status(struct scsi_cmnd *scp,
+			       struct sdebug_dev_info *devip)
 {
 	u8 *cmd = scp->cmnd;
 	u64 lba;
@@ -3323,8 +3313,8 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
 	return 0;
 }
 
-static int
-resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+static int resp_xdwriteread_10(struct scsi_cmnd *scp,
+			       struct sdebug_dev_info *devip)
 {
 	u8 *cmd = scp->cmnd;
 	u64 lba;
@@ -3350,8 +3340,7 @@ resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 }
 
 /* Queued command completions converge here. */
-static void
-sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
+static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
 {
 	int qa_indx;
 	int retiring = 0;
@@ -3409,8 +3398,7 @@ sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
 }
 
 /* When high resolution timer goes off this function is called. */
-static enum hrtimer_restart
-sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
+static enum hrtimer_restart sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
 {
 	struct sdebug_defer *sd_dp = container_of(timer, struct sdebug_defer,
 						  hrt);
@@ -3419,16 +3407,15 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
 }
 
 /* When work queue schedules work, it calls this function. */
-static void
-sdebug_q_cmd_wq_complete(struct work_struct *work)
+static void sdebug_q_cmd_wq_complete(struct work_struct *work)
 {
 	struct sdebug_defer *sd_dp = container_of(work, struct sdebug_defer,
 						  ew.work);
 	sdebug_q_cmd_complete(sd_dp);
 }
 
-static struct sdebug_dev_info *
-sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
+static struct sdebug_dev_info *sdebug_device_create(
+			struct sdebug_host_info *sdbg_host, gfp_t flags)
 {
 	struct sdebug_dev_info *devip;
 
@@ -3794,9 +3781,8 @@ static void __init sdebug_build_parts(unsigned char *ramp,
 	}
 }
 
-static int
-schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
-	      int scsi_result, int delta_jiff)
+static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
+			 int scsi_result, int delta_jiff)
 {
 	unsigned long iflags;
 	int k, num_in_q, qdepth, inject;
@@ -4020,7 +4006,8 @@ static const char * scsi_debug_info(struct Scsi_Host * shp)
 }
 
 /* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */
-static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length)
+static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer,
+				 int length)
 {
 	char arr[16];
 	int opts;
@@ -4124,7 +4111,7 @@ static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
 /* Returns -EBUSY if ndelay is being changed and commands are queued */
 /* If > 0 and accepted then sdebug_jdelay is set to JDELAY_OVERRIDDEN */
 static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
-			   size_t count)
+			    size_t count)
 {
 	unsigned long iflags;
 	int ndelay, res, k;
@@ -4433,6 +4420,9 @@ static ssize_t add_host_show(struct device_driver *ddp, char *buf)
 	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_add_host);
 }
 
+static int sdebug_add_adapter(void);
+static void sdebug_remove_adapter(void);
+
 static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
 			      size_t count)
 {
@@ -4902,8 +4892,7 @@ static void sdebug_remove_adapter(void)
 	--sdebug_add_host;
 }
 
-static int
-sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
+static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
 {
 	int num_in_q = 0;
 	unsigned long iflags;
@@ -4933,8 +4922,7 @@ sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
 	return sdev->queue_depth;
 }
 
-static int
-check_inject(struct scsi_cmnd *scp)
+static int check_inject(struct scsi_cmnd *scp)
 {
 	struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
 
@@ -4965,8 +4953,8 @@ check_inject(struct scsi_cmnd *scp)
 	return 0;
 }
 
-static int
-scsi_debug_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scp)
+static int scsi_debug_queuecommand(struct Scsi_Host *shost,
+				   struct scsi_cmnd *scp)
 {
 	u8 sdeb_i;
 	struct scsi_device *sdp = scp->device;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 07/12] scsi_debug: use likely hints on fast path
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (5 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 06/12] scsi_debug: re-order file scope declarations Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:22   ` Hannes Reinecke
  2016-04-26 22:14   ` Bart Van Assche
  2016-04-25 16:16 ` [PATCH 08/12] scsi_debug: rework resp_report_luns Douglas Gilbert
                   ` (5 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

The most common commands in normal use are the READ and WRITE SCSI
commands. Use likely and unlikely hints along the path taken by
these commands. Rename check_readiness() to make_ua() and remove
associated dead code. Rename devInfoReg() to find_build_dev_info().

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 349eaeb..cf44ab0 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -190,10 +190,6 @@ static const char *sdebug_version_date = "20160422";
 #define SDEBUG_UA_MICROCODE_CHANGED_WO_RESET 6
 #define SDEBUG_NUM_UAS 7
 
-/* for check_readiness() */
-#define UAS_ONLY 1	/* check for UAs only */
-#define UAS_TUR 0	/* if no UAs then check if media access possible */
-
 /* when 1==SDEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
  * sector on read commands: */
 #define OPT_MEDIUM_ERR_ADDR   0x1234 /* that's sector 4660 in decimal */
@@ -595,6 +591,7 @@ static bool sdebug_host_lock = DEF_HOST_LOCK;
 static bool sdebug_strict = DEF_STRICT;
 static bool sdebug_any_injecting_opt;
 static bool sdebug_verbose;
+static bool have_dif_prot;
 
 static atomic_t sdebug_cmnd_count;
 static atomic_t sdebug_completions;
@@ -793,8 +790,7 @@ static void clear_luns_changed_on_target(struct sdebug_dev_info *devip)
 	spin_unlock(&sdebug_host_list_lock);
 }
 
-static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
-			   struct sdebug_dev_info * devip)
+static int make_ua(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
 	int k;
 
@@ -804,37 +800,37 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
 
 		switch (k) {
 		case SDEBUG_UA_POR:
-			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
-					UA_RESET_ASC, POWER_ON_RESET_ASCQ);
+			mk_sense_buffer(scp, UNIT_ATTENTION, UA_RESET_ASC,
+					POWER_ON_RESET_ASCQ);
 			if (sdebug_verbose)
 				cp = "power on reset";
 			break;
 		case SDEBUG_UA_BUS_RESET:
-			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
-					UA_RESET_ASC, BUS_RESET_ASCQ);
+			mk_sense_buffer(scp, UNIT_ATTENTION, UA_RESET_ASC,
+					BUS_RESET_ASCQ);
 			if (sdebug_verbose)
 				cp = "bus reset";
 			break;
 		case SDEBUG_UA_MODE_CHANGED:
-			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
-					UA_CHANGED_ASC, MODE_CHANGED_ASCQ);
+			mk_sense_buffer(scp, UNIT_ATTENTION, UA_CHANGED_ASC,
+					MODE_CHANGED_ASCQ);
 			if (sdebug_verbose)
 				cp = "mode parameters changed";
 			break;
 		case SDEBUG_UA_CAPACITY_CHANGED:
-			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
-					UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
+			mk_sense_buffer(scp, UNIT_ATTENTION, UA_CHANGED_ASC,
+					CAPACITY_CHANGED_ASCQ);
 			if (sdebug_verbose)
 				cp = "capacity data changed";
 			break;
 		case SDEBUG_UA_MICROCODE_CHANGED:
-			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
-				 TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ);
+			mk_sense_buffer(scp, UNIT_ATTENTION,
+				TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ);
 			if (sdebug_verbose)
 				cp = "microcode has been changed";
 			break;
 		case SDEBUG_UA_MICROCODE_CHANGED_WO_RESET:
-			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+			mk_sense_buffer(scp, UNIT_ATTENTION,
 					TARGET_CHANGED_ASC,
 					MICROCODE_CHANGED_WO_RESET_ASCQ);
 			if (sdebug_verbose)
@@ -851,7 +847,7 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
 			 */
 			if (sdebug_scsi_level >= 6)	/* SPC-4 and above */
 				clear_luns_changed_on_target(devip);
-			mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+			mk_sense_buffer(scp, UNIT_ATTENTION,
 					TARGET_CHANGED_ASC,
 					LUNS_CHANGED_ASCQ);
 			if (sdebug_verbose)
@@ -865,20 +861,11 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
 		}
 		clear_bit(k, devip->uas_bm);
 		if (sdebug_verbose)
-			sdev_printk(KERN_INFO, SCpnt->device,
+			sdev_printk(KERN_INFO, scp->device,
 				   "%s reports: Unit attention: %s\n",
 				   my_name, cp);
 		return check_condition_result;
 	}
-	if ((UAS_TUR == uas_only) && devip->stopped) {
-		mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY,
-				0x2);
-		if (sdebug_verbose)
-			sdev_printk(KERN_INFO, SCpnt->device,
-				    "%s reports: Not ready: %s\n", my_name,
-				    "initializing command required");
-		return check_condition_result;
-	}
 	return 0;
 }
 
@@ -1345,7 +1332,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	arr[2] = sdebug_scsi_level;
 	arr[3] = 2;    /* response_data_format==2 */
 	arr[4] = SDEBUG_LONG_INQ_SZ - 5;
-	arr[5] = sdebug_dif ? 1 : 0; /* PROTECT bit */
+	arr[5] = (int)have_dif_prot;	/* PROTECT bit */
 	if (0 == sdebug_vpd_use_hostno)
 		arr[5] = 0x10; /* claim: implicit TGPS */
 	arr[6] = 0x10; /* claim: MultiP */
@@ -2506,7 +2493,7 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		check_prot = false;
 		break;
 	}
-	if (check_prot) {
+	if (unlikely(have_dif_prot && check_prot)) {
 		if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
 		    (cmd[1] & 0xe0)) {
 			mk_sense_invalid_opcode(scp);
@@ -2518,7 +2505,7 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 			sdev_printk(KERN_ERR, scp->device, "Unprotected RD "
 				    "to DIF device\n");
 	}
-	if (sdebug_any_injecting_opt) {
+	if (unlikely(sdebug_any_injecting_opt)) {
 		struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
 
 		if (ep->inj_short)
@@ -2526,20 +2513,20 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	}
 
 	/* inline check_device_access_params() */
-	if (lba + num > sdebug_capacity) {
+	if (unlikely(lba + num > sdebug_capacity)) {
 		mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
 		return check_condition_result;
 	}
 	/* transfer length excessive (tie in to block limits VPD page) */
-	if (num > sdebug_store_sectors) {
+	if (unlikely(num > sdebug_store_sectors)) {
 		/* needs work to find which cdb byte 'num' comes from */
 		mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
 		return check_condition_result;
 	}
 
-	if ((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&
-	    (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
-	    ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
+	if (unlikely((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&
+		     (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
+		     ((lba + num) > OPT_MEDIUM_ERR_ADDR))) {
 		/* claim unrecoverable read error */
 		mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
 		/* set info field and valid bit for fixed descriptor */
@@ -2556,7 +2543,7 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	read_lock_irqsave(&atomic_rw, iflags);
 
 	/* DIX + T10 DIF */
-	if (sdebug_dix && scsi_prot_sg_count(scp)) {
+	if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
 		int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
 
 		if (prot_ret) {
@@ -2568,12 +2555,12 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 
 	ret = do_device_access(scp, lba, num, false);
 	read_unlock_irqrestore(&atomic_rw, iflags);
-	if (ret == -1)
+	if (unlikely(ret == -1))
 		return DID_ERROR << 16;
 
 	scsi_in(scp)->resid = scsi_bufflen(scp) - ret;
 
-	if (sdebug_any_injecting_opt) {
+	if (unlikely(sdebug_any_injecting_opt)) {
 		struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
 
 		if (ep->inj_recovered) {
@@ -2817,7 +2804,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 		check_prot = false;
 		break;
 	}
-	if (check_prot) {
+	if (unlikely(have_dif_prot && check_prot)) {
 		if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
 		    (cmd[1] & 0xe0)) {
 			mk_sense_invalid_opcode(scp);
@@ -2831,12 +2818,12 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	}
 
 	/* inline check_device_access_params() */
-	if (lba + num > sdebug_capacity) {
+	if (unlikely(lba + num > sdebug_capacity)) {
 		mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
 		return check_condition_result;
 	}
 	/* transfer length excessive (tie in to block limits VPD page) */
-	if (num > sdebug_store_sectors) {
+	if (unlikely(num > sdebug_store_sectors)) {
 		/* needs work to find which cdb byte 'num' comes from */
 		mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
 		return check_condition_result;
@@ -2845,7 +2832,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	write_lock_irqsave(&atomic_rw, iflags);
 
 	/* DIX + T10 DIF */
-	if (sdebug_dix && scsi_prot_sg_count(scp)) {
+	if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
 		int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
 
 		if (prot_ret) {
@@ -2856,17 +2843,17 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	}
 
 	ret = do_device_access(scp, lba, num, true);
-	if (scsi_debug_lbp())
+	if (unlikely(scsi_debug_lbp()))
 		map_region(lba, num);
 	write_unlock_irqrestore(&atomic_rw, iflags);
-	if (-1 == ret)
+	if (unlikely(-1 == ret))
 		return DID_ERROR << 16;
 	else if (sdebug_verbose && (ret < (num * sdebug_sector_size)))
 		sdev_printk(KERN_INFO, scp->device,
 			    "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
 			    my_name, num * sdebug_sector_size, ret);
 
-	if (sdebug_any_injecting_opt) {
+	if (unlikely(sdebug_any_injecting_opt)) {
 		struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
 
 		if (ep->inj_recovered) {
@@ -3351,28 +3338,28 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
 
 	atomic_inc(&sdebug_completions);
 	qa_indx = sd_dp->qa_indx;
-	if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
+	if (unlikely((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE))) {
 		pr_err("wild qa_indx=%d\n", qa_indx);
 		return;
 	}
 	spin_lock_irqsave(&queued_arr_lock, iflags);
 	sqcp = &queued_arr[qa_indx];
 	scp = sqcp->a_cmnd;
-	if (NULL == scp) {
+	if (unlikely(NULL == scp)) {
 		spin_unlock_irqrestore(&queued_arr_lock, iflags);
 		pr_err("scp is NULL\n");
 		return;
 	}
 	devip = (struct sdebug_dev_info *)scp->device->hostdata;
-	if (devip)
+	if (likely(devip))
 		atomic_dec(&devip->num_in_q);
 	else
 		pr_err("devip=NULL\n");
-	if (atomic_read(&retired_max_queue) > 0)
+	if (unlikely(atomic_read(&retired_max_queue) > 0))
 		retiring = 1;
 
 	sqcp->a_cmnd = NULL;
-	if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
+	if (unlikely(!test_and_clear_bit(qa_indx, queued_in_use_bm))) {
 		spin_unlock_irqrestore(&queued_arr_lock, iflags);
 		pr_err("Unexpected completion\n");
 		return;
@@ -3427,15 +3414,12 @@ static struct sdebug_dev_info *sdebug_device_create(
 	return devip;
 }
 
-static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
+static struct sdebug_dev_info *find_build_dev_info(struct scsi_device *sdev)
 {
-	struct sdebug_host_info * sdbg_host;
-	struct sdebug_dev_info * open_devip = NULL;
-	struct sdebug_dev_info * devip =
-			(struct sdebug_dev_info *)sdev->hostdata;
+	struct sdebug_host_info *sdbg_host;
+	struct sdebug_dev_info *open_devip = NULL;
+	struct sdebug_dev_info *devip;
 
-	if (devip)
-		return devip;
 	sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
 	if (!sdbg_host) {
 		pr_err("Host info NULL\n");
@@ -3480,16 +3464,19 @@ static int scsi_debug_slave_alloc(struct scsi_device *sdp)
 
 static int scsi_debug_slave_configure(struct scsi_device *sdp)
 {
-	struct sdebug_dev_info *devip;
+	struct sdebug_dev_info *devip =
+			(struct sdebug_dev_info *)sdp->hostdata;
 
 	if (sdebug_verbose)
 		pr_info("slave_configure <%u %u %u %llu>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
 		sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
-	devip = devInfoReg(sdp);
-	if (NULL == devip)
-		return 1;	/* no resources, will be marked offline */
+	if (NULL == devip) {
+		devip = find_build_dev_info(sdp);
+		if (NULL == devip)
+			return 1;  /* no resources, will be marked offline */
+	}
 	sdp->hostdata = devip;
 	blk_queue_max_segment_size(sdp->request_queue, -1U);
 	if (sdebug_no_uld)
@@ -3622,15 +3609,14 @@ static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
 
 static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
 {
-	struct sdebug_dev_info * devip;
-
 	++num_dev_resets;
 	if (SCpnt && SCpnt->device) {
 		struct scsi_device *sdp = SCpnt->device;
+		struct sdebug_dev_info *devip =
+				(struct sdebug_dev_info *)sdp->hostdata;
 
 		if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
 			sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
-		devip = devInfoReg(sdp);
 		if (devip)
 			set_bit(SDEBUG_UA_POR, devip->uas_bm);
 	}
@@ -3790,19 +3776,18 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 	struct scsi_device *sdp;
 	struct sdebug_defer *sd_dp;
 
-	/* this should never happen */
-	if (WARN_ON(!cmnd))
+	if (unlikely(WARN_ON(!cmnd)))
 		return SCSI_MLQUEUE_HOST_BUSY;
 
-	if (NULL == devip) {
-		pr_warn("called devip == NULL\n");
-		/* no particularly good error to report back */
-		return SCSI_MLQUEUE_HOST_BUSY;
+	if (unlikely(NULL == devip)) {
+		if (0 == scsi_result)
+			scsi_result = DID_NO_CONNECT << 16;
+		goto respond_in_thread;
 	}
 
 	sdp = cmnd->device;
 
-	if (sdebug_verbose && scsi_result)
+	if (unlikely(sdebug_verbose && scsi_result))
 		sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
 			    __func__, scsi_result);
 	if (delta_jiff == 0)
@@ -3813,15 +3798,15 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 	num_in_q = atomic_read(&devip->num_in_q);
 	qdepth = cmnd->device->queue_depth;
 	inject = 0;
-	if ((qdepth > 0) && (num_in_q >= qdepth)) {
+	if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) {
 		if (scsi_result) {
 			spin_unlock_irqrestore(&queued_arr_lock, iflags);
 			goto respond_in_thread;
 		} else
 			scsi_result = device_qfull_result;
-	} else if ((sdebug_every_nth != 0) &&
-		   (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
-		   (scsi_result == 0)) {
+	} else if (unlikely((sdebug_every_nth != 0) &&
+			    (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
+			    (scsi_result == 0))) {
 		if ((num_in_q == (qdepth - 1)) &&
 		    (atomic_inc_return(&sdebug_a_tsf) >=
 		     abs(sdebug_every_nth))) {
@@ -3832,7 +3817,7 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 	}
 
 	k = find_first_zero_bit(queued_in_use_bm, sdebug_max_queue);
-	if (k >= sdebug_max_queue) {
+	if (unlikely(k >= sdebug_max_queue)) {
 		spin_unlock_irqrestore(&queued_arr_lock, iflags);
 		if (scsi_result)
 			goto respond_in_thread;
@@ -3888,8 +3873,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 		}
 		schedule_work(&sd_dp->ew.work);
 	}
-	if ((SDEBUG_OPT_Q_NOISE & sdebug_opts) &&
-	    (scsi_result == device_qfull_result))
+	if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) &&
+		     (scsi_result == device_qfull_result)))
 		sdev_printk(KERN_INFO, sdp,
 			    "%s: num_in_q=%d +1, %s%s\n", __func__,
 			    num_in_q, (inject ? "<inject> " : ""),
@@ -4632,9 +4617,11 @@ static int __init scsi_debug_init(void)
 	switch (sdebug_dif) {
 
 	case SD_DIF_TYPE0_PROTECTION:
+		break;
 	case SD_DIF_TYPE1_PROTECTION:
 	case SD_DIF_TYPE2_PROTECTION:
 	case SD_DIF_TYPE3_PROTECTION:
+		have_dif_prot = true;
 		break;
 
 	default:
@@ -4971,7 +4958,8 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
 	bool has_wlun_rl;
 
 	scsi_set_resid(scp, 0);
-	if (sdebug_verbose && !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts)) {
+	if (unlikely(sdebug_verbose &&
+		     !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts))) {
 		char b[120];
 		int n, len, sb;
 
@@ -4987,17 +4975,16 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
 		sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
 	}
 	has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS);
-	if ((sdp->lun >= sdebug_max_luns) && !has_wlun_rl)
-		return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, 0);
+	if (unlikely((sdp->lun >= sdebug_max_luns) && !has_wlun_rl))
+		goto err_out;
 
 	sdeb_i = opcode_ind_arr[opcode];	/* fully mapped */
 	oip = &opcode_info_arr[sdeb_i];		/* safe if table consistent */
 	devip = (struct sdebug_dev_info *)sdp->hostdata;
-	if (!devip) {
-		devip = devInfoReg(sdp);
+	if (unlikely(!devip)) {
+		devip = find_build_dev_info(sdp);
 		if (NULL == devip)
-			return schedule_resp(scp, NULL, DID_NO_CONNECT << 16,
-					     0);
+			goto err_out;
 	}
 	na = oip->num_attached;
 	r_pfp = oip->pfp;
@@ -5029,18 +5016,18 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
 		}
 	}	/* else (when na==0) we assume the oip is a match */
 	flags = oip->flags;
-	if (F_INV_OP & flags) {
+	if (unlikely(F_INV_OP & flags)) {
 		mk_sense_invalid_opcode(scp);
 		goto check_cond;
 	}
-	if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) {
+	if (unlikely(has_wlun_rl && !(F_RL_WLUN_OK & flags))) {
 		if (sdebug_verbose)
 			sdev_printk(KERN_INFO, sdp, "%s: Opcode 0x%x not%s\n",
 				    my_name, opcode, " supported for wlun");
 		mk_sense_invalid_opcode(scp);
 		goto check_cond;
 	}
-	if (sdebug_strict) {	/* check cdb against mask */
+	if (unlikely(sdebug_strict)) {	/* check cdb against mask */
 		u8 rem;
 		int j;
 
@@ -5056,13 +5043,14 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
 			}
 		}
 	}
-	if (!(F_SKIP_UA & flags) &&
-	    SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS)) {
-		errsts = check_readiness(scp, UAS_ONLY, devip);
+	if (unlikely(!(F_SKIP_UA & flags) &&
+		     SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm,
+						      SDEBUG_NUM_UAS))) {
+		errsts = make_ua(scp, devip);
 		if (errsts)
 			goto check_cond;
 	}
-	if ((F_M_ACCESS & flags) && devip->stopped) {
+	if (unlikely((F_M_ACCESS & flags) && devip->stopped)) {
 		mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
 		if (sdebug_verbose)
 			sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
@@ -5073,12 +5061,12 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
 	}
 	if (sdebug_fake_rw && (F_FAKE_RW & flags))
 		goto fini;
-	if (sdebug_every_nth) {
+	if (unlikely(sdebug_every_nth)) {
 		if (check_inject(scp))
 			return 0;	/* ignore command: make trouble */
 	}
-	if (oip->pfp)	/* if this command has a resp_* function, call it */
-		errsts = oip->pfp(scp, devip);
+	if (likely(oip->pfp))
+		errsts = oip->pfp(scp, devip);	/* calls a resp_* function */
 	else if (r_pfp)	/* if leaf function ptr NULL, try the root's */
 		errsts = r_pfp(scp, devip);
 
@@ -5087,6 +5075,8 @@ fini:
 			     ((F_DELAY_OVERR & flags) ? 0 : sdebug_jdelay));
 check_cond:
 	return schedule_resp(scp, devip, check_condition_result, 0);
+err_out:
+	return schedule_resp(scp, NULL, DID_NO_CONNECT << 16, 0);
 }
 
 static struct scsi_host_template sdebug_driver_template = {
@@ -5122,7 +5112,7 @@ static int sdebug_driver_probe(struct device * dev)
 	int error = 0;
 	struct sdebug_host_info *sdbg_host;
 	struct Scsi_Host *hpnt;
-	int host_prot;
+	int hprot;
 
 	sdbg_host = to_sdebug_host(dev);
 
@@ -5145,44 +5135,45 @@ static int sdebug_driver_probe(struct device * dev)
 	/* = sdebug_max_luns; */
 	hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
 
-	host_prot = 0;
+	hprot = 0;
 
 	switch (sdebug_dif) {
 
 	case SD_DIF_TYPE1_PROTECTION:
-		host_prot = SHOST_DIF_TYPE1_PROTECTION;
+		hprot = SHOST_DIF_TYPE1_PROTECTION;
 		if (sdebug_dix)
-			host_prot |= SHOST_DIX_TYPE1_PROTECTION;
+			hprot |= SHOST_DIX_TYPE1_PROTECTION;
 		break;
 
 	case SD_DIF_TYPE2_PROTECTION:
-		host_prot = SHOST_DIF_TYPE2_PROTECTION;
+		hprot = SHOST_DIF_TYPE2_PROTECTION;
 		if (sdebug_dix)
-			host_prot |= SHOST_DIX_TYPE2_PROTECTION;
+			hprot |= SHOST_DIX_TYPE2_PROTECTION;
 		break;
 
 	case SD_DIF_TYPE3_PROTECTION:
-		host_prot = SHOST_DIF_TYPE3_PROTECTION;
+		hprot = SHOST_DIF_TYPE3_PROTECTION;
 		if (sdebug_dix)
-			host_prot |= SHOST_DIX_TYPE3_PROTECTION;
+			hprot |= SHOST_DIX_TYPE3_PROTECTION;
 		break;
 
 	default:
 		if (sdebug_dix)
-			host_prot |= SHOST_DIX_TYPE0_PROTECTION;
+			hprot |= SHOST_DIX_TYPE0_PROTECTION;
 		break;
 	}
 
-	scsi_host_set_prot(hpnt, host_prot);
+	scsi_host_set_prot(hpnt, hprot);
 
-	pr_info("host protection%s%s%s%s%s%s%s\n",
-	       (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
-	       (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
-	       (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
-	       (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
-	       (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
-	       (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
-	       (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
+	if (have_dif_prot || sdebug_dix)
+		pr_info("host protection%s%s%s%s%s%s%s\n",
+			(hprot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
+			(hprot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
+			(hprot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
+			(hprot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
+			(hprot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
+			(hprot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
+			(hprot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
 
 	if (sdebug_guard == 1)
 		scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 08/12] scsi_debug: rework resp_report_luns
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (6 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 07/12] scsi_debug: use likely hints on fast path Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:26   ` Hannes Reinecke
                     ` (2 more replies)
  2016-04-25 16:16 ` [PATCH 09/12] scsi_debug: add multiple queue support Douglas Gilbert
                   ` (4 subsequent siblings)
  12 siblings, 3 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Based on "[PATH V2] scsi_debug: rework resp_report_luns" patch
sent by Tomas Winkler on Thursday, 26 Feb 2015. His notes:
  1. Remove duplicated boundary checks which simplify the fill-in
     loop
  2. Use more of scsi generic API
Replace fixed length response array a with heap allocation
allowing up to 16383 LUNs per target.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index cf44ab0..eac62b8 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3205,63 +3205,99 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
 	return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
 }
 
-#define SDEBUG_RLUN_ARR_SZ 256
-
-static int resp_report_luns(struct scsi_cmnd * scp,
-			    struct sdebug_dev_info * devip)
+/* Even though each pseudo target has a REPORT LUNS "well known logical unit"
+ * (W-LUN), the normal Linux scanning logic does not associate it with a
+ * device (e.g. /dev/sg7). The following magic will make that association:
+ *   "cd /sys/class/scsi_host/host<n> ; echo '- - 49409' > scan"
+ * where <n> is a host number. If there are multiple targets in a host then
+ * the above will associate a W-LUN to each target. To only get a W-LUN
+ * for target 2, then use "echo '- 2 49409' > scan" . */
+static int resp_report_luns(struct scsi_cmnd *scp,
+			    struct sdebug_dev_info *devip)
 {
+	unsigned char *cmd = scp->cmnd;
 	unsigned int alloc_len;
-	int lun_cnt, i, upper, num, n, want_wlun, shortish;
+	unsigned char select_report;
 	u64 lun;
-	unsigned char *cmd = scp->cmnd;
-	int select_report = (int)cmd[2];
-	struct scsi_lun *one_lun;
-	unsigned char arr[SDEBUG_RLUN_ARR_SZ];
-	unsigned char * max_addr;
+	struct scsi_lun *lun_p;
+	u8 *arr;
+	unsigned int lun_cnt;	/* normal LUN count (max: 16383) */
+	unsigned int wlun_cnt;	/* report luns W-LUN count */
+	unsigned int tlun_cnt;	/* total LUN count */
+	unsigned int rlen;	/* response length (in bytes) less header */
+	int i, res;
 
 	clear_luns_changed_on_target(devip);
-	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
-	shortish = (alloc_len < 4);
-	if (shortish || (select_report > 2)) {
-		mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
+
+	select_report = cmd[2];
+	alloc_len = get_unaligned_be32(cmd + 6);
+
+	if (alloc_len < 4) {
+		pr_err("alloc len too small %d\n", alloc_len);
+		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
 		return check_condition_result;
 	}
-	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
-	memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
+
+	if (select_report > 0x02) {
+		pr_err("select report invalid %d\n", select_report);
+		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
+		return check_condition_result;
+	}
+
 	lun_cnt = sdebug_max_luns;
-	if (1 == select_report)
+	wlun_cnt = 0;
+
+	/* report only w_lun */
+	if (select_report == 0x01)
 		lun_cnt = 0;
-	else if (sdebug_no_lun_0 && (lun_cnt > 0))
+
+	if (sdebug_no_lun_0 && (lun_cnt > 0))
 		--lun_cnt;
-	want_wlun = (select_report > 0) ? 1 : 0;
-	num = lun_cnt + want_wlun;
-	arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
-	arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
-	n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
-			    sizeof(struct scsi_lun)), num);
-	if (n < num) {
-		want_wlun = 0;
-		lun_cnt = n;
-	}
-	one_lun = (struct scsi_lun *) &arr[8];
-	max_addr = arr + SDEBUG_RLUN_ARR_SZ;
-	for (i = 0, lun = (sdebug_no_lun_0 ? 1 : 0);
-             ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
-	     i++, lun++) {
-		upper = (lun >> 8) & 0x3f;
-		if (upper)
-			one_lun[i].scsi_lun[0] =
-			    (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
-		one_lun[i].scsi_lun[1] = lun & 0xff;
-	}
-	if (want_wlun) {
-		one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff;
-		one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
-		i++;
-	}
-	alloc_len = (unsigned char *)(one_lun + i) - arr;
-	return fill_from_dev_buffer(scp, arr,
-				    min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
+
+	/* report w_lun */
+	if (select_report == 0x01 || select_report == 0x02)
+		wlun_cnt = 1;
+
+	tlun_cnt = lun_cnt + wlun_cnt;
+	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
+	arr = kzalloc((tlun_cnt * sizeof(lun_p->scsi_lun)) + 8, GFP_ATOMIC);
+	if (!arr) {
+		pr_warn("No space for report luns response\n");
+		mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
+				INSUFF_RES_ASCQ);
+		return check_condition_result;
+	}
+	pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n",
+		 select_report, lun_cnt, wlun_cnt, sdebug_no_lun_0);
+
+	lun = 0LL;
+	/* luns start at offset 8 after the byte length */
+	lun_p = (struct scsi_lun *)&arr[8];
+
+	/* skip lun 0 */
+	if (sdebug_no_lun_0)
+		lun++;
+	/*
+	 * Address method (we use Peripherial = 00b)
+	 * 10b - Logical unit
+	 * 00b - Peripherial device - Use this one
+	 * 01b - Logical device
+	 * 11b - reserved
+	 */
+	for (i = 0; i < lun_cnt; i++)
+		int_to_scsilun(lun++, lun_p++);
+
+	/* report SCSI_W_LUN_REPORT_LUN */
+	if (wlun_cnt)
+		int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, lun_p++);
+
+	rlen = tlun_cnt * sizeof(struct scsi_lun);
+
+	put_unaligned_be32(rlen, &arr[0]);
+
+	res = fill_from_dev_buffer(scp, arr, rlen + 8);
+	kfree(arr);
+	return res;
 }
 
 static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
@@ -4299,6 +4335,10 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
 	bool changed;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+		if (n > 16383) {
+			pr_warn("max_luns can be no more than 16383\n");
+			return -EINVAL;
+		}
 		changed = (sdebug_max_luns != n);
 		sdebug_max_luns = n;
 		sdebug_max_tgts_luns();
@@ -4643,6 +4683,10 @@ static int __init scsi_debug_init(void)
 		pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp);
 		return -EINVAL;
 	}
+	if (sdebug_max_luns > 16383) {
+		pr_warn("max_luns can be no more than 16383, use default\n");
+		sdebug_max_luns = DEF_MAX_LUNS;
+	}
 
 	if (sdebug_lowest_aligned > 0x3fff) {
 		pr_err("lowest_aligned too big: %u\n", sdebug_lowest_aligned);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 09/12] scsi_debug: add multiple queue support
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (7 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 08/12] scsi_debug: rework resp_report_luns Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:29   ` Hannes Reinecke
  2016-04-26 22:19   ` Bart Van Assche
  2016-04-25 16:16 ` [PATCH 10/12] scsi_debug: vpd and mode page work Douglas Gilbert
                   ` (3 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Add submit_queue parameter (minimum and default: 1; maximum:
nr_cpu_ids) that controls how many queues are built, each with
their own lock and in_use bit vector. Add statistics parameter
which is default on.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index eac62b8..bdc9ece 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -135,6 +135,8 @@ static const char *sdebug_version_date = "20160422";
 #define DEF_VPD_USE_HOSTNO 1
 #define DEF_WRITESAME_LENGTH 0xFFFF
 #define DEF_STRICT 0
+#define DEF_STATISTICS true
+#define DEF_SUBMIT_QUEUES 1
 #define JDELAY_OVERRIDDEN -9999
 
 /* bit mask values for sdebug_opts */
@@ -200,19 +202,14 @@ static const char *sdebug_version_date = "20160422";
 #define SAM2_LUN_ADDRESS_METHOD 0
 
 /* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
- * (for response) at one time. Can be reduced by max_queue option. Command
- * responses are not queued when jdelay=0 and ndelay=0. The per-device
- * DEF_CMD_PER_LUN can be changed via sysfs:
- * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
- * SCSI_DEBUG_CANQUEUE. */
-#define SCSI_DEBUG_CANQUEUE_WORDS  9	/* a WORD is bits in a long */
+ * (for response) per submit queue at one time. Can be reduced by max_queue
+ * option. Command responses are not queued when jdelay=0 and ndelay=0. The
+ * per-device DEF_CMD_PER_LUN can be changed via sysfs:
+ * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but . */
+#define SCSI_DEBUG_CANQUEUE_WORDS  3	/* a WORD is bits in a long */
 #define SCSI_DEBUG_CANQUEUE  (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
 #define DEF_CMD_PER_LUN  255
 
-#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE
-#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
-#endif
-
 #define F_D_IN			1
 #define F_D_OUT			2
 #define F_D_OUT_MAYBE		4	/* WRITE SAME, NDOB bit */
@@ -243,7 +240,7 @@ struct sdebug_dev_info {
 	struct sdebug_host_info *sdbg_host;
 	unsigned long uas_bm[1];
 	atomic_t num_in_q;
-	char stopped;		/* TODO: should be atomic */
+	atomic_t stopped;
 	bool used;
 };
 
@@ -260,21 +257,30 @@ struct sdebug_host_info {
 struct sdebug_defer {
 	struct hrtimer hrt;
 	struct execute_work ew;
-	int qa_indx;
+	int qc_indx;
+	int sq_indx;
 };
 
 struct sdebug_queued_cmd {
-	/* in_use flagged by a bit in queued_in_use_bm[] */
+	/* a bit in in_use_bm[] in struct sdebug_queue flags if in use */
 	struct sdebug_defer *sd_dp;
 	struct scsi_cmnd *a_cmnd;
+	unsigned int inj_recovered:1;
+	unsigned int inj_transport:1;
+	unsigned int inj_dif:1;
+	unsigned int inj_dix:1;
+	unsigned int inj_short:1;
 };
 
-struct sdebug_scmd_extra_t {
-	bool inj_recovered;
-	bool inj_transport;
-	bool inj_dif;
-	bool inj_dix;
-	bool inj_short;
+struct sdebug_queue {
+	struct sdebug_queued_cmd qc_arr[SCSI_DEBUG_CANQUEUE];
+	unsigned long in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
+	spinlock_t qc_lock;
+	atomic_t blocked;	/* to temporarily stop more being queued */
+	atomic_t cmnd_count;	/* number of incoming commands */
+	atomic_t completions;	/* only command with deferred responses */
+	atomic_t misqueues;	/* completion q different from submission q */
+	atomic_t a_tsf;		/* 'almost task set full' event counter */
 };
 
 struct opcode_info_t {
@@ -324,6 +330,7 @@ enum sdeb_opcode_index {
 	SDEB_I_LAST_ELEMENT = 30,	/* keep this last */
 };
 
+
 static const unsigned char opcode_ind_arr[256] = {
 /* 0x0; 0x0->0x1f: 6 byte cdbs */
 	SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE,
@@ -561,7 +568,7 @@ static int sdebug_fake_rw = DEF_FAKE_RW;
 static unsigned int sdebug_guard = DEF_GUARD;
 static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED;
 static int sdebug_max_luns = DEF_MAX_LUNS;
-static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE;
+static int sdebug_max_queue = SCSI_DEBUG_CANQUEUE;	/* per submit queue */
 static atomic_t retired_max_queue;	/* if > 0 then was prior max_queue */
 static int sdebug_ndelay = DEF_NDELAY;	/* if > 0 then unit is nanoseconds */
 static int sdebug_no_lun_0 = DEF_NO_LUN_0;
@@ -592,10 +599,8 @@ static bool sdebug_strict = DEF_STRICT;
 static bool sdebug_any_injecting_opt;
 static bool sdebug_verbose;
 static bool have_dif_prot;
-
-static atomic_t sdebug_cmnd_count;
-static atomic_t sdebug_completions;
-static atomic_t sdebug_a_tsf;		/* counter of 'almost' TSFs */
+static bool sdebug_statistics = DEF_STATISTICS;
+static bool sdebug_mq_available;
 
 static unsigned int sdebug_store_sectors;
 static sector_t sdebug_capacity;	/* in sectors */
@@ -623,10 +628,9 @@ static int dix_writes;
 static int dix_reads;
 static int dif_errors;
 
-static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
-static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS];
+static int submit_queues = DEF_SUBMIT_QUEUES;  /* > 1 for multi-queue (mq) */
+static struct sdebug_queue *sdebug_q_arr;  /* ptr to array of submit queues */
 
-static DEFINE_SPINLOCK(queued_arr_lock);
 static DEFINE_RWLOCK(atomic_rw);
 
 static char sdebug_proc_name[] = MY_NAME;
@@ -1425,16 +1429,15 @@ static int resp_start_stop(struct scsi_cmnd * scp,
 			   struct sdebug_dev_info * devip)
 {
 	unsigned char *cmd = scp->cmnd;
-	int power_cond, start;
+	int power_cond, stop;
 
 	power_cond = (cmd[4] & 0xf0) >> 4;
 	if (power_cond) {
 		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
 		return check_condition_result;
 	}
-	start = cmd[4] & 1;
-	if (start == devip->stopped)
-		devip->stopped = !start;
+	stop = !(cmd[4] & 1);
+	atomic_xchg(&devip->stopped, stop);
 	return 0;
 }
 
@@ -2447,6 +2450,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
 static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
 	u8 *cmd = scp->cmnd;
+	struct sdebug_queued_cmd *sqcp;
 	u64 lba;
 	u32 num;
 	u32 ei_lba;
@@ -2506,11 +2510,14 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 				    "to DIF device\n");
 	}
 	if (unlikely(sdebug_any_injecting_opt)) {
-		struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
+		sqcp = (struct sdebug_queued_cmd *)scp->host_scribble;
 
-		if (ep->inj_short)
-			num /= 2;
-	}
+		if (sqcp) {
+			if (sqcp->inj_short)
+				num /= 2;
+		}
+	} else
+		sqcp = NULL;
 
 	/* inline check_device_access_params() */
 	if (unlikely(lba + num > sdebug_capacity)) {
@@ -2560,22 +2567,20 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 
 	scsi_in(scp)->resid = scsi_bufflen(scp) - ret;
 
-	if (unlikely(sdebug_any_injecting_opt)) {
-		struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
-
-		if (ep->inj_recovered) {
+	if (unlikely(sqcp)) {
+		if (sqcp->inj_recovered) {
 			mk_sense_buffer(scp, RECOVERED_ERROR,
 					THRESHOLD_EXCEEDED, 0);
 			return check_condition_result;
-		} else if (ep->inj_transport) {
+		} else if (sqcp->inj_transport) {
 			mk_sense_buffer(scp, ABORTED_COMMAND,
 					TRANSPORT_PROBLEM, ACK_NAK_TO);
 			return check_condition_result;
-		} else if (ep->inj_dif) {
+		} else if (sqcp->inj_dif) {
 			/* Logical block guard check failed */
 			mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
 			return illegal_condition_result;
-		} else if (ep->inj_dix) {
+		} else if (sqcp->inj_dix) {
 			mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
 			return illegal_condition_result;
 		}
@@ -2848,25 +2853,29 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	write_unlock_irqrestore(&atomic_rw, iflags);
 	if (unlikely(-1 == ret))
 		return DID_ERROR << 16;
-	else if (sdebug_verbose && (ret < (num * sdebug_sector_size)))
+	else if (unlikely(sdebug_verbose &&
+			  (ret < (num * sdebug_sector_size))))
 		sdev_printk(KERN_INFO, scp->device,
 			    "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
 			    my_name, num * sdebug_sector_size, ret);
 
 	if (unlikely(sdebug_any_injecting_opt)) {
-		struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
+		struct sdebug_queued_cmd *sqcp =
+				(struct sdebug_queued_cmd *)scp->host_scribble;
 
-		if (ep->inj_recovered) {
-			mk_sense_buffer(scp, RECOVERED_ERROR,
-					THRESHOLD_EXCEEDED, 0);
-			return check_condition_result;
-		} else if (ep->inj_dif) {
-			/* Logical block guard check failed */
-			mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
-			return illegal_condition_result;
-		} else if (ep->inj_dix) {
-			mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
-			return illegal_condition_result;
+		if (sqcp) {
+			if (sqcp->inj_recovered) {
+				mk_sense_buffer(scp, RECOVERED_ERROR,
+						THRESHOLD_EXCEEDED, 0);
+				return check_condition_result;
+			} else if (sqcp->inj_dif) {
+				/* Logical block guard check failed */
+				mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+				return illegal_condition_result;
+			} else if (sqcp->inj_dix) {
+				mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+				return illegal_condition_result;
+			}
 		}
 	}
 	return 0;
@@ -3362,27 +3371,40 @@ static int resp_xdwriteread_10(struct scsi_cmnd *scp,
 	return resp_xdwriteread(scp, lba, num, devip);
 }
 
+static struct sdebug_queue *get_queue(void)
+{
+	struct sdebug_queue *sqp = sdebug_q_arr;
+
+	return sqp + (raw_smp_processor_id() % submit_queues);
+}
+
 /* Queued command completions converge here. */
 static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
 {
-	int qa_indx;
+	int qc_indx;
 	int retiring = 0;
 	unsigned long iflags;
+	struct sdebug_queue *sqp;
 	struct sdebug_queued_cmd *sqcp;
 	struct scsi_cmnd *scp;
 	struct sdebug_dev_info *devip;
 
-	atomic_inc(&sdebug_completions);
-	qa_indx = sd_dp->qa_indx;
-	if (unlikely((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE))) {
-		pr_err("wild qa_indx=%d\n", qa_indx);
+	sqp = sdebug_q_arr + sd_dp->sq_indx;
+	if (sdebug_statistics) {
+		atomic_inc(&sqp->completions);
+		if (get_queue() != sqp)
+			atomic_inc(&sqp->misqueues);
+	}
+	qc_indx = sd_dp->qc_indx;
+	if (unlikely((qc_indx < 0) || (qc_indx >= SCSI_DEBUG_CANQUEUE))) {
+		pr_err("wild qc_indx=%d\n", qc_indx);
 		return;
 	}
-	spin_lock_irqsave(&queued_arr_lock, iflags);
-	sqcp = &queued_arr[qa_indx];
+	spin_lock_irqsave(&sqp->qc_lock, iflags);
+	sqcp = &sqp->qc_arr[qc_indx];
 	scp = sqcp->a_cmnd;
 	if (unlikely(NULL == scp)) {
-		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		spin_unlock_irqrestore(&sqp->qc_lock, iflags);
 		pr_err("scp is NULL\n");
 		return;
 	}
@@ -3395,8 +3417,8 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
 		retiring = 1;
 
 	sqcp->a_cmnd = NULL;
-	if (unlikely(!test_and_clear_bit(qa_indx, queued_in_use_bm))) {
-		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+	if (unlikely(!test_and_clear_bit(qc_indx, sqp->in_use_bm))) {
+		spin_unlock_irqrestore(&sqp->qc_lock, iflags);
 		pr_err("Unexpected completion\n");
 		return;
 	}
@@ -3405,18 +3427,18 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
 		int k, retval;
 
 		retval = atomic_read(&retired_max_queue);
-		if (qa_indx >= retval) {
-			spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		if (qc_indx >= retval) {
+			spin_unlock_irqrestore(&sqp->qc_lock, iflags);
 			pr_err("index %d too large\n", retval);
 			return;
 		}
-		k = find_last_bit(queued_in_use_bm, retval);
+		k = find_last_bit(sqp->in_use_bm, retval);
 		if ((k < sdebug_max_queue) || (k == retval))
 			atomic_set(&retired_max_queue, 0);
 		else
 			atomic_set(&retired_max_queue, k + 1);
 	}
-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+	spin_unlock_irqrestore(&sqp->qc_lock, iflags);
 	scp->scsi_done(scp); /* callback to mid level */
 }
 
@@ -3535,47 +3557,53 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp)
 	}
 }
 
+static void stop_qc_helper(struct sdebug_defer *sd_dp)
+{
+	if (!sd_dp)
+		return;
+	if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0))
+		hrtimer_cancel(&sd_dp->hrt);
+	else if (sdebug_jdelay < 0)
+		cancel_work_sync(&sd_dp->ew.work);
+}
+
 /* If @cmnd found deletes its timer or work queue and returns true; else
    returns false */
 static bool stop_queued_cmnd(struct scsi_cmnd *cmnd)
 {
 	unsigned long iflags;
-	int k, qmax, r_qmax;
+	int j, k, qmax, r_qmax;
+	struct sdebug_queue *sqp;
 	struct sdebug_queued_cmd *sqcp;
 	struct sdebug_dev_info *devip;
 	struct sdebug_defer *sd_dp;
 
-	spin_lock_irqsave(&queued_arr_lock, iflags);
-	qmax = sdebug_max_queue;
-	r_qmax = atomic_read(&retired_max_queue);
-	if (r_qmax > qmax)
-		qmax = r_qmax;
-	for (k = 0; k < qmax; ++k) {
-		if (test_bit(k, queued_in_use_bm)) {
-			sqcp = &queued_arr[k];
-			if (cmnd != sqcp->a_cmnd)
-				continue;
-			/* found command */
-			devip = (struct sdebug_dev_info *)
-				cmnd->device->hostdata;
-			if (devip)
-				atomic_dec(&devip->num_in_q);
-			sqcp->a_cmnd = NULL;
-			sd_dp = sqcp->sd_dp;
-			spin_unlock_irqrestore(&queued_arr_lock,
-					       iflags);
-			if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) {
-				if (sd_dp)
-					hrtimer_cancel(&sd_dp->hrt);
-			} else if (sdebug_jdelay < 0) {
-				if (sd_dp)
-					cancel_work_sync(&sd_dp->ew.work);
+	for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) {
+		spin_lock_irqsave(&sqp->qc_lock, iflags);
+		qmax = sdebug_max_queue;
+		r_qmax = atomic_read(&retired_max_queue);
+		if (r_qmax > qmax)
+			qmax = r_qmax;
+		for (k = 0; k < qmax; ++k) {
+			if (test_bit(k, sqp->in_use_bm)) {
+				sqcp = &sqp->qc_arr[k];
+				if (cmnd != sqcp->a_cmnd)
+					continue;
+				/* found */
+				devip = (struct sdebug_dev_info *)
+						cmnd->device->hostdata;
+				if (devip)
+					atomic_dec(&devip->num_in_q);
+				sqcp->a_cmnd = NULL;
+				sd_dp = sqcp->sd_dp;
+				spin_unlock_irqrestore(&sqp->qc_lock, iflags);
+				stop_qc_helper(sd_dp);
+				clear_bit(k, sqp->in_use_bm);
+				return true;
 			}
-			clear_bit(k, queued_in_use_bm);
-			return true;
 		}
+		spin_unlock_irqrestore(&sqp->qc_lock, iflags);
 	}
-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 	return false;
 }
 
@@ -3583,48 +3611,48 @@ static bool stop_queued_cmnd(struct scsi_cmnd *cmnd)
 static void stop_all_queued(void)
 {
 	unsigned long iflags;
-	int k;
+	int j, k;
+	struct sdebug_queue *sqp;
 	struct sdebug_queued_cmd *sqcp;
 	struct sdebug_dev_info *devip;
 	struct sdebug_defer *sd_dp;
 
-	spin_lock_irqsave(&queued_arr_lock, iflags);
-	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
-		if (test_bit(k, queued_in_use_bm)) {
-			sqcp = &queued_arr[k];
-			if (NULL == sqcp->a_cmnd)
-				continue;
-			devip = (struct sdebug_dev_info *)
-				sqcp->a_cmnd->device->hostdata;
-			if (devip)
-				atomic_dec(&devip->num_in_q);
-			sqcp->a_cmnd = NULL;
-			sd_dp = sqcp->sd_dp;
-			spin_unlock_irqrestore(&queued_arr_lock, iflags);
-			if ((sdebug_jdelay > 0) || (sdebug_ndelay > 0)) {
-				if (sd_dp)
-					hrtimer_cancel(&sd_dp->hrt);
-			} else if (sdebug_jdelay < 0) {
-				if (sd_dp)
-					cancel_work_sync(&sd_dp->ew.work);
+	for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) {
+		spin_lock_irqsave(&sqp->qc_lock, iflags);
+		for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+			if (test_bit(k, sqp->in_use_bm)) {
+				sqcp = &sqp->qc_arr[k];
+				if (NULL == sqcp->a_cmnd)
+					continue;
+				devip = (struct sdebug_dev_info *)
+					sqcp->a_cmnd->device->hostdata;
+				if (devip)
+					atomic_dec(&devip->num_in_q);
+				sqcp->a_cmnd = NULL;
+				sd_dp = sqcp->sd_dp;
+				spin_unlock_irqrestore(&sqp->qc_lock, iflags);
+				stop_qc_helper(sd_dp);
+				clear_bit(k, sqp->in_use_bm);
+				spin_lock_irqsave(&sqp->qc_lock, iflags);
 			}
-			clear_bit(k, queued_in_use_bm);
-			spin_lock_irqsave(&queued_arr_lock, iflags);
 		}
+		spin_unlock_irqrestore(&sqp->qc_lock, iflags);
 	}
-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
 /* Free queued command memory on heap */
 static void free_all_queued(void)
 {
-	int k;
+	int j, k;
+	struct sdebug_queue *sqp;
 	struct sdebug_queued_cmd *sqcp;
 
-	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
-		sqcp = &queued_arr[k];
-		kfree(sqcp->sd_dp);
-		sqcp->sd_dp = NULL;
+	for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) {
+		for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+			sqcp = &sqp->qc_arr[k];
+			kfree(sqcp->sd_dp);
+			sqcp->sd_dp = NULL;
+		}
 	}
 }
 
@@ -3803,24 +3831,77 @@ static void __init sdebug_build_parts(unsigned char *ramp,
 	}
 }
 
+static void block_unblock_all_queues(bool block)
+{
+	int j;
+	struct sdebug_queue *sqp;
+
+	for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp)
+		atomic_set(&sqp->blocked, (int)block);
+}
+
+/* Adjust (by rounding down) each cmnd_count so abs(every_nth)-1 commands
+ * will be processed normally on each queue before triggers occur. */
+static void tweak_cmnd_count(void)
+{
+	int j, count, modulo;
+	struct sdebug_queue *sqp;
+
+	modulo = abs(sdebug_every_nth);
+	if (modulo < 2)
+		return;
+	block_unblock_all_queues(true);
+	for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) {
+		count = atomic_read(&sqp->cmnd_count);
+		atomic_set(&sqp->cmnd_count, (count / modulo) * modulo);
+	}
+	block_unblock_all_queues(false);
+}
+
+static void clear_queue_stats(void)
+{
+	int j;
+	struct sdebug_queue *sqp;
+
+	for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) {
+		atomic_set(&sqp->cmnd_count, 0);
+		atomic_set(&sqp->completions, 0);
+		atomic_set(&sqp->misqueues, 0);
+		atomic_set(&sqp->a_tsf, 0);
+	}
+}
+
+static void setup_inject(struct sdebug_queue *sqp,
+			 struct sdebug_queued_cmd *sqcp)
+{
+	if ((atomic_read(&sqp->cmnd_count) % abs(sdebug_every_nth)) > 0)
+		return;
+	sqcp->inj_recovered = !!(SDEBUG_OPT_RECOVERED_ERR & sdebug_opts);
+	sqcp->inj_transport = !!(SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts);
+	sqcp->inj_dif = !!(SDEBUG_OPT_DIF_ERR & sdebug_opts);
+	sqcp->inj_dix = !!(SDEBUG_OPT_DIX_ERR & sdebug_opts);
+	sqcp->inj_short = !!(SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts);
+}
+
+/* Complete the processing of the thread that queued a SCSI command to this
+ * driver. It either completes the command by calling cmnd_done() or
+ * schedules a hr timer or work queue then returns 0. Returns
+ * SCSI_MLQUEUE_HOST_BUSY if temporarily out of resources. */
 static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 			 int scsi_result, int delta_jiff)
 {
 	unsigned long iflags;
 	int k, num_in_q, qdepth, inject;
+	struct sdebug_queue *sqp;
 	struct sdebug_queued_cmd *sqcp = NULL;
 	struct scsi_device *sdp;
 	struct sdebug_defer *sd_dp;
 
-	if (unlikely(WARN_ON(!cmnd)))
-		return SCSI_MLQUEUE_HOST_BUSY;
-
 	if (unlikely(NULL == devip)) {
 		if (0 == scsi_result)
 			scsi_result = DID_NO_CONNECT << 16;
 		goto respond_in_thread;
 	}
-
 	sdp = cmnd->device;
 
 	if (unlikely(sdebug_verbose && scsi_result))
@@ -3830,31 +3911,36 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 		goto respond_in_thread;
 
 	/* schedule the response at a later time if resources permit */
-	spin_lock_irqsave(&queued_arr_lock, iflags);
+	sqp = get_queue();
+	spin_lock_irqsave(&sqp->qc_lock, iflags);
+	if (unlikely(atomic_read(&sqp->blocked))) {
+		spin_unlock_irqrestore(&sqp->qc_lock, iflags);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 	num_in_q = atomic_read(&devip->num_in_q);
 	qdepth = cmnd->device->queue_depth;
 	inject = 0;
 	if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) {
 		if (scsi_result) {
-			spin_unlock_irqrestore(&queued_arr_lock, iflags);
+			spin_unlock_irqrestore(&sqp->qc_lock, iflags);
 			goto respond_in_thread;
 		} else
 			scsi_result = device_qfull_result;
-	} else if (unlikely((sdebug_every_nth != 0) &&
+	} else if (unlikely(sdebug_every_nth &&
 			    (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
 			    (scsi_result == 0))) {
 		if ((num_in_q == (qdepth - 1)) &&
-		    (atomic_inc_return(&sdebug_a_tsf) >=
+		    (atomic_inc_return(&sqp->a_tsf) >=
 		     abs(sdebug_every_nth))) {
-			atomic_set(&sdebug_a_tsf, 0);
+			atomic_set(&sqp->a_tsf, 0);
 			inject = 1;
 			scsi_result = device_qfull_result;
 		}
 	}
 
-	k = find_first_zero_bit(queued_in_use_bm, sdebug_max_queue);
+	k = find_first_zero_bit(sqp->in_use_bm, sdebug_max_queue);
 	if (unlikely(k >= sdebug_max_queue)) {
-		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		spin_unlock_irqrestore(&sqp->qc_lock, iflags);
 		if (scsi_result)
 			goto respond_in_thread;
 		else if (SDEBUG_OPT_ALL_TSF & sdebug_opts)
@@ -3870,13 +3956,16 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 		else
 			return SCSI_MLQUEUE_HOST_BUSY;
 	}
-	__set_bit(k, queued_in_use_bm);
+	__set_bit(k, sqp->in_use_bm);
 	atomic_inc(&devip->num_in_q);
-	sqcp = &queued_arr[k];
+	sqcp = &sqp->qc_arr[k];
 	sqcp->a_cmnd = cmnd;
+	cmnd->host_scribble = (unsigned char *)sqcp;
 	cmnd->result = scsi_result;
-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 	sd_dp = sqcp->sd_dp;
+	spin_unlock_irqrestore(&sqp->qc_lock, iflags);
+	if (unlikely(sdebug_every_nth && sdebug_any_injecting_opt))
+		setup_inject(sqp, sqcp);
 	if ((delta_jiff > 0) || (sdebug_ndelay > 0)) {
 		ktime_t kt;
 
@@ -3893,18 +3982,20 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
 				return SCSI_MLQUEUE_HOST_BUSY;
 			sqcp->sd_dp = sd_dp;
 			hrtimer_init(&sd_dp->hrt, CLOCK_MONOTONIC,
-				     HRTIMER_MODE_REL);
+				     HRTIMER_MODE_REL_PINNED);
 			sd_dp->hrt.function = sdebug_q_cmd_hrt_complete;
-			sd_dp->qa_indx = k;
+			sd_dp->sq_indx = sqp - sdebug_q_arr;
+			sd_dp->qc_indx = k;
 		}
-		hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL);
-	} else {	/* jdelay < 0 */
+		hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL_PINNED);
+	} else {	/* jdelay < 0, use work queue */
 		if (NULL == sd_dp) {
 			sd_dp = kzalloc(sizeof(*sqcp->sd_dp), GFP_ATOMIC);
 			if (NULL == sd_dp)
 				return SCSI_MLQUEUE_HOST_BUSY;
 			sqcp->sd_dp = sd_dp;
-			sd_dp->qa_indx = k;
+			sd_dp->sq_indx = sqp - sdebug_q_arr;
+			sd_dp->qc_indx = k;
 			INIT_WORK(&sd_dp->ew.work, sdebug_q_cmd_wq_complete);
 		}
 		schedule_work(&sd_dp->ew.work);
@@ -3960,7 +4051,9 @@ module_param_named(ptype, sdebug_ptype, int, S_IRUGO | S_IWUSR);
 module_param_named(removable, sdebug_removable, bool, S_IRUGO | S_IWUSR);
 module_param_named(scsi_level, sdebug_scsi_level, int, S_IRUGO);
 module_param_named(sector_size, sdebug_sector_size, int, S_IRUGO);
+module_param_named(statistics, sdebug_statistics, bool, S_IRUGO | S_IWUSR);
 module_param_named(strict, sdebug_strict, bool, S_IRUGO | S_IWUSR);
+module_param_named(submit_queues, submit_queues, int, S_IRUGO);
 module_param_named(unmap_alignment, sdebug_unmap_alignment, int, S_IRUGO);
 module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO);
 module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO);
@@ -4007,7 +4100,9 @@ MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
 MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
 MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])");
 MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
+MODULE_PARM_DESC(statistics, "collect statistics on commands, queues (def=1)");
 MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
+MODULE_PARM_DESC(submit_queues, "support for block multi-queue (def=1)");
 MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
 MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
 MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
@@ -4020,9 +4115,17 @@ static char sdebug_info[256];
 
 static const char * scsi_debug_info(struct Scsi_Host * shp)
 {
-	sprintf(sdebug_info, "scsi_debug, version %s [%s], "
-		"dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION,
-		sdebug_version_date, sdebug_dev_size_mb, sdebug_opts);
+	int k;
+
+	k = scnprintf(sdebug_info, sizeof(sdebug_info),
+		      "%s: version %s [%s], dev_size_mb=%d, opts=0x%x\n",
+		      my_name, SCSI_DEBUG_VERSION, sdebug_version_date,
+		      sdebug_dev_size_mb, sdebug_opts);
+	if (k >= (sizeof(sdebug_info) - 1))
+		return sdebug_info;
+	scnprintf(sdebug_info + k, sizeof(sdebug_info) - k,
+		  "%s: submit_queues=%d, statistics=%d\n", my_name,
+		  submit_queues, (int)sdebug_statistics);
 	return sdebug_info;
 }
 
@@ -4044,7 +4147,7 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer,
 	sdebug_verbose = !!(SDEBUG_OPT_NOISE & opts);
 	sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & opts);
 	if (sdebug_every_nth != 0)
-		atomic_set(&sdebug_cmnd_count, 0);
+		tweak_cmnd_count();
 	return length;
 }
 
@@ -4053,39 +4156,42 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer,
  * output are not atomics so might be inaccurate in a busy system. */
 static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host)
 {
-	int f, l;
-	char b[32];
-
-	if (sdebug_every_nth > 0)
-		snprintf(b, sizeof(b), " (curr:%d)",
-			 ((SDEBUG_OPT_RARE_TSF & sdebug_opts) ?
-				atomic_read(&sdebug_a_tsf) :
-				atomic_read(&sdebug_cmnd_count)));
-	else
-		b[0] = '\0';
-
-	seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n"
-		"num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
-		"every_nth=%d%s\n"
-		"delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n"
-		"sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
-		"command aborts=%d; RESETs: device=%d, target=%d, bus=%d, "
-		"host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d "
-		"usec_in_jiffy=%lu\n",
-		SCSI_DEBUG_VERSION, sdebug_version_date,
-		sdebug_num_tgts, sdebug_dev_size_mb, sdebug_opts,
-		sdebug_every_nth, b, sdebug_jdelay, sdebug_ndelay,
-		sdebug_max_luns, atomic_read(&sdebug_completions),
-		sdebug_sector_size, sdebug_cylinders_per, sdebug_heads,
-		sdebug_sectors_per, num_aborts, num_dev_resets,
-		num_target_resets, num_bus_resets, num_host_resets,
-		dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000);
-
-	f = find_first_bit(queued_in_use_bm, sdebug_max_queue);
-	if (f != sdebug_max_queue) {
-		l = find_last_bit(queued_in_use_bm, sdebug_max_queue);
-		seq_printf(m, "   %s BUSY: first,last bits set: %d,%d\n",
-			   "queued_in_use_bm", f, l);
+	int f, j, l;
+	struct sdebug_queue *sqp;
+
+	seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n",
+		   SCSI_DEBUG_VERSION, sdebug_version_date);
+	seq_printf(m, "num_tgts=%d, %ssize=%d MB, opts=0x%x, every_nth=%d\n",
+		   sdebug_num_tgts, "shared (ram) ", sdebug_dev_size_mb,
+		   sdebug_opts, sdebug_every_nth);
+	seq_printf(m, "delay=%d, ndelay=%d, max_luns=%d, sector_size=%d %s\n",
+		   sdebug_jdelay, sdebug_ndelay, sdebug_max_luns,
+		   sdebug_sector_size, "bytes");
+	seq_printf(m, "cylinders=%d, heads=%d, sectors=%d, command aborts=%d\n",
+		   sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per,
+		   num_aborts);
+	seq_printf(m, "RESETs: device=%d, target=%d, bus=%d, host=%d\n",
+		   num_dev_resets, num_target_resets, num_bus_resets,
+		   num_host_resets);
+	seq_printf(m, "dix_reads=%d, dix_writes=%d, dif_errors=%d\n",
+		   dix_reads, dix_writes, dif_errors);
+	seq_printf(m, "%s=%lu, %s=%d, mq_available=%d, submit_queues=%d\n",
+		   "usec_in_jiffy", TICK_NSEC / 1000, "statistics",
+		   sdebug_statistics, sdebug_mq_available, submit_queues);
+
+	for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) {
+		seq_printf(m, "queue %d:\n", j);
+		seq_printf(m, "    cmnd_count=%d, %s=%d, %s=%d, a_tsf=%d\n",
+			   atomic_read(&sqp->cmnd_count),
+			   "completions", atomic_read(&sqp->completions),
+			   "misqueues", atomic_read(&sqp->misqueues),
+			   atomic_read(&sqp->a_tsf));
+		f = find_first_bit(sqp->in_use_bm, sdebug_max_queue);
+		if (f != sdebug_max_queue) {
+			l = find_last_bit(sqp->in_use_bm, sdebug_max_queue);
+			seq_printf(m, "    in_use_bm BUSY: %s: %d,%d\n",
+				   "first,last bits", f, l);
+		}
 	}
 	return 0;
 }
@@ -4094,7 +4200,8 @@ static ssize_t delay_show(struct device_driver *ddp, char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_jdelay);
 }
-/* Returns -EBUSY if jdelay is being changed and commands are queued */
+/* Returns -EBUSY if jdelay is being changed and commands are queued. The unit
+ * of delay is jiffies. */
 static ssize_t delay_store(struct device_driver *ddp, const char *buf,
 			   size_t count)
 {
@@ -4103,21 +4210,27 @@ static ssize_t delay_store(struct device_driver *ddp, const char *buf,
 	if ((count > 0) && (1 == sscanf(buf, "%d", &jdelay))) {
 		res = count;
 		if (sdebug_jdelay != jdelay) {
-			unsigned long iflags;
-			int k;
-
-			spin_lock_irqsave(&queued_arr_lock, iflags);
-			k = find_first_bit(queued_in_use_bm, sdebug_max_queue);
-			if (k != sdebug_max_queue)
-				res = -EBUSY;	/* have queued commands */
-			else {
+			int j, k;
+			struct sdebug_queue *sqp;
+
+			block_unblock_all_queues(true);
+			for (j = 0, sqp = sdebug_q_arr; j < submit_queues;
+			     ++j, ++sqp) {
+				k = find_first_bit(sqp->in_use_bm,
+						   sdebug_max_queue);
+				if (k != sdebug_max_queue) {
+					res = -EBUSY;   /* queued commands */
+					break;
+				}
+			}
+			if (res > 0) {
 				/* make sure sdebug_defer instances get
 				 * re-allocated for new delay variant */
 				free_all_queued();
 				sdebug_jdelay = jdelay;
 				sdebug_ndelay = 0;
 			}
-			spin_unlock_irqrestore(&queued_arr_lock, iflags);
+			block_unblock_all_queues(false);
 		}
 		return res;
 	}
@@ -4134,18 +4247,26 @@ static ssize_t ndelay_show(struct device_driver *ddp, char *buf)
 static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
 			    size_t count)
 {
-	unsigned long iflags;
-	int ndelay, res, k;
+	int ndelay, res;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) &&
-	    (ndelay >= 0) && (ndelay < 1000000000)) {
+	    (ndelay >= 0) && (ndelay < (1000 * 1000 * 1000))) {
 		res = count;
 		if (sdebug_ndelay != ndelay) {
-			spin_lock_irqsave(&queued_arr_lock, iflags);
-			k = find_first_bit(queued_in_use_bm, sdebug_max_queue);
-			if (k != sdebug_max_queue)
-				res = -EBUSY;	/* have queued commands */
-			else {
+			int j, k;
+			struct sdebug_queue *sqp;
+
+			block_unblock_all_queues(true);
+			for (j = 0, sqp = sdebug_q_arr; j < submit_queues;
+			     ++j, ++sqp) {
+				k = find_first_bit(sqp->in_use_bm,
+						   sdebug_max_queue);
+				if (k != sdebug_max_queue) {
+					res = -EBUSY;   /* queued commands */
+					break;
+				}
+			}
+			if (res > 0) {
 				/* make sure sdebug_defer instances get
 				 * re-allocated for new delay variant */
 				free_all_queued();
@@ -4153,7 +4274,7 @@ static ssize_t ndelay_store(struct device_driver *ddp, const char *buf,
 				sdebug_jdelay = ndelay  ? JDELAY_OVERRIDDEN
 							: DEF_JDELAY;
 			}
-			spin_unlock_irqrestore(&queued_arr_lock, iflags);
+			block_unblock_all_queues(false);
 		}
 		return res;
 	}
@@ -4186,8 +4307,7 @@ opts_done:
 	sdebug_opts = opts;
 	sdebug_verbose = !!(SDEBUG_OPT_NOISE & opts);
 	sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & opts);
-	atomic_set(&sdebug_cmnd_count, 0);
-	atomic_set(&sdebug_a_tsf, 0);
+	tweak_cmnd_count();
 	return count;
 }
 static DRIVER_ATTR_RW(opts);
@@ -4317,7 +4437,7 @@ static ssize_t every_nth_store(struct device_driver *ddp, const char *buf,
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
 		sdebug_every_nth = nth;
-		atomic_set(&sdebug_cmnd_count, 0);
+		tweak_cmnd_count();
 		return count;
 	}
 	return -EINVAL;
@@ -4372,13 +4492,19 @@ static ssize_t max_queue_show(struct device_driver *ddp, char *buf)
 static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
 			       size_t count)
 {
-	unsigned long iflags;
-	int n, k;
+	int j, n, k, a;
+	struct sdebug_queue *sqp;
 
 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
 	    (n <= SCSI_DEBUG_CANQUEUE)) {
-		spin_lock_irqsave(&queued_arr_lock, iflags);
-		k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE);
+		block_unblock_all_queues(true);
+		k = 0;
+		for (j = 0, sqp = sdebug_q_arr; j < submit_queues;
+		     ++j, ++sqp) {
+			a = find_last_bit(sqp->in_use_bm, SCSI_DEBUG_CANQUEUE);
+			if (a > k)
+				k = a;
+		}
 		sdebug_max_queue = n;
 		if (SCSI_DEBUG_CANQUEUE == k)
 			atomic_set(&retired_max_queue, 0);
@@ -4386,7 +4512,7 @@ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf,
 			atomic_set(&retired_max_queue, k + 1);
 		else
 			atomic_set(&retired_max_queue, 0);
-		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		block_unblock_all_queues(false);
 		return count;
 	}
 	return -EINVAL;
@@ -4485,12 +4611,40 @@ static ssize_t vpd_use_hostno_store(struct device_driver *ddp, const char *buf,
 }
 static DRIVER_ATTR_RW(vpd_use_hostno);
 
+static ssize_t statistics_show(struct device_driver *ddp, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (int)sdebug_statistics);
+}
+static ssize_t statistics_store(struct device_driver *ddp, const char *buf,
+				size_t count)
+{
+	int n;
+
+	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+		if (n > 0)
+			sdebug_statistics = true;
+		else {
+			clear_queue_stats();
+			sdebug_statistics = false;
+		}
+		return count;
+	}
+	return -EINVAL;
+}
+static DRIVER_ATTR_RW(statistics);
+
 static ssize_t sector_size_show(struct device_driver *ddp, char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%u\n", sdebug_sector_size);
 }
 static DRIVER_ATTR_RO(sector_size);
 
+static ssize_t submit_queues_show(struct device_driver *ddp, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%d\n", submit_queues);
+}
+static DRIVER_ATTR_RO(submit_queues);
+
 static ssize_t dix_show(struct device_driver *ddp, char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dix);
@@ -4611,6 +4765,8 @@ static struct attribute *sdebug_drv_attrs[] = {
 	&driver_attr_add_host.attr,
 	&driver_attr_vpd_use_hostno.attr,
 	&driver_attr_sector_size.attr,
+	&driver_attr_statistics.attr,
+	&driver_attr_submit_queues.attr,
 	&driver_attr_dix.attr,
 	&driver_attr_dif.attr,
 	&driver_attr_guard.attr,
@@ -4633,8 +4789,6 @@ static int __init scsi_debug_init(void)
 	int k;
 	int ret;
 
-	atomic_set(&sdebug_cmnd_count, 0);
-	atomic_set(&sdebug_completions, 0);
 	atomic_set(&retired_max_queue, 0);
 
 	if (sdebug_ndelay >= 1000 * 1000 * 1000) {
@@ -4693,6 +4847,19 @@ static int __init scsi_debug_init(void)
 		return -EINVAL;
 	}
 
+	if (submit_queues < 1) {
+		pr_err("submit_queues must be 1 or more\n");
+		return -EINVAL;
+	}
+	sdebug_q_arr = kzalloc(sizeof(struct sdebug_queue) * submit_queues,
+			       GFP_KERNEL);
+	if (NULL == sdebug_q_arr) {
+		pr_err("sdebug_q_arr out of memory\n");
+		return -ENOMEM;
+	}
+	for (k = 0; k < submit_queues; ++k)
+		spin_lock_init(&sdebug_q_arr[k].qc_lock);
+
 	if (sdebug_dev_size_mb < 1)
 		sdebug_dev_size_mb = 1;  /* force minimum 1 MB ramdisk */
 	sz = (unsigned long)sdebug_dev_size_mb * 1048576;
@@ -4720,7 +4887,8 @@ static int __init scsi_debug_init(void)
 		fake_storep = vmalloc(sz);
 		if (NULL == fake_storep) {
 			pr_err("out of memory, 1\n");
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto free_q_arr;
 		}
 		memset(fake_storep, 0, sz);
 		if (sdebug_num_parts > 0)
@@ -4759,7 +4927,8 @@ static int __init scsi_debug_init(void)
 		    sdebug_unmap_granularity <=
 		    sdebug_unmap_alignment) {
 			pr_err("ERR: unmap_granularity <= unmap_alignment\n");
-			return -EINVAL;
+			ret = -EINVAL;
+			goto free_vm;
 		}
 
 		map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
@@ -4820,7 +4989,8 @@ free_vm:
 	vfree(map_storep);
 	vfree(dif_storep);
 	vfree(fake_storep);
-
+free_q_arr:
+	kfree(sdebug_q_arr);
 	return ret;
 }
 
@@ -4838,6 +5008,7 @@ static void __exit scsi_debug_exit(void)
 
 	vfree(dif_storep);
 	vfree(fake_storep);
+	kfree(sdebug_q_arr);
 }
 
 device_initcall(scsi_debug_init);
@@ -4926,62 +5097,45 @@ static void sdebug_remove_adapter(void)
 static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
 {
 	int num_in_q = 0;
-	unsigned long iflags;
 	struct sdebug_dev_info *devip;
 
-	spin_lock_irqsave(&queued_arr_lock, iflags);
+	block_unblock_all_queues(true);
 	devip = (struct sdebug_dev_info *)sdev->hostdata;
 	if (NULL == devip) {
-		spin_unlock_irqrestore(&queued_arr_lock, iflags);
+		block_unblock_all_queues(false);
 		return	-ENODEV;
 	}
 	num_in_q = atomic_read(&devip->num_in_q);
-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 
 	if (qdepth < 1)
 		qdepth = 1;
-	/* allow to exceed max host queued_arr elements for testing */
+	/* allow to exceed max host qc_arr elements for testing */
 	if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
 		qdepth = SCSI_DEBUG_CANQUEUE + 10;
 	scsi_change_queue_depth(sdev, qdepth);
 
 	if (SDEBUG_OPT_Q_NOISE & sdebug_opts) {
-		sdev_printk(KERN_INFO, sdev,
-			    "%s: qdepth=%d, num_in_q=%d\n",
+		sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d, num_in_q=%d\n",
 			    __func__, qdepth, num_in_q);
 	}
+	block_unblock_all_queues(false);
 	return sdev->queue_depth;
 }
 
-static int check_inject(struct scsi_cmnd *scp)
+static bool fake_timeout(struct sdebug_queue *sqp, struct scsi_cmnd *scp)
 {
-	struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
-
-	memset(ep, 0, sizeof(struct sdebug_scmd_extra_t));
-
-	if (atomic_inc_return(&sdebug_cmnd_count) >= abs(sdebug_every_nth)) {
-		atomic_set(&sdebug_cmnd_count, 0);
+	if (NULL == sqp)
+		sqp = get_queue();
+	if (0 == (atomic_read(&sqp->cmnd_count) % abs(sdebug_every_nth))) {
 		if (sdebug_every_nth < -1)
 			sdebug_every_nth = -1;
 		if (SDEBUG_OPT_TIMEOUT & sdebug_opts)
-			return 1; /* ignore command causing timeout */
+			return true; /* ignore command causing timeout */
 		else if (SDEBUG_OPT_MAC_TIMEOUT & sdebug_opts &&
 			 scsi_medium_access_command(scp))
-			return 1; /* time out reads and writes */
-		if (sdebug_any_injecting_opt) {
-			if (SDEBUG_OPT_RECOVERED_ERR & sdebug_opts)
-				ep->inj_recovered = true;
-			if (SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts)
-				ep->inj_transport = true;
-			if (SDEBUG_OPT_DIF_ERR & sdebug_opts)
-				ep->inj_dif = true;
-			if (SDEBUG_OPT_DIX_ERR & sdebug_opts)
-				ep->inj_dix = true;
-			if (SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts)
-				ep->inj_short = true;
-		}
+			return true; /* time out reads and writes */
 	}
-	return 0;
+	return false;
 }
 
 static int scsi_debug_queuecommand(struct Scsi_Host *shost,
@@ -4992,6 +5146,7 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
 	const struct opcode_info_t *oip;
 	const struct opcode_info_t *r_oip;
 	struct sdebug_dev_info *devip;
+	struct sdebug_queue *sqp = NULL;
 	u8 *cmd = scp->cmnd;
 	int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
 	int k, na;
@@ -5002,6 +5157,10 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
 	bool has_wlun_rl;
 
 	scsi_set_resid(scp, 0);
+	if (sdebug_statistics) {
+		sqp = get_queue();
+		atomic_inc(&sqp->cmnd_count);
+	}
 	if (unlikely(sdebug_verbose &&
 		     !(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts))) {
 		char b[120];
@@ -5094,7 +5253,7 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
 		if (errsts)
 			goto check_cond;
 	}
-	if (unlikely((F_M_ACCESS & flags) && devip->stopped)) {
+	if (unlikely((F_M_ACCESS & flags) && atomic_read(&devip->stopped))) {
 		mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
 		if (sdebug_verbose)
 			sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
@@ -5106,7 +5265,7 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
 	if (sdebug_fake_rw && (F_FAKE_RW & flags))
 		goto fini;
 	if (unlikely(sdebug_every_nth)) {
-		if (check_inject(scp))
+		if (fake_timeout(sqp, scp))
 			return 0;	/* ignore command: make trouble */
 	}
 	if (likely(oip->pfp))
@@ -5148,7 +5307,6 @@ static struct scsi_host_template sdebug_driver_template = {
 	.use_clustering = 	DISABLE_CLUSTERING,
 	.module =		THIS_MODULE,
 	.track_queue_depth =	1,
-	.cmd_size =		sizeof(struct sdebug_scmd_extra_t),
 };
 
 static int sdebug_driver_probe(struct device * dev)
@@ -5169,6 +5327,16 @@ static int sdebug_driver_probe(struct device * dev)
 		error = -ENODEV;
 		return error;
 	}
+	if (submit_queues > nr_cpu_ids) {
+		pr_warn("%s: trim submit_queues (was %d) to nr_cpu_ids=%d\n",
+			my_name, submit_queues, nr_cpu_ids);
+		submit_queues = nr_cpu_ids;
+	}
+	/* Decide whether to tell scsi subsystem that we want mq */
+	/* Following should give the same answer for each host */
+	sdebug_mq_available = shost_use_blk_mq(hpnt);
+	if (sdebug_mq_available && (submit_queues > 1))
+		hpnt->nr_hw_queues = submit_queues;
 
         sdbg_host->shost = hpnt;
 	*((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
@@ -5226,6 +5394,8 @@ static int sdebug_driver_probe(struct device * dev)
 
 	sdebug_verbose = !!(SDEBUG_OPT_NOISE & sdebug_opts);
 	sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & sdebug_opts);
+	if (sdebug_every_nth)	/* need stats counters for every_nth */
+		sdebug_statistics = true;
         error = scsi_add_host(hpnt, &sdbg_host->dev);
         if (error) {
 		pr_err("scsi_add_host failed\n");
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 10/12] scsi_debug: vpd and mode page work
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (8 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 09/12] scsi_debug: add multiple queue support Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:29   ` Hannes Reinecke
  2016-04-25 16:16 ` [PATCH 11/12] scsi_debug: uuid for lu name Douglas Gilbert
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Cleanup some mode and vpd pages. Stop reporting SBC (disk) pages
when peripheral type is something else (e.g. tape). Update
version descriptors. Expand LBPRZ flag handling.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index bdc9ece..99c4b49 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -125,7 +125,7 @@ static const char *sdebug_version_date = "20160422";
 #define DEF_PHYSBLK_EXP 0
 #define DEF_PTYPE   0
 #define DEF_REMOVABLE false
-#define DEF_SCSI_LEVEL   6    /* INQUIRY, byte2 [6->SPC-4] */
+#define DEF_SCSI_LEVEL   7    /* INQUIRY, byte2 [6->SPC-4; 7->SPC-5] */
 #define DEF_SECTOR_SIZE 512
 #define DEF_UNMAP_ALIGNMENT 0
 #define DEF_UNMAP_GRANULARITY 1
@@ -653,7 +653,10 @@ static const int device_qfull_result =
 	(DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
 
 
-static unsigned int scsi_debug_lbp(void)
+/* Only do the extra work involved in logical block provisioning if one or
+ * more of the lbpu, lbpws or lbpws10 parameters are given and we are doing
+ * real reads and writes (i.e. not skipping them for speed). */
+static bool scsi_debug_lbp(void)
 {
 	return ((0 == sdebug_fake_rw) &&
 		(sdebug_lbpu | sdebug_lbpws | sdebug_lbpws10));
@@ -913,10 +916,10 @@ static const u64 naa5_comp_b = 0x5333333000000000ULL;
 static const u64 naa5_comp_c = 0x5111111000000000ULL;
 
 /* Device identification VPD page. Returns number of bytes placed in arr */
-static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
-			   int target_dev_id, int dev_id_num,
-			   const char * dev_id_str,
-			   int dev_id_str_len)
+static int inquiry_vpd_83(unsigned char *arr, int port_group_id,
+			  int target_dev_id, int dev_id_num,
+			  const char *dev_id_str,
+			  int dev_id_str_len)
 {
 	int num, port_a;
 	char b[32];
@@ -995,14 +998,14 @@ static unsigned char vpd84_data[] = {
 };
 
 /*  Software interface identification VPD page */
-static int inquiry_evpd_84(unsigned char * arr)
+static int inquiry_vpd_84(unsigned char *arr)
 {
 	memcpy(arr, vpd84_data, sizeof(vpd84_data));
 	return sizeof(vpd84_data);
 }
 
 /* Management network addresses VPD page */
-static int inquiry_evpd_85(unsigned char * arr)
+static int inquiry_vpd_85(unsigned char *arr)
 {
 	int num = 0;
 	const char * na1 = "https://www.kernel.org/config";
@@ -1037,7 +1040,7 @@ static int inquiry_evpd_85(unsigned char * arr)
 }
 
 /* SCSI ports VPD page */
-static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
+static int inquiry_vpd_88(unsigned char *arr, int target_dev_id)
 {
 	int num = 0;
 	int port_a, port_b;
@@ -1124,7 +1127,7 @@ static unsigned char vpd89_data[] = {
 };
 
 /* ATA Information VPD page */
-static int inquiry_evpd_89(unsigned char * arr)
+static int inquiry_vpd_89(unsigned char *arr)
 {
 	memcpy(arr, vpd89_data, sizeof(vpd89_data));
 	return sizeof(vpd89_data);
@@ -1139,7 +1142,7 @@ static unsigned char vpdb0_data[] = {
 };
 
 /* Block limits VPD page (SBC-3) */
-static int inquiry_evpd_b0(unsigned char * arr)
+static int inquiry_vpd_b0(unsigned char *arr)
 {
 	unsigned int gran;
 
@@ -1182,7 +1185,7 @@ static int inquiry_evpd_b0(unsigned char * arr)
 }
 
 /* Block device characteristics VPD page (SBC-3) */
-static int inquiry_evpd_b1(unsigned char *arr)
+static int inquiry_vpd_b1(unsigned char *arr)
 {
 	memset(arr, 0, 0x3c);
 	arr[0] = 0;
@@ -1193,24 +1196,22 @@ static int inquiry_evpd_b1(unsigned char *arr)
 	return 0x3c;
 }
 
-/* Logical block provisioning VPD page (SBC-3) */
-static int inquiry_evpd_b2(unsigned char *arr)
+/* Logical block provisioning VPD page (SBC-4) */
+static int inquiry_vpd_b2(unsigned char *arr)
 {
 	memset(arr, 0, 0x4);
 	arr[0] = 0;			/* threshold exponent */
-
 	if (sdebug_lbpu)
 		arr[1] = 1 << 7;
-
 	if (sdebug_lbpws)
 		arr[1] |= 1 << 6;
-
 	if (sdebug_lbpws10)
 		arr[1] |= 1 << 5;
-
-	if (sdebug_lbprz)
-		arr[1] |= 1 << 2;
-
+	if (sdebug_lbprz && scsi_debug_lbp())
+		arr[1] |= (sdebug_lbprz & 0x7) << 2;  /* sbc4r07 and later */
+	/* anc_sup=0; dp=0 (no provisioning group descriptor) */
+	/* minimum_percentage=0; provisioning_type=0 (unknown) */
+	/* threshold_percentage=0 */
 	return 0x4;
 }
 
@@ -1223,12 +1224,13 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	unsigned char * arr;
 	unsigned char *cmd = scp->cmnd;
 	int alloc_len, n, ret;
-	bool have_wlun;
+	bool have_wlun, is_disk;
 
 	alloc_len = get_unaligned_be16(cmd + 3);
 	arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
 	if (! arr)
 		return DID_REQUEUE << 16;
+	is_disk = (sdebug_ptype == 0);
 	have_wlun = (scp->device->lun == SCSI_W_LUN_REPORT_LUNS);
 	if (have_wlun)
 		pq_pdt = 0x1e;	/* present, wlun */
@@ -1266,11 +1268,12 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 			arr[n++] = 0x86;  /* extended inquiry */
 			arr[n++] = 0x87;  /* mode page policy */
 			arr[n++] = 0x88;  /* SCSI ports */
-			arr[n++] = 0x89;  /* ATA information */
-			arr[n++] = 0xb0;  /* Block limits (SBC) */
-			arr[n++] = 0xb1;  /* Block characteristics (SBC) */
-			if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */
-				arr[n++] = 0xb2;
+			if (is_disk) {	  /* SBC only */
+				arr[n++] = 0x89;  /* ATA information */
+				arr[n++] = 0xb0;  /* Block limits */
+				arr[n++] = 0xb1;  /* Block characteristics */
+				arr[n++] = 0xb2;  /* Logical Block Prov */
+			}
 			arr[3] = n - 4;	  /* number of supported VPD pages */
 		} else if (0x80 == cmd[2]) { /* unit serial number */
 			arr[1] = cmd[2];	/*sanity */
@@ -1278,21 +1281,21 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 			memcpy(&arr[4], lu_id_str, len);
 		} else if (0x83 == cmd[2]) { /* device identification */
 			arr[1] = cmd[2];	/*sanity */
-			arr[3] = inquiry_evpd_83(&arr[4], port_group_id,
-						 target_dev_id, lu_id_num,
-						 lu_id_str, len);
+			arr[3] = inquiry_vpd_83(&arr[4], port_group_id,
+						target_dev_id, lu_id_num,
+						lu_id_str, len);
 		} else if (0x84 == cmd[2]) { /* Software interface ident. */
 			arr[1] = cmd[2];	/*sanity */
-			arr[3] = inquiry_evpd_84(&arr[4]);
+			arr[3] = inquiry_vpd_84(&arr[4]);
 		} else if (0x85 == cmd[2]) { /* Management network addresses */
 			arr[1] = cmd[2];	/*sanity */
-			arr[3] = inquiry_evpd_85(&arr[4]);
+			arr[3] = inquiry_vpd_85(&arr[4]);
 		} else if (0x86 == cmd[2]) { /* extended inquiry */
 			arr[1] = cmd[2];	/*sanity */
 			arr[3] = 0x3c;	/* number of following entries */
 			if (sdebug_dif == SD_DIF_TYPE3_PROTECTION)
 				arr[4] = 0x4;	/* SPT: GRD_CHK:1 */
-			else if (sdebug_dif)
+			else if (have_dif_prot)
 				arr[4] = 0x5;   /* SPT: GRD_CHK:1, REF_CHK:1 */
 			else
 				arr[4] = 0x0;   /* no protection stuff */
@@ -1306,20 +1309,20 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 			arr[10] = 0x82;	 /* mlus, per initiator port */
 		} else if (0x88 == cmd[2]) { /* SCSI Ports */
 			arr[1] = cmd[2];	/*sanity */
-			arr[3] = inquiry_evpd_88(&arr[4], target_dev_id);
-		} else if (0x89 == cmd[2]) { /* ATA information */
+			arr[3] = inquiry_vpd_88(&arr[4], target_dev_id);
+		} else if (is_disk && 0x89 == cmd[2]) { /* ATA information */
 			arr[1] = cmd[2];        /*sanity */
-			n = inquiry_evpd_89(&arr[4]);
+			n = inquiry_vpd_89(&arr[4]);
 			put_unaligned_be16(n, arr + 2);
-		} else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
+		} else if (is_disk && 0xb0 == cmd[2]) { /* Block limits */
 			arr[1] = cmd[2];        /*sanity */
-			arr[3] = inquiry_evpd_b0(&arr[4]);
-		} else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
+			arr[3] = inquiry_vpd_b0(&arr[4]);
+		} else if (is_disk && 0xb1 == cmd[2]) { /* Block char. */
 			arr[1] = cmd[2];        /*sanity */
-			arr[3] = inquiry_evpd_b1(&arr[4]);
-		} else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */
+			arr[3] = inquiry_vpd_b1(&arr[4]);
+		} else if (is_disk && 0xb2 == cmd[2]) { /* LB Prov. */
 			arr[1] = cmd[2];        /*sanity */
-			arr[3] = inquiry_evpd_b2(&arr[4]);
+			arr[3] = inquiry_vpd_b2(&arr[4]);
 		} else {
 			mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
 			kfree(arr);
@@ -1346,15 +1349,17 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	memcpy(&arr[16], inq_product_id, 16);
 	memcpy(&arr[32], inq_product_rev, 4);
 	/* version descriptors (2 bytes each) follow */
-	arr[58] = 0x0; arr[59] = 0xa2;  /* SAM-5 rev 4 */
-	arr[60] = 0x4; arr[61] = 0x68;  /* SPC-4 rev 37 */
+	put_unaligned_be16(0xc0, arr + 58);   /* SAM-6 no version claimed */
+	put_unaligned_be16(0x5c0, arr + 60);  /* SPC-5 no version claimed */
 	n = 62;
-	if (sdebug_ptype == 0) {
-		arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */
-	} else if (sdebug_ptype == 1) {
-		arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */
-	}
-	arr[n++] = 0x20; arr[n++] = 0xe6;  /* SPL-3 rev 7 */
+	if (is_disk) {		/* SBC-4 no version claimed */
+		put_unaligned_be16(0x600, arr + n);
+		n += 2;
+	} else if (sdebug_ptype == 1) {	/* SSC-4 rev 3 */
+		put_unaligned_be16(0x525, arr + n);
+		n += 2;
+	}
+	put_unaligned_be16(0x2100, arr + n);	/* SPL-4 no version claimed */
 	ret = fill_from_dev_buffer(scp, arr,
 			    min(alloc_len, SDEBUG_LONG_INQ_SZ));
 	kfree(arr);
@@ -1490,13 +1495,16 @@ static int resp_readcap16(struct scsi_cmnd * scp,
 
 	if (scsi_debug_lbp()) {
 		arr[14] |= 0x80; /* LBPME */
-		if (sdebug_lbprz)
-			arr[14] |= 0x40; /* LBPRZ */
+		/* from sbc4r07, this LBPRZ field is 1 bit, but the LBPRZ in
+		 * the LB Provisioning VPD page is 3 bits. Note that lbprz=2
+		 * in the wider field maps to 0 in this field */
+		if (sdebug_lbprz & 1)	/* precisely what the draft requires */
+			arr[14] |= 0x40;
 	}
 
 	arr[15] = sdebug_lowest_aligned & 0xff;
 
-	if (sdebug_dif) {
+	if (have_dif_prot) {
 		arr[12] = (sdebug_dif - 1) << 1; /* P_TYPE */
 		arr[12] |= 1; /* PROT_EN */
 	}
@@ -1926,22 +1934,23 @@ static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
 static int resp_mode_sense(struct scsi_cmnd *scp,
 			   struct sdebug_dev_info *devip)
 {
-	unsigned char dbd, llbaa;
 	int pcontrol, pcode, subpcode, bd_len;
 	unsigned char dev_spec;
-	int alloc_len, msense_6, offset, len, target_dev_id;
+	int alloc_len, offset, len, target_dev_id;
 	int target = scp->device->id;
 	unsigned char * ap;
 	unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
 	unsigned char *cmd = scp->cmnd;
+	bool dbd, llbaa, msense_6, is_disk, bad_pcode;
 
-	dbd = !!(cmd[1] & 0x8);
+	dbd = !!(cmd[1] & 0x8);		/* disable block descriptors */
 	pcontrol = (cmd[2] & 0xc0) >> 6;
 	pcode = cmd[2] & 0x3f;
 	subpcode = cmd[3];
 	msense_6 = (MODE_SENSE == cmd[0]);
-	llbaa = msense_6 ? 0 : !!(cmd[1] & 0x10);
-	if ((0 == sdebug_ptype) && (0 == dbd))
+	llbaa = msense_6 ? false : !!(cmd[1] & 0x10);
+	is_disk = (0 == sdebug_ptype);
+	if (is_disk && !dbd)
 		bd_len = llbaa ? 16 : 8;
 	else
 		bd_len = 0;
@@ -1954,7 +1963,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
 	target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
 			(devip->target * 1000) - 3;
 	/* set DPOFUA bit for disks */
-	if (0 == sdebug_ptype)
+	if (is_disk)
 		dev_spec = 0x10;	/* would be 0x81 if read-only */
 	else
 		dev_spec = 0x0;
@@ -1993,6 +2002,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
 		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
 		return check_condition_result;
 	}
+	bad_pcode = false;
+
 	switch (pcode) {
 	case 0x1:	/* Read-Write error recovery page, direct access */
 		len = resp_err_recov_pg(ap, pcontrol, target);
@@ -2003,12 +2014,18 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
 		offset += len;
 		break;
         case 0x3:       /* Format device page, direct access */
-                len = resp_format_pg(ap, pcontrol, target);
-                offset += len;
+		if (is_disk) {
+			len = resp_format_pg(ap, pcontrol, target);
+			offset += len;
+		} else
+			bad_pcode = true;
                 break;
 	case 0x8:	/* Caching page, direct access */
-		len = resp_caching_pg(ap, pcontrol, target);
-		offset += len;
+		if (is_disk) {
+			len = resp_caching_pg(ap, pcontrol, target);
+			offset += len;
+		} else
+			bad_pcode = true;
 		break;
 	case 0xa:	/* Control Mode page, all devices */
 		len = resp_ctrl_m_pg(ap, pcontrol, target);
@@ -2037,8 +2054,12 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
 		if ((0 == subpcode) || (0xff == subpcode)) {
 			len = resp_err_recov_pg(ap, pcontrol, target);
 			len += resp_disconnect_pg(ap + len, pcontrol, target);
-			len += resp_format_pg(ap + len, pcontrol, target);
-			len += resp_caching_pg(ap + len, pcontrol, target);
+			if (is_disk) {
+				len += resp_format_pg(ap + len, pcontrol,
+						      target);
+				len += resp_caching_pg(ap + len, pcontrol,
+						       target);
+			}
 			len += resp_ctrl_m_pg(ap + len, pcontrol, target);
 			len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
 			if (0xff == subpcode) {
@@ -2047,13 +2068,17 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
 				len += resp_sas_sha_m_spg(ap + len, pcontrol);
 			}
 			len += resp_iec_m_pg(ap + len, pcontrol, target);
+			offset += len;
 		} else {
 			mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
 			return check_condition_result;
                 }
-		offset += len;
 		break;
 	default:
+		bad_pcode = true;
+		break;
+	}
+	if (bad_pcode) {
 		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
 		return check_condition_result;
 	}
@@ -2744,9 +2769,10 @@ static void unmap_region(sector_t lba, unsigned int len)
 		    lba + sdebug_unmap_granularity <= end &&
 		    index < map_size) {
 			clear_bit(index, map_storep);
-			if (sdebug_lbprz) {
+			if (sdebug_lbprz) {  /* for LBPRZ=2 return 0xff_s */
 				memset(fake_storep +
-				       lba * sdebug_sector_size, 0,
+				       lba * sdebug_sector_size,
+				       (sdebug_lbprz & 1) ? 0 : 0xff,
 				       sdebug_sector_size *
 				       sdebug_unmap_granularity);
 			}
@@ -4084,7 +4110,8 @@ MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)");
 MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
 MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
 MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
-MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)");
+MODULE_PARM_DESC(lbprz,
+	"on read unmapped LBs return 0 when 1 (def), return 0xff when 2");
 MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
 MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
 MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
@@ -4098,7 +4125,7 @@ MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err...
 MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
 MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
 MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
-MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])");
+MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=7[SPC-5])");
 MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
 MODULE_PARM_DESC(statistics, "collect statistics on commands, queues (def=1)");
 MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 11/12] scsi_debug: uuid for lu name
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (9 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 10/12] scsi_debug: vpd and mode page work Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:30   ` Hannes Reinecke
  2016-04-25 16:16 ` [PATCH 12/12] scsi_debug: use locally assigned naa Douglas Gilbert
  2016-04-29 23:53 ` [PATCH 00/12] scsi_debug: multiple queue support and cleanup Martin K. Petersen
  12 siblings, 1 reply; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Permit changing of a LU name from a (fake) IEEE registered
NAA (5) to a locally assigned UUID. Using a UUID (RFC 4122)
for a SCSI designator descriptor (e.g. a LU name) was added
in spc5r08.pdf (a draft INCITS standard) on 25 January 2016.
Add parameter uuid_ctl to use a separate UUID for each LU
(storage device) name. Additional option for all LU names to
be the same UUID (since their storage is shared). Previous
action of using NAA identifier for LU name remains the default.

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 99c4b49..46bdd3e 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -41,6 +41,7 @@
 #include <linux/interrupt.h>
 #include <linux/atomic.h>
 #include <linux/hrtimer.h>
+#include <linux/uuid.h>
 
 #include <net/checksum.h>
 
@@ -137,6 +138,7 @@ static const char *sdebug_version_date = "20160422";
 #define DEF_STRICT 0
 #define DEF_STATISTICS true
 #define DEF_SUBMIT_QUEUES 1
+#define DEF_UUID_CTL 0
 #define JDELAY_OVERRIDDEN -9999
 
 /* bit mask values for sdebug_opts */
@@ -237,6 +239,7 @@ struct sdebug_dev_info {
 	unsigned int channel;
 	unsigned int target;
 	u64 lun;
+	uuid_be lu_name;
 	struct sdebug_host_info *sdbg_host;
 	unsigned long uas_bm[1];
 	atomic_t num_in_q;
@@ -592,6 +595,7 @@ static unsigned int sdebug_unmap_granularity = DEF_UNMAP_GRANULARITY;
 static unsigned int sdebug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
 static unsigned int sdebug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
 static unsigned int sdebug_write_same_length = DEF_WRITESAME_LENGTH;
+static int sdebug_uuid_ctl = DEF_UUID_CTL;
 static bool sdebug_removable = DEF_REMOVABLE;
 static bool sdebug_clustering;
 static bool sdebug_host_lock = DEF_HOST_LOCK;
@@ -918,8 +922,8 @@ static const u64 naa5_comp_c = 0x5111111000000000ULL;
 /* Device identification VPD page. Returns number of bytes placed in arr */
 static int inquiry_vpd_83(unsigned char *arr, int port_group_id,
 			  int target_dev_id, int dev_id_num,
-			  const char *dev_id_str,
-			  int dev_id_str_len)
+			  const char *dev_id_str, int dev_id_str_len,
+			  const uuid_be *lu_name)
 {
 	int num, port_a;
 	char b[32];
@@ -936,13 +940,25 @@ static int inquiry_vpd_83(unsigned char *arr, int port_group_id,
 	arr[3] = num;
 	num += 4;
 	if (dev_id_num >= 0) {
-		/* NAA-5, Logical unit identifier (binary) */
-		arr[num++] = 0x1;	/* binary (not necessarily sas) */
-		arr[num++] = 0x3;	/* PIV=0, lu, naa */
-		arr[num++] = 0x0;
-		arr[num++] = 0x8;
-		put_unaligned_be64(naa5_comp_b + dev_id_num, arr + num);
-		num += 8;
+		if (sdebug_uuid_ctl) {
+			/* Locally assigned UUID */
+			arr[num++] = 0x1;  /* binary (not necessarily sas) */
+			arr[num++] = 0xa;  /* PIV=0, lu, naa */
+			arr[num++] = 0x0;
+			arr[num++] = 0x12;
+			arr[num++] = 0x10; /* uuid type=1, locally assigned */
+			arr[num++] = 0x0;
+			memcpy(arr + num, lu_name, 16);
+			num += 16;
+		} else {
+			/* NAA-5, Logical unit identifier (binary) */
+			arr[num++] = 0x1;  /* binary (not necessarily sas) */
+			arr[num++] = 0x3;  /* PIV=0, lu, naa */
+			arr[num++] = 0x0;
+			arr[num++] = 0x8;
+			put_unaligned_be64(naa5_comp_b + dev_id_num, arr + num);
+			num += 8;
+		}
 		/* Target relative port number */
 		arr[num++] = 0x61;	/* proto=sas, binary */
 		arr[num++] = 0x94;	/* PIV=1, target port, rel port */
@@ -1283,7 +1299,8 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 			arr[1] = cmd[2];	/*sanity */
 			arr[3] = inquiry_vpd_83(&arr[4], port_group_id,
 						target_dev_id, lu_id_num,
-						lu_id_str, len);
+						lu_id_str, len,
+						&devip->lu_name);
 		} else if (0x84 == cmd[2]) { /* Software interface ident. */
 			arr[1] = cmd[2];	/*sanity */
 			arr[3] = inquiry_vpd_84(&arr[4]);
@@ -3485,6 +3502,9 @@ static void sdebug_q_cmd_wq_complete(struct work_struct *work)
 	sdebug_q_cmd_complete(sd_dp);
 }
 
+static bool got_shared_uuid;
+static uuid_be shared_uuid;
+
 static struct sdebug_dev_info *sdebug_device_create(
 			struct sdebug_host_info *sdbg_host, gfp_t flags)
 {
@@ -3492,6 +3512,17 @@ static struct sdebug_dev_info *sdebug_device_create(
 
 	devip = kzalloc(sizeof(*devip), flags);
 	if (devip) {
+		if (1 == sdebug_uuid_ctl)
+			uuid_be_gen(&devip->lu_name);
+		else if (2 == sdebug_uuid_ctl) {
+			if (got_shared_uuid)
+				devip->lu_name = shared_uuid;
+			else {
+				uuid_be_gen(&shared_uuid);
+				got_shared_uuid = true;
+				devip->lu_name = shared_uuid;
+			}
+		}
 		devip->sdbg_host = sdbg_host;
 		list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
 	}
@@ -4085,6 +4116,7 @@ module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO);
 module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO);
 module_param_named(unmap_max_desc, sdebug_unmap_max_desc, int, S_IRUGO);
 module_param_named(virtual_gb, sdebug_virtual_gb, int, S_IRUGO | S_IWUSR);
+module_param_named(uuid_ctl, sdebug_uuid_ctl, int, S_IRUGO);
 module_param_named(vpd_use_hostno, sdebug_vpd_use_hostno, int,
 		   S_IRUGO | S_IWUSR);
 module_param_named(write_same_length, sdebug_write_same_length, int,
@@ -4134,6 +4166,8 @@ MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"
 MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
 MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
 MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
+MODULE_PARM_DESC(uuid_ctl,
+		 "1->use uuid for lu name, 0->don't, 2->all use same (def=0)");
 MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)");
 MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
 MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
@@ -4765,6 +4799,12 @@ static ssize_t strict_store(struct device_driver *ddp, const char *buf,
 }
 static DRIVER_ATTR_RW(strict);
 
+static ssize_t uuid_ctl_show(struct device_driver *ddp, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%d\n", !!sdebug_uuid_ctl);
+}
+static DRIVER_ATTR_RO(uuid_ctl);
+
 
 /* Note: The following array creates attribute files in the
    /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
@@ -4803,6 +4843,7 @@ static struct attribute *sdebug_drv_attrs[] = {
 	&driver_attr_host_lock.attr,
 	&driver_attr_ndelay.attr,
 	&driver_attr_strict.attr,
+	&driver_attr_uuid_ctl.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(sdebug_drv);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 12/12] scsi_debug: use locally assigned naa
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (10 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 11/12] scsi_debug: uuid for lu name Douglas Gilbert
@ 2016-04-25 16:16 ` Douglas Gilbert
  2016-04-26  6:31   ` Hannes Reinecke
  2016-04-29 23:53 ` [PATCH 00/12] scsi_debug: multiple queue support and cleanup Martin K. Petersen
  12 siblings, 1 reply; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-25 16:16 UTC (permalink / raw)
  To: linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

Change NAA addresses used for SAS addresses from fake IEEE
registered NAA (5) to locally assigned NAA (3).

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

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 46bdd3e..15f6d55 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -915,9 +915,10 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
 static const char * inq_vendor_id = "Linux   ";
 static const char * inq_product_id = "scsi_debug      ";
 static const char *inq_product_rev = "0186";	/* version less '.' */
-static const u64 naa5_comp_a = 0x5222222000000000ULL;
-static const u64 naa5_comp_b = 0x5333333000000000ULL;
-static const u64 naa5_comp_c = 0x5111111000000000ULL;
+/* Use some locallu assigned NAAs for SAS addresses. */
+static const u64 naa3_comp_a = 0x3222222000000000ULL;
+static const u64 naa3_comp_b = 0x3333333000000000ULL;
+static const u64 naa3_comp_c = 0x3111111000000000ULL;
 
 /* Device identification VPD page. Returns number of bytes placed in arr */
 static int inquiry_vpd_83(unsigned char *arr, int port_group_id,
@@ -951,12 +952,12 @@ static int inquiry_vpd_83(unsigned char *arr, int port_group_id,
 			memcpy(arr + num, lu_name, 16);
 			num += 16;
 		} else {
-			/* NAA-5, Logical unit identifier (binary) */
+			/* NAA-3, Logical unit identifier (binary) */
 			arr[num++] = 0x1;  /* binary (not necessarily sas) */
 			arr[num++] = 0x3;  /* PIV=0, lu, naa */
 			arr[num++] = 0x0;
 			arr[num++] = 0x8;
-			put_unaligned_be64(naa5_comp_b + dev_id_num, arr + num);
+			put_unaligned_be64(naa3_comp_b + dev_id_num, arr + num);
 			num += 8;
 		}
 		/* Target relative port number */
@@ -969,14 +970,14 @@ static int inquiry_vpd_83(unsigned char *arr, int port_group_id,
 		arr[num++] = 0x0;
 		arr[num++] = 0x1;	/* relative port A */
 	}
-	/* NAA-5, Target port identifier */
+	/* NAA-3, Target port identifier */
 	arr[num++] = 0x61;	/* proto=sas, binary */
 	arr[num++] = 0x93;	/* piv=1, target port, naa */
 	arr[num++] = 0x0;
 	arr[num++] = 0x8;
-	put_unaligned_be64(naa5_comp_a + port_a, arr + num);
+	put_unaligned_be64(naa3_comp_a + port_a, arr + num);
 	num += 8;
-	/* NAA-5, Target port group identifier */
+	/* NAA-3, Target port group identifier */
 	arr[num++] = 0x61;	/* proto=sas, binary */
 	arr[num++] = 0x95;	/* piv=1, target port group id */
 	arr[num++] = 0x0;
@@ -985,19 +986,19 @@ static int inquiry_vpd_83(unsigned char *arr, int port_group_id,
 	arr[num++] = 0;
 	put_unaligned_be16(port_group_id, arr + num);
 	num += 2;
-	/* NAA-5, Target device identifier */
+	/* NAA-3, Target device identifier */
 	arr[num++] = 0x61;	/* proto=sas, binary */
 	arr[num++] = 0xa3;	/* piv=1, target device, naa */
 	arr[num++] = 0x0;
 	arr[num++] = 0x8;
-	put_unaligned_be64(naa5_comp_a + target_dev_id, arr + num);
+	put_unaligned_be64(naa3_comp_a + target_dev_id, arr + num);
 	num += 8;
 	/* SCSI name string: Target device identifier */
 	arr[num++] = 0x63;	/* proto=sas, UTF-8 */
 	arr[num++] = 0xa8;	/* piv=1, target device, SCSI name string */
 	arr[num++] = 0x0;
 	arr[num++] = 24;
-	memcpy(arr + num, "naa.52222220", 12);
+	memcpy(arr + num, "naa.32222220", 12);
 	num += 12;
 	snprintf(b, sizeof(b), "%08X", target_dev_id);
 	memcpy(arr + num, b, 8);
@@ -1076,7 +1077,7 @@ static int inquiry_vpd_88(unsigned char *arr, int target_dev_id)
 	arr[num++] = 0x93;	/* PIV=1, target port, NAA */
 	arr[num++] = 0x0;	/* reserved */
 	arr[num++] = 0x8;	/* length */
-	put_unaligned_be64(naa5_comp_a + port_a, arr + num);
+	put_unaligned_be64(naa3_comp_a + port_a, arr + num);
 	num += 8;
 	arr[num++] = 0x0;	/* reserved */
 	arr[num++] = 0x0;	/* reserved */
@@ -1091,7 +1092,7 @@ static int inquiry_vpd_88(unsigned char *arr, int target_dev_id)
 	arr[num++] = 0x93;	/* PIV=1, target port, NAA */
 	arr[num++] = 0x0;	/* reserved */
 	arr[num++] = 0x8;	/* length */
-	put_unaligned_be64(naa5_comp_a + port_b, arr + num);
+	put_unaligned_be64(naa3_comp_a + port_b, arr + num);
 	num += 8;
 
 	return num;
@@ -1920,10 +1921,10 @@ static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target,
 		};
 	int port_a, port_b;
 
-	put_unaligned_be64(naa5_comp_a, sas_pcd_m_pg + 16);
-	put_unaligned_be64(naa5_comp_c + 1, sas_pcd_m_pg + 24);
-	put_unaligned_be64(naa5_comp_a, sas_pcd_m_pg + 64);
-	put_unaligned_be64(naa5_comp_c + 1, sas_pcd_m_pg + 72);
+	put_unaligned_be64(naa3_comp_a, sas_pcd_m_pg + 16);
+	put_unaligned_be64(naa3_comp_c + 1, sas_pcd_m_pg + 24);
+	put_unaligned_be64(naa3_comp_a, sas_pcd_m_pg + 64);
+	put_unaligned_be64(naa3_comp_c + 1, sas_pcd_m_pg + 72);
 	port_a = target_dev_id + 1;
 	port_b = port_a + 1;
 	memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg));
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH 01/12] scsi_debug: cleanup naming and bit crunching
  2016-04-25 16:16 ` [PATCH 01/12] scsi_debug: cleanup naming and bit crunching Douglas Gilbert
@ 2016-04-26  6:14   ` Hannes Reinecke
  2016-04-26 18:13   ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:14 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> Shorten file scope static and constant names. Use more
> get/put_unaligned calls to hide bit banging. Introduce
> sdebug_verbose boolean to replace frequent masking of
> option bit flags. Add GPL and bump version.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 1162 ++++++++++++++++++++-------------------------
>  1 file changed, 525 insertions(+), 637 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 02/12] scsi_debug: ignore host lock option
  2016-04-25 16:16 ` [PATCH 02/12] scsi_debug: ignore host lock option Douglas Gilbert
@ 2016-04-26  6:15   ` Hannes Reinecke
  0 siblings, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:15 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> Remove logic to optionally hold host_lock while each command is
> queued. Keep module and sysfs host_lock parameters for backward
> compatibility. Note in module parameter description that host_lock
> is ignored.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 44 +++++++-------------------------------------
>  1 file changed, 7 insertions(+), 37 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 03/12] scsi_debug: replace jiffy timers with hr timers
  2016-04-25 16:16 ` [PATCH 03/12] scsi_debug: replace jiffy timers with hr timers Douglas Gilbert
@ 2016-04-26  6:17   ` Hannes Reinecke
  2016-04-26 18:38   ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:17 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> The driver supports two command delay interfaces, the
> original one whose unit is a jiffy, and a newer one whose
> unit is a nanosecond. Each had different implementations.
> Keep both interfaces but simplify the implemenation to use a
> single delay mechanism based on high resolution timers.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 56 ++++++++++++++++++-----------------------------
>  1 file changed, 21 insertions(+), 35 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 04/12] scsi_debug: make jiffy delay name clearer
  2016-04-25 16:16 ` [PATCH 04/12] scsi_debug: make jiffy delay name clearer Douglas Gilbert
@ 2016-04-26  6:17   ` Hannes Reinecke
  0 siblings, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:17 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> Add 'j' to delay names to make it clearer that its unit is
> jiffies and to differentiate it from sdebug_ndelay whose unit is
> nanoseconds.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 46 +++++++++++++++++++++++-----------------------
>  1 file changed, 23 insertions(+), 23 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 05/12] scsi_debug: replace tasklet with work queue
  2016-04-25 16:16 ` [PATCH 05/12] scsi_debug: replace tasklet with work queue Douglas Gilbert
@ 2016-04-26  6:20   ` Hannes Reinecke
  0 siblings, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:20 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> When a negative value was placed in the delay parameter, a tasklet
> was scheduled. Change the tasklet to a work queue. Previously a
> delay of -1 scheduled a high priority tasklet; since there are no
> high priority work queues, treat -1 like other negative values
> in delay and schedule a work item.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 230 +++++++++++++++++++---------------------------
>  1 file changed, 95 insertions(+), 135 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 06/12] scsi_debug: re-order file scope declarations
  2016-04-25 16:16 ` [PATCH 06/12] scsi_debug: re-order file scope declarations Douglas Gilbert
@ 2016-04-26  6:21   ` Hannes Reinecke
  2016-04-26 20:55   ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:21 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> Group most defines together first; followed by struct definitions
> and then table and variable definitions. Normalize all function
> headers.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 314 ++++++++++++++++++++++------------------------
>  1 file changed, 151 insertions(+), 163 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 07/12] scsi_debug: use likely hints on fast path
  2016-04-25 16:16 ` [PATCH 07/12] scsi_debug: use likely hints on fast path Douglas Gilbert
@ 2016-04-26  6:22   ` Hannes Reinecke
  2016-04-26 22:14   ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:22 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> The most common commands in normal use are the READ and WRITE SCSI
> commands. Use likely and unlikely hints along the path taken by
> these commands. Rename check_readiness() to make_ua() and remove
> associated dead code. Rename devInfoReg() to find_build_dev_info().
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 219 ++++++++++++++++++++++------------------------
>  1 file changed, 105 insertions(+), 114 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 08/12] scsi_debug: rework resp_report_luns
  2016-04-25 16:16 ` [PATCH 08/12] scsi_debug: rework resp_report_luns Douglas Gilbert
@ 2016-04-26  6:26   ` Hannes Reinecke
  2016-04-27  4:08     ` Douglas Gilbert
  2016-04-26  7:33   ` Winkler, Tomas
  2016-04-27 23:09   ` Bart Van Assche
  2 siblings, 1 reply; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:26 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> Based on "[PATH V2] scsi_debug: rework resp_report_luns" patch
> sent by Tomas Winkler on Thursday, 26 Feb 2015. His notes:
>   1. Remove duplicated boundary checks which simplify the fill-in
>      loop
>   2. Use more of scsi generic API
> Replace fixed length response array a with heap allocation
> allowing up to 16383 LUNs per target.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 138 ++++++++++++++++++++++++++++++----------------
>  1 file changed, 91 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
> index cf44ab0..eac62b8 100644
> --- a/drivers/scsi/scsi_debug.c
> +++ b/drivers/scsi/scsi_debug.c
> @@ -3205,63 +3205,99 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
>  	return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
>  }
>  
> -#define SDEBUG_RLUN_ARR_SZ 256
> -
> -static int resp_report_luns(struct scsi_cmnd * scp,
> -			    struct sdebug_dev_info * devip)
> +/* Even though each pseudo target has a REPORT LUNS "well known logical unit"
> + * (W-LUN), the normal Linux scanning logic does not associate it with a
> + * device (e.g. /dev/sg7). The following magic will make that association:
> + *   "cd /sys/class/scsi_host/host<n> ; echo '- - 49409' > scan"
> + * where <n> is a host number. If there are multiple targets in a host then
> + * the above will associate a W-LUN to each target. To only get a W-LUN
> + * for target 2, then use "echo '- 2 49409' > scan" . */
> +static int resp_report_luns(struct scsi_cmnd *scp,
> +			    struct sdebug_dev_info *devip)
>  {
> +	unsigned char *cmd = scp->cmnd;
>  	unsigned int alloc_len;
> -	int lun_cnt, i, upper, num, n, want_wlun, shortish;
> +	unsigned char select_report;
>  	u64 lun;
> -	unsigned char *cmd = scp->cmnd;
> -	int select_report = (int)cmd[2];
> -	struct scsi_lun *one_lun;
> -	unsigned char arr[SDEBUG_RLUN_ARR_SZ];
> -	unsigned char * max_addr;
> +	struct scsi_lun *lun_p;
> +	u8 *arr;
> +	unsigned int lun_cnt;	/* normal LUN count (max: 16383) */
> +	unsigned int wlun_cnt;	/* report luns W-LUN count */
> +	unsigned int tlun_cnt;	/* total LUN count */
> +	unsigned int rlen;	/* response length (in bytes) less header */
> +	int i, res;
>  
>  	clear_luns_changed_on_target(devip);
> -	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
> -	shortish = (alloc_len < 4);
> -	if (shortish || (select_report > 2)) {
> -		mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
> +
> +	select_report = cmd[2];
> +	alloc_len = get_unaligned_be32(cmd + 6);
> +
> +	if (alloc_len < 4) {
> +		pr_err("alloc len too small %d\n", alloc_len);
> +		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
>  		return check_condition_result;
>  	}
> -	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
> -	memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
> +
> +	if (select_report > 0x02) {
> +		pr_err("select report invalid %d\n", select_report);
> +		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
> +		return check_condition_result;
> +	}
> +
>  	lun_cnt = sdebug_max_luns;
> -	if (1 == select_report)
> +	wlun_cnt = 0;
> +
> +	/* report only w_lun */
> +	if (select_report == 0x01)
>  		lun_cnt = 0;
> -	else if (sdebug_no_lun_0 && (lun_cnt > 0))
> +
> +	if (sdebug_no_lun_0 && (lun_cnt > 0))
>  		--lun_cnt;
> -	want_wlun = (select_report > 0) ? 1 : 0;
> -	num = lun_cnt + want_wlun;
> -	arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
> -	arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
> -	n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
> -			    sizeof(struct scsi_lun)), num);
> -	if (n < num) {
> -		want_wlun = 0;
> -		lun_cnt = n;
> -	}
> -	one_lun = (struct scsi_lun *) &arr[8];
> -	max_addr = arr + SDEBUG_RLUN_ARR_SZ;
> -	for (i = 0, lun = (sdebug_no_lun_0 ? 1 : 0);
> -             ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
> -	     i++, lun++) {
> -		upper = (lun >> 8) & 0x3f;
> -		if (upper)
> -			one_lun[i].scsi_lun[0] =
> -			    (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
> -		one_lun[i].scsi_lun[1] = lun & 0xff;
> -	}
> -	if (want_wlun) {
> -		one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff;
> -		one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
> -		i++;
> -	}
> -	alloc_len = (unsigned char *)(one_lun + i) - arr;
> -	return fill_from_dev_buffer(scp, arr,
> -				    min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
> +
> +	/* report w_lun */
> +	if (select_report == 0x01 || select_report == 0x02)
> +		wlun_cnt = 1;
> +
> +	tlun_cnt = lun_cnt + wlun_cnt;
> +	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
> +	arr = kzalloc((tlun_cnt * sizeof(lun_p->scsi_lun)) + 8, GFP_ATOMIC);
> +	if (!arr) {
> +		pr_warn("No space for report luns response\n");
> +		mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
> +				INSUFF_RES_ASCQ);
> +		return check_condition_result;
> +	}
> +	pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n",
> +		 select_report, lun_cnt, wlun_cnt, sdebug_no_lun_0);
> +
> +	lun = 0LL;
> +	/* luns start at offset 8 after the byte length */
> +	lun_p = (struct scsi_lun *)&arr[8];
> +
> +	/* skip lun 0 */
> +	if (sdebug_no_lun_0)
> +		lun++;
> +	/*
> +	 * Address method (we use Peripherial = 00b)
> +	 * 10b - Logical unit
> +	 * 00b - Peripherial device - Use this one
> +	 * 01b - Logical device
> +	 * 11b - reserved
> +	 */
> +	for (i = 0; i < lun_cnt; i++)
> +		int_to_scsilun(lun++, lun_p++);
> +
> +	/* report SCSI_W_LUN_REPORT_LUN */
> +	if (wlun_cnt)
> +		int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, lun_p++);
> +
> +	rlen = tlun_cnt * sizeof(struct scsi_lun);
> +
> +	put_unaligned_be32(rlen, &arr[0]);
> +
> +	res = fill_from_dev_buffer(scp, arr, rlen + 8);
> +	kfree(arr);
> +	return res;
>  }
>  
>  static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
> @@ -4299,6 +4335,10 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
>  	bool changed;
>  
>  	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
> +		if (n > 16383) {
> +			pr_warn("max_luns can be no more than 16383\n");
> +			return -EINVAL;
> +		}
>  		changed = (sdebug_max_luns != n);
>  		sdebug_max_luns = n;
>  		sdebug_max_tgts_luns();
> @@ -4643,6 +4683,10 @@ static int __init scsi_debug_init(void)
>  		pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp);
>  		return -EINVAL;
>  	}
> +	if (sdebug_max_luns > 16383) {
> +		pr_warn("max_luns can be no more than 16383, use default\n");
> +		sdebug_max_luns = DEF_MAX_LUNS;
> +	}
>  
>  	if (sdebug_lowest_aligned > 0x3fff) {
>  		pr_err("lowest_aligned too big: %u\n", sdebug_lowest_aligned);
> 
Hmm.

Have you actually checked this?

Thing is, only LUNs 0-255 are numbered sequentially; any higher LUNs
has to use one of the various encoding schemes, at which point the
sequentiality (sp?) breaks down.

So to be correct you probably should be using a loop from 0-255 to
generate the low-order LUNs, and another loop from 255 - lun_cnt to
construct the higher-order LUNs from the address method + lun number.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 09/12] scsi_debug: add multiple queue support
  2016-04-25 16:16 ` [PATCH 09/12] scsi_debug: add multiple queue support Douglas Gilbert
@ 2016-04-26  6:29   ` Hannes Reinecke
  2016-04-26 22:19   ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:29 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> Add submit_queue parameter (minimum and default: 1; maximum:
> nr_cpu_ids) that controls how many queues are built, each with
> their own lock and in_use bit vector. Add statistics parameter
> which is default on.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 662 +++++++++++++++++++++++++++++-----------------
>  1 file changed, 416 insertions(+), 246 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 10/12] scsi_debug: vpd and mode page work
  2016-04-25 16:16 ` [PATCH 10/12] scsi_debug: vpd and mode page work Douglas Gilbert
@ 2016-04-26  6:29   ` Hannes Reinecke
  0 siblings, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:29 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> Cleanup some mode and vpd pages. Stop reporting SBC (disk) pages
> when peripheral type is something else (e.g. tape). Update
> version descriptors. Expand LBPRZ flag handling.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 167 +++++++++++++++++++++++++++-------------------
>  1 file changed, 97 insertions(+), 70 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/12] scsi_debug: uuid for lu name
  2016-04-25 16:16 ` [PATCH 11/12] scsi_debug: uuid for lu name Douglas Gilbert
@ 2016-04-26  6:30   ` Hannes Reinecke
  0 siblings, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:30 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> Permit changing of a LU name from a (fake) IEEE registered
> NAA (5) to a locally assigned UUID. Using a UUID (RFC 4122)
> for a SCSI designator descriptor (e.g. a LU name) was added
> in spc5r08.pdf (a draft INCITS standard) on 25 January 2016.
> Add parameter uuid_ctl to use a separate UUID for each LU
> (storage device) name. Additional option for all LU names to
> be the same UUID (since their storage is shared). Previous
> action of using NAA identifier for LU name remains the default.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 61 +++++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 51 insertions(+), 10 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 12/12] scsi_debug: use locally assigned naa
  2016-04-25 16:16 ` [PATCH 12/12] scsi_debug: use locally assigned naa Douglas Gilbert
@ 2016-04-26  6:31   ` Hannes Reinecke
  0 siblings, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-26  6:31 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
> Change NAA addresses used for SAS addresses from fake IEEE
> registered NAA (5) to locally assigned NAA (3).
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
> ---
>  drivers/scsi/scsi_debug.c | 35 ++++++++++++++++++-----------------
>  1 file changed, 18 insertions(+), 17 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.com>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* RE: [PATCH 08/12] scsi_debug: rework resp_report_luns
  2016-04-25 16:16 ` [PATCH 08/12] scsi_debug: rework resp_report_luns Douglas Gilbert
  2016-04-26  6:26   ` Hannes Reinecke
@ 2016-04-26  7:33   ` Winkler, Tomas
  2016-04-27 23:09   ` Bart Van Assche
  2 siblings, 0 replies; 41+ messages in thread
From: Winkler, Tomas @ 2016-04-26  7:33 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, emilne



> 
> Based on "[PATH V2] scsi_debug: rework resp_report_luns" patch sent by
> Tomas Winkler on Thursday, 26 Feb 2015. His notes:
>   1. Remove duplicated boundary checks which simplify the fill-in
>      loop
>   2. Use more of scsi generic API
> Replace fixed length response array a with heap allocation allowing up to
> 16383 LUNs per target.
> 
> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
You can add my signed off.
Tomas

> ---
>  drivers/scsi/scsi_debug.c | 138 ++++++++++++++++++++++++++++++------------
> ----
>  1 file changed, 91 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index
> cf44ab0..eac62b8 100644
> --- a/drivers/scsi/scsi_debug.c
> +++ b/drivers/scsi/scsi_debug.c
> @@ -3205,63 +3205,99 @@ static int resp_get_lba_status(struct scsi_cmnd
> *scp,
>  	return fill_from_dev_buffer(scp, arr,
> SDEBUG_GET_LBA_STATUS_LEN);  }
> 
> -#define SDEBUG_RLUN_ARR_SZ 256
> -
> -static int resp_report_luns(struct scsi_cmnd * scp,
> -			    struct sdebug_dev_info * devip)
> +/* Even though each pseudo target has a REPORT LUNS "well known logical
> unit"
> + * (W-LUN), the normal Linux scanning logic does not associate it with
> +a
> + * device (e.g. /dev/sg7). The following magic will make that association:
> + *   "cd /sys/class/scsi_host/host<n> ; echo '- - 49409' > scan"
> + * where <n> is a host number. If there are multiple targets in a host
> +then
> + * the above will associate a W-LUN to each target. To only get a W-LUN
> + * for target 2, then use "echo '- 2 49409' > scan" . */ static int
> +resp_report_luns(struct scsi_cmnd *scp,
> +			    struct sdebug_dev_info *devip)
>  {
> +	unsigned char *cmd = scp->cmnd;
>  	unsigned int alloc_len;
> -	int lun_cnt, i, upper, num, n, want_wlun, shortish;
> +	unsigned char select_report;
>  	u64 lun;
> -	unsigned char *cmd = scp->cmnd;
> -	int select_report = (int)cmd[2];
> -	struct scsi_lun *one_lun;
> -	unsigned char arr[SDEBUG_RLUN_ARR_SZ];
> -	unsigned char * max_addr;
> +	struct scsi_lun *lun_p;
> +	u8 *arr;
> +	unsigned int lun_cnt;	/* normal LUN count (max: 16383) */
> +	unsigned int wlun_cnt;	/* report luns W-LUN count */
> +	unsigned int tlun_cnt;	/* total LUN count */
> +	unsigned int rlen;	/* response length (in bytes) less header */
> +	int i, res;
> 
>  	clear_luns_changed_on_target(devip);
> -	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
> -	shortish = (alloc_len < 4);
> -	if (shortish || (select_report > 2)) {
> -		mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
> +
> +	select_report = cmd[2];
> +	alloc_len = get_unaligned_be32(cmd + 6);
> +
> +	if (alloc_len < 4) {
> +		pr_err("alloc len too small %d\n", alloc_len);
> +		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
>  		return check_condition_result;
>  	}
> -	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
> -	memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
> +
> +	if (select_report > 0x02) {
> +		pr_err("select report invalid %d\n", select_report);
> +		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
> +		return check_condition_result;
> +	}
> +
>  	lun_cnt = sdebug_max_luns;
> -	if (1 == select_report)
> +	wlun_cnt = 0;
> +
> +	/* report only w_lun */
> +	if (select_report == 0x01)
>  		lun_cnt = 0;
> -	else if (sdebug_no_lun_0 && (lun_cnt > 0))
> +
> +	if (sdebug_no_lun_0 && (lun_cnt > 0))
>  		--lun_cnt;
> -	want_wlun = (select_report > 0) ? 1 : 0;
> -	num = lun_cnt + want_wlun;
> -	arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
> -	arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
> -	n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
> -			    sizeof(struct scsi_lun)), num);
> -	if (n < num) {
> -		want_wlun = 0;
> -		lun_cnt = n;
> -	}
> -	one_lun = (struct scsi_lun *) &arr[8];
> -	max_addr = arr + SDEBUG_RLUN_ARR_SZ;
> -	for (i = 0, lun = (sdebug_no_lun_0 ? 1 : 0);
> -             ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
> -	     i++, lun++) {
> -		upper = (lun >> 8) & 0x3f;
> -		if (upper)
> -			one_lun[i].scsi_lun[0] =
> -			    (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
> -		one_lun[i].scsi_lun[1] = lun & 0xff;
> -	}
> -	if (want_wlun) {
> -		one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) &
> 0xff;
> -		one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
> -		i++;
> -	}
> -	alloc_len = (unsigned char *)(one_lun + i) - arr;
> -	return fill_from_dev_buffer(scp, arr,
> -				    min((int)alloc_len,
> SDEBUG_RLUN_ARR_SZ));
> +
> +	/* report w_lun */
> +	if (select_report == 0x01 || select_report == 0x02)
> +		wlun_cnt = 1;
> +
> +	tlun_cnt = lun_cnt + wlun_cnt;
> +	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
> +	arr = kzalloc((tlun_cnt * sizeof(lun_p->scsi_lun)) + 8, GFP_ATOMIC);
> +	if (!arr) {
> +		pr_warn("No space for report luns response\n");
> +		mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
> +				INSUFF_RES_ASCQ);
> +		return check_condition_result;
> +	}
> +	pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n",
> +		 select_report, lun_cnt, wlun_cnt, sdebug_no_lun_0);
> +
> +	lun = 0LL;
> +	/* luns start at offset 8 after the byte length */
> +	lun_p = (struct scsi_lun *)&arr[8];
> +
> +	/* skip lun 0 */
> +	if (sdebug_no_lun_0)
> +		lun++;
> +	/*
> +	 * Address method (we use Peripherial = 00b)
> +	 * 10b - Logical unit
> +	 * 00b - Peripherial device - Use this one
> +	 * 01b - Logical device
> +	 * 11b - reserved
> +	 */
> +	for (i = 0; i < lun_cnt; i++)
> +		int_to_scsilun(lun++, lun_p++);
> +
> +	/* report SCSI_W_LUN_REPORT_LUN */
> +	if (wlun_cnt)
> +		int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, lun_p++);
> +
> +	rlen = tlun_cnt * sizeof(struct scsi_lun);
> +
> +	put_unaligned_be32(rlen, &arr[0]);
> +
> +	res = fill_from_dev_buffer(scp, arr, rlen + 8);
> +	kfree(arr);
> +	return res;
>  }
> 
>  static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
> @@ -4299,6 +4335,10 @@ static ssize_t max_luns_store(struct device_driver
> *ddp, const char *buf,
>  	bool changed;
> 
>  	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
> +		if (n > 16383) {
> +			pr_warn("max_luns can be no more than 16383\n");
> +			return -EINVAL;
> +		}
>  		changed = (sdebug_max_luns != n);
>  		sdebug_max_luns = n;
>  		sdebug_max_tgts_luns();
> @@ -4643,6 +4683,10 @@ static int __init scsi_debug_init(void)
>  		pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp);
>  		return -EINVAL;
>  	}
> +	if (sdebug_max_luns > 16383) {
> +		pr_warn("max_luns can be no more than 16383, use
> default\n");
> +		sdebug_max_luns = DEF_MAX_LUNS;
> +	}
> 
>  	if (sdebug_lowest_aligned > 0x3fff) {
>  		pr_err("lowest_aligned too big: %u\n",
> sdebug_lowest_aligned);
> --
> 2.7.4


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 01/12] scsi_debug: cleanup naming and bit crunching
  2016-04-25 16:16 ` [PATCH 01/12] scsi_debug: cleanup naming and bit crunching Douglas Gilbert
  2016-04-26  6:14   ` Hannes Reinecke
@ 2016-04-26 18:13   ` Bart Van Assche
  2016-04-26 18:27     ` James Bottomley
  2016-04-27  5:25     ` Douglas Gilbert
  1 sibling, 2 replies; 41+ messages in thread
From: Bart Van Assche @ 2016-04-26 18:13 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
> @@ -580,8 +580,8 @@ static int sdebug_sectors_per;		/* sectors per cylinder */
>
>   static unsigned int scsi_debug_lbp(void)
>   {
> -	return ((0 == scsi_debug_fake_rw) &&
> -		(scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
> +	return ((0 == sdebug_fake_rw) &&
> +		(sdebug_lbpu | sdebug_lbpws | sdebug_lbpws10));
>   }

Since you are changing this code, please remove the superfluous 
parentheses, place the constant at the right side of the comparison and 
change "|" into "||" since the intention of the above code is to perform 
a logical or and this code is not in a performance-critical path.

> +	sdebug_verbose = !!(SDEBUG_OPT_NOISE & sdebug_opts);
> +	sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & sdebug_opts);

Same comment here: please put constants at the right side. I think the 
latest version of checkpatch requests to do so.

Bart.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 01/12] scsi_debug: cleanup naming and bit crunching
  2016-04-26 18:13   ` Bart Van Assche
@ 2016-04-26 18:27     ` James Bottomley
  2016-04-27  5:25     ` Douglas Gilbert
  1 sibling, 0 replies; 41+ messages in thread
From: James Bottomley @ 2016-04-26 18:27 UTC (permalink / raw)
  To: Bart Van Assche, Douglas Gilbert, linux-scsi
  Cc: martin.petersen, tomas.winkler, emilne

On Tue, 2016-04-26 at 11:13 -0700, Bart Van Assche wrote:
> On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
> > @@ -580,8 +580,8 @@ static int sdebug_sectors_per;		/
> > * sectors per cylinder */
> > 
> >   static unsigned int scsi_debug_lbp(void)
> >   {
> > -	return ((0 == scsi_debug_fake_rw) &&
> > -		(scsi_debug_lbpu | scsi_debug_lbpws |
> > scsi_debug_lbpws10));
> > +	return ((0 == sdebug_fake_rw) &&
> > +		(sdebug_lbpu | sdebug_lbpws | sdebug_lbpws10));
> >   }
> 
> Since you are changing this code, please remove the superfluous 
> parentheses, place the constant at the right side of the comparison 
> and change "|" into "||" since the intention of the above code is to
> perform a logical or and this code is not in a performance-critical
> path.

This is getting completely pointless.  We're not slaves to checkpatch
and the Maintainer has considerable leeway to decide the style for
their code.  I personally don't like the const == rvalue form of compar
ison, but it does pick up an erroneous '=' instead of '==', so I'm not
going to object to a maintainer who wishes to use it.

Plus, if you only alter it in one place, the file becomes a mess of
styles and thus harder to read.

James



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 03/12] scsi_debug: replace jiffy timers with hr timers
  2016-04-25 16:16 ` [PATCH 03/12] scsi_debug: replace jiffy timers with hr timers Douglas Gilbert
  2016-04-26  6:17   ` Hannes Reinecke
@ 2016-04-26 18:38   ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Bart Van Assche @ 2016-04-26 18:38 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
> -				if (sdebug_ndelay > 0) {
> +				if ((sdebug_delay > 0) ||
> +				    (sdebug_ndelay > 0)) {
> [ ... ]
> -				if (sdebug_ndelay > 0) {
> +				if ((sdebug_delay > 0) ||
> +				    (sdebug_ndelay > 0)) {
> [ ... ]
> +	if ((delta_jiff > 0) || (sdebug_ndelay > 0)) {

Please do not introduce superfluous parentheses since this makes the 
code unnecessarily hard to read. Otherwise this patch looks fine to me.

Bart.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 06/12] scsi_debug: re-order file scope declarations
  2016-04-25 16:16 ` [PATCH 06/12] scsi_debug: re-order file scope declarations Douglas Gilbert
  2016-04-26  6:21   ` Hannes Reinecke
@ 2016-04-26 20:55   ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Bart Van Assche @ 2016-04-26 20:55 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
> +static unsigned int scsi_debug_lbp(void)
> +{
> +	return ((0 == sdebug_fake_rw) &&
> +		(sdebug_lbpu | sdebug_lbpws | sdebug_lbpws10));
> +}

Same comment here as for a previous patch: please do not introduce 
superfluous parentheses and please use logical or instead of binary or 
for combining boolean variables.

> @@ -1970,7 +1965,7 @@ resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
>   			(devip->target * 1000) - 3;
>   	/* set DPOFUA bit for disks */
>   	if (0 == sdebug_ptype)
> -		dev_spec = (DEV_READONLY(target) ? 0x80 : 0x0) | 0x10;
> +		dev_spec = 0x10;	/* would be 0x81 if read-only */
>   	else
>   		dev_spec = 0x0;
>   	if (msense_6) {

This change has not been explained in the patch description. Should it 
perhaps be merged into another patch of this series?

Bart.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 07/12] scsi_debug: use likely hints on fast path
  2016-04-25 16:16 ` [PATCH 07/12] scsi_debug: use likely hints on fast path Douglas Gilbert
  2016-04-26  6:22   ` Hannes Reinecke
@ 2016-04-26 22:14   ` Bart Van Assche
  2016-04-27  5:25     ` Douglas Gilbert
  1 sibling, 1 reply; 41+ messages in thread
From: Bart Van Assche @ 2016-04-26 22:14 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
> -	if ((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&
> -	    (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
> -	    ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
> +	if (unlikely((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&
> +		     (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
> +		     ((lba + num) > OPT_MEDIUM_ERR_ADDR))) {
 > [ ... ]
> -	if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
> +	if (unlikely((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE))) {
 > [ ... ]
> -	if ((qdepth > 0) && (num_in_q >= qdepth)) {
> +	if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) {
 > [ ... ]
> -	} else if ((sdebug_every_nth != 0) &&
> -		   (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
> -		   (scsi_result == 0)) {
> +	} else if (unlikely((sdebug_every_nth != 0) &&
> +			    (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
> +			    (scsi_result == 0))) {

Since you are modifying this code, please remove the superfluous 
parentheses.

 > -	struct sdebug_host_info * sdbg_host;
 > -	struct sdebug_dev_info * open_devip = NULL;
 > -	struct sdebug_dev_info * devip =
 > -			(struct sdebug_dev_info *)sdev->hostdata;
 > +	struct sdebug_host_info *sdbg_host;
 > +	struct sdebug_dev_info *open_devip = NULL;
 > +	struct sdebug_dev_info *devip;
 >
 > -	if (devip)
 > -		return devip;

Has this change been described in the patch description?

> @@ -4632,9 +4617,11 @@ static int __init scsi_debug_init(void)
>   	switch (sdebug_dif) {
>
>   	case SD_DIF_TYPE0_PROTECTION:
> +		break;
>   	case SD_DIF_TYPE1_PROTECTION:
>   	case SD_DIF_TYPE2_PROTECTION:
>   	case SD_DIF_TYPE3_PROTECTION:
> +		have_dif_prot = true;
>   		break;

Same comment for this code: has this change been explained in the patch 
description?

Bart.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 09/12] scsi_debug: add multiple queue support
  2016-04-25 16:16 ` [PATCH 09/12] scsi_debug: add multiple queue support Douglas Gilbert
  2016-04-26  6:29   ` Hannes Reinecke
@ 2016-04-26 22:19   ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Bart Van Assche @ 2016-04-26 22:19 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
> - * (for response) at one time. Can be reduced by max_queue option. Command
> - * responses are not queued when jdelay=0 and ndelay=0. The per-device
> - * DEF_CMD_PER_LUN can be changed via sysfs:
> - * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed
> - * SCSI_DEBUG_CANQUEUE. */
> -#define SCSI_DEBUG_CANQUEUE_WORDS  9	/* a WORD is bits in a long */
> + * (for response) per submit queue at one time. Can be reduced by max_queue
> + * option. Command responses are not queued when jdelay=0 and ndelay=0. The
> + * per-device DEF_CMD_PER_LUN can be changed via sysfs:
> + * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but . */
> +#define SCSI_DEBUG_CANQUEUE_WORDS  3	/* a WORD is bits in a long */
>   #define SCSI_DEBUG_CANQUEUE  (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
>   #define DEF_CMD_PER_LUN  255

The original comment has the text "but cannot exceed 
SCSI_DEBUG_CANQUEUE". That text has been changed into "but .". Has that 
last part of the comment been changed on purpose?

Bart.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 08/12] scsi_debug: rework resp_report_luns
  2016-04-26  6:26   ` Hannes Reinecke
@ 2016-04-27  4:08     ` Douglas Gilbert
  2016-04-27  5:58       ` Hannes Reinecke
  0 siblings, 1 reply; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-27  4:08 UTC (permalink / raw)
  To: Hannes Reinecke, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 2016-04-26 02:26 AM, Hannes Reinecke wrote:
> On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
>> Based on "[PATH V2] scsi_debug: rework resp_report_luns" patch
>> sent by Tomas Winkler on Thursday, 26 Feb 2015. His notes:
>>    1. Remove duplicated boundary checks which simplify the fill-in
>>       loop
>>    2. Use more of scsi generic API
>> Replace fixed length response array a with heap allocation
>> allowing up to 16383 LUNs per target.
>>
>> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
>> ---
>>   drivers/scsi/scsi_debug.c | 138 ++++++++++++++++++++++++++++++----------------
>>   1 file changed, 91 insertions(+), 47 deletions(-)
>>
>> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
>> index cf44ab0..eac62b8 100644
>> --- a/drivers/scsi/scsi_debug.c
>> +++ b/drivers/scsi/scsi_debug.c
>> @@ -3205,63 +3205,99 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
>>   	return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
>>   }
>>
>> -#define SDEBUG_RLUN_ARR_SZ 256
>> -
>> -static int resp_report_luns(struct scsi_cmnd * scp,
>> -			    struct sdebug_dev_info * devip)
>> +/* Even though each pseudo target has a REPORT LUNS "well known logical unit"
>> + * (W-LUN), the normal Linux scanning logic does not associate it with a
>> + * device (e.g. /dev/sg7). The following magic will make that association:
>> + *   "cd /sys/class/scsi_host/host<n> ; echo '- - 49409' > scan"
>> + * where <n> is a host number. If there are multiple targets in a host then
>> + * the above will associate a W-LUN to each target. To only get a W-LUN
>> + * for target 2, then use "echo '- 2 49409' > scan" . */
>> +static int resp_report_luns(struct scsi_cmnd *scp,
>> +			    struct sdebug_dev_info *devip)
>>   {
>> +	unsigned char *cmd = scp->cmnd;
>>   	unsigned int alloc_len;
>> -	int lun_cnt, i, upper, num, n, want_wlun, shortish;
>> +	unsigned char select_report;
>>   	u64 lun;
>> -	unsigned char *cmd = scp->cmnd;
>> -	int select_report = (int)cmd[2];
>> -	struct scsi_lun *one_lun;
>> -	unsigned char arr[SDEBUG_RLUN_ARR_SZ];
>> -	unsigned char * max_addr;
>> +	struct scsi_lun *lun_p;
>> +	u8 *arr;
>> +	unsigned int lun_cnt;	/* normal LUN count (max: 16383) */
>> +	unsigned int wlun_cnt;	/* report luns W-LUN count */
>> +	unsigned int tlun_cnt;	/* total LUN count */
>> +	unsigned int rlen;	/* response length (in bytes) less header */
>> +	int i, res;
>>
>>   	clear_luns_changed_on_target(devip);
>> -	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
>> -	shortish = (alloc_len < 4);
>> -	if (shortish || (select_report > 2)) {
>> -		mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
>> +
>> +	select_report = cmd[2];
>> +	alloc_len = get_unaligned_be32(cmd + 6);
>> +
>> +	if (alloc_len < 4) {
>> +		pr_err("alloc len too small %d\n", alloc_len);
>> +		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
>>   		return check_condition_result;
>>   	}
>> -	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
>> -	memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
>> +
>> +	if (select_report > 0x02) {
>> +		pr_err("select report invalid %d\n", select_report);
>> +		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
>> +		return check_condition_result;
>> +	}
>> +
>>   	lun_cnt = sdebug_max_luns;
>> -	if (1 == select_report)
>> +	wlun_cnt = 0;
>> +
>> +	/* report only w_lun */
>> +	if (select_report == 0x01)
>>   		lun_cnt = 0;
>> -	else if (sdebug_no_lun_0 && (lun_cnt > 0))
>> +
>> +	if (sdebug_no_lun_0 && (lun_cnt > 0))
>>   		--lun_cnt;
>> -	want_wlun = (select_report > 0) ? 1 : 0;
>> -	num = lun_cnt + want_wlun;
>> -	arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
>> -	arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
>> -	n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
>> -			    sizeof(struct scsi_lun)), num);
>> -	if (n < num) {
>> -		want_wlun = 0;
>> -		lun_cnt = n;
>> -	}
>> -	one_lun = (struct scsi_lun *) &arr[8];
>> -	max_addr = arr + SDEBUG_RLUN_ARR_SZ;
>> -	for (i = 0, lun = (sdebug_no_lun_0 ? 1 : 0);
>> -             ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
>> -	     i++, lun++) {
>> -		upper = (lun >> 8) & 0x3f;
>> -		if (upper)
>> -			one_lun[i].scsi_lun[0] =
>> -			    (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
>> -		one_lun[i].scsi_lun[1] = lun & 0xff;
>> -	}
>> -	if (want_wlun) {
>> -		one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff;
>> -		one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
>> -		i++;
>> -	}
>> -	alloc_len = (unsigned char *)(one_lun + i) - arr;
>> -	return fill_from_dev_buffer(scp, arr,
>> -				    min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
>> +
>> +	/* report w_lun */
>> +	if (select_report == 0x01 || select_report == 0x02)
>> +		wlun_cnt = 1;
>> +
>> +	tlun_cnt = lun_cnt + wlun_cnt;
>> +	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
>> +	arr = kzalloc((tlun_cnt * sizeof(lun_p->scsi_lun)) + 8, GFP_ATOMIC);
>> +	if (!arr) {
>> +		pr_warn("No space for report luns response\n");
>> +		mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
>> +				INSUFF_RES_ASCQ);
>> +		return check_condition_result;
>> +	}
>> +	pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n",
>> +		 select_report, lun_cnt, wlun_cnt, sdebug_no_lun_0);
>> +
>> +	lun = 0LL;
>> +	/* luns start at offset 8 after the byte length */
>> +	lun_p = (struct scsi_lun *)&arr[8];
>> +
>> +	/* skip lun 0 */
>> +	if (sdebug_no_lun_0)
>> +		lun++;
>> +	/*
>> +	 * Address method (we use Peripherial = 00b)
>> +	 * 10b - Logical unit
>> +	 * 00b - Peripherial device - Use this one
>> +	 * 01b - Logical device
>> +	 * 11b - reserved
>> +	 */
>> +	for (i = 0; i < lun_cnt; i++)
>> +		int_to_scsilun(lun++, lun_p++);
>> +
>> +	/* report SCSI_W_LUN_REPORT_LUN */
>> +	if (wlun_cnt)
>> +		int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, lun_p++);
>> +
>> +	rlen = tlun_cnt * sizeof(struct scsi_lun);
>> +
>> +	put_unaligned_be32(rlen, &arr[0]);
>> +
>> +	res = fill_from_dev_buffer(scp, arr, rlen + 8);
>> +	kfree(arr);
>> +	return res;
>>   }
>>
>>   static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
>> @@ -4299,6 +4335,10 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
>>   	bool changed;
>>
>>   	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
>> +		if (n > 16383) {
>> +			pr_warn("max_luns can be no more than 16383\n");
>> +			return -EINVAL;
>> +		}
>>   		changed = (sdebug_max_luns != n);
>>   		sdebug_max_luns = n;
>>   		sdebug_max_tgts_luns();
>> @@ -4643,6 +4683,10 @@ static int __init scsi_debug_init(void)
>>   		pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp);
>>   		return -EINVAL;
>>   	}
>> +	if (sdebug_max_luns > 16383) {
>> +		pr_warn("max_luns can be no more than 16383, use default\n");
>> +		sdebug_max_luns = DEF_MAX_LUNS;
>> +	}
>>
>>   	if (sdebug_lowest_aligned > 0x3fff) {
>>   		pr_err("lowest_aligned too big: %u\n", sdebug_lowest_aligned);
>>
> Hmm.
>
> Have you actually checked this?

Yes I did and it worked!! It took 13 minutes on my laptop with
'max_luns=16383' and after that I could access various LUs across
that range. You can try it yourself :-)

> Thing is, only LUNs 0-255 are numbered sequentially; any higher LUNs
> has to use one of the various encoding schemes, at which point the
> sequentiality (sp?) breaks down.

I checked sam6r01.pdf clause 4.7.5 and you are correct. So the
comment inherited from Tomas's patch about 16k luns is wrong.

> So to be correct you probably should be using a loop from 0-255 to
> generate the low-order LUNs, and another loop from 255 - lun_cnt to
> construct the higher-order LUNs from the address method + lun number.

So should I scale max_luns back to no more than 256 (which should
produce LUNs 0...255 (or if no_lun_0=1 produce LUNs 1...255)), or
switch to flat space addressing (address_method=1) at LUN 256
through 16383?

The driver already has the capability of building an arbitrary
number of targets (num_tgts) and hosts (add_host: it says a max
of 127 but that is not enforced). The previous limit on LUNs
(per target, per host) was 31.

Doug Gilbert



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 01/12] scsi_debug: cleanup naming and bit crunching
  2016-04-26 18:13   ` Bart Van Assche
  2016-04-26 18:27     ` James Bottomley
@ 2016-04-27  5:25     ` Douglas Gilbert
  1 sibling, 0 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-27  5:25 UTC (permalink / raw)
  To: Bart Van Assche, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 2016-04-26 02:13 PM, Bart Van Assche wrote:
> On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
>> @@ -580,8 +580,8 @@ static int sdebug_sectors_per;        /* sectors per
>> cylinder */
>>
>>   static unsigned int scsi_debug_lbp(void)
>>   {
>> -    return ((0 == scsi_debug_fake_rw) &&
>> -        (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10));
>> +    return ((0 == sdebug_fake_rw) &&
>> +        (sdebug_lbpu | sdebug_lbpws | sdebug_lbpws10));
>>   }
>
> Since you are changing this code, please remove the superfluous parentheses,
> place the constant at the right side of the comparison and change "|" into "||"
> since the intention of the above code is to perform a logical or and this code
> is not in a performance-critical path.

Hmmm. I hadn't even noticed the bitwise ORs. Not sure why
Martin did that. Anyway I can change it.

BTW I had no intention of changing Martin's LB provisioning logic.
Those lines appear in the patch due to the name shortening.

>> +    sdebug_verbose = !!(SDEBUG_OPT_NOISE & sdebug_opts);
>> +    sdebug_any_injecting_opt = !!(SDEBUG_OPT_ALL_INJECTING & sdebug_opts);
>
> Same comment here: please put constants at the right side. I think the latest
> version of checkpatch requests to do so.

The whole patch series went through checkpatch.pl without
errors or warnings on linux-stable.git .

Doug Gilbert



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 07/12] scsi_debug: use likely hints on fast path
  2016-04-26 22:14   ` Bart Van Assche
@ 2016-04-27  5:25     ` Douglas Gilbert
  2016-04-27  5:33       ` Bart Van Assche
  2016-04-27 14:29       ` Bart Van Assche
  0 siblings, 2 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-27  5:25 UTC (permalink / raw)
  To: Bart Van Assche, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 2016-04-26 06:14 PM, Bart Van Assche wrote:
> On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
>> -    if ((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&
>> -        (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
>> -        ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
>> +    if (unlikely((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&
>> +             (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
>> +             ((lba + num) > OPT_MEDIUM_ERR_ADDR))) {
>  > [ ... ]
>> -    if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
>> +    if (unlikely((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE))) {
>  > [ ... ]
>> -    if ((qdepth > 0) && (num_in_q >= qdepth)) {
>> +    if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) {
>  > [ ... ]
>> -    } else if ((sdebug_every_nth != 0) &&
>> -           (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
>> -           (scsi_result == 0)) {
>> +    } else if (unlikely((sdebug_every_nth != 0) &&
>> +                (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
>> +                (scsi_result == 0))) {
>
> Since you are modifying this code, please remove the superfluous parentheses.

I can find no reference to "superfluous parentheses" in
Documentation/CodingStyle . As for the improved readability of:

            else if (unlikely(sdebug_every_nth != 0 &&
                       SDEBUG_OPT_RARE_TSF & sdebug_opts &&
                       scsi_result == 0)) {
I have my doubts.

>  > -    struct sdebug_host_info * sdbg_host;
>  > -    struct sdebug_dev_info * open_devip = NULL;
>  > -    struct sdebug_dev_info * devip =
>  > -            (struct sdebug_dev_info *)sdev->hostdata;
>  > +    struct sdebug_host_info *sdbg_host;
>  > +    struct sdebug_dev_info *open_devip = NULL;
>  > +    struct sdebug_dev_info *devip;
>  >
>  > -    if (devip)
>  > -        return devip;
>
> Has this change been described in the patch description?

The function was previously called devInfoReg() and was called
irrespective of whether a suitable sdebug_dev_info instance
existed or not. So that function call just wasted time if an
instance existed. That function is replaced by
find_build_dev_info() which is only called when non trivial work
is needed. Its invocation looks like this:
         if (NULL == devip) {
                 devip = find_build_dev_info(sdp);
                 if (NULL == devip)
                         return 1;  /* no resources, will be marked offline */
         }

Do all re-factorings of code need a patch description?

>> @@ -4632,9 +4617,11 @@ static int __init scsi_debug_init(void)
>>       switch (sdebug_dif) {
>>
>>       case SD_DIF_TYPE0_PROTECTION:
>> +        break;
>>       case SD_DIF_TYPE1_PROTECTION:
>>       case SD_DIF_TYPE2_PROTECTION:
>>       case SD_DIF_TYPE3_PROTECTION:
>> +        have_dif_prot = true;
>>           break;
>
> Same comment for this code: has this change been explained in the patch
> description?

The code previously did things like
         if (!sdebug_dif) { /* whatever */ }
which annoyed me because it relied on knowing that the badly
named SD_DIF_TYPE0_PROTECTION (which is _no_ protection) has
the value 0. So I introduced a bool at file scope (thus it is
initialized to false and checkpatch.pl complains if that is
stated explicitly). The above code is where the bool (i.e.
have_dif_prot) is set.

Doug Gilbert


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 07/12] scsi_debug: use likely hints on fast path
  2016-04-27  5:25     ` Douglas Gilbert
@ 2016-04-27  5:33       ` Bart Van Assche
  2016-04-27 14:29       ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Bart Van Assche @ 2016-04-27  5:33 UTC (permalink / raw)
  To: dgilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/26/16 22:25, Douglas Gilbert wrote:
> Do all re-factorings of code need a patch description?

Describing all changes makes the job of a reviewer easier because if all 
changes have been described the reviewer only has to verify the changes 
against the patch description instead of additionally having to figure 
out the purpose of changes that have not been described.

Bart.


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 08/12] scsi_debug: rework resp_report_luns
  2016-04-27  4:08     ` Douglas Gilbert
@ 2016-04-27  5:58       ` Hannes Reinecke
  0 siblings, 0 replies; 41+ messages in thread
From: Hannes Reinecke @ 2016-04-27  5:58 UTC (permalink / raw)
  To: dgilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/27/2016 06:08 AM, Douglas Gilbert wrote:
> On 2016-04-26 02:26 AM, Hannes Reinecke wrote:
>> On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
>>> Based on "[PATH V2] scsi_debug: rework resp_report_luns" patch
>>> sent by Tomas Winkler on Thursday, 26 Feb 2015. His notes:
>>>    1. Remove duplicated boundary checks which simplify the fill-in
>>>       loop
>>>    2. Use more of scsi generic API
>>> Replace fixed length response array a with heap allocation
>>> allowing up to 16383 LUNs per target.
>>>
>>> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
>>> ---
>>>   drivers/scsi/scsi_debug.c | 138
>>> ++++++++++++++++++++++++++++++----------------
>>>   1 file changed, 91 insertions(+), 47 deletions(-)
>>>
>>> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
>>> index cf44ab0..eac62b8 100644
>>> --- a/drivers/scsi/scsi_debug.c
>>> +++ b/drivers/scsi/scsi_debug.c
>>> @@ -3205,63 +3205,99 @@ static int resp_get_lba_status(struct
>>> scsi_cmnd *scp,
>>>       return fill_from_dev_buffer(scp, arr,
>>> SDEBUG_GET_LBA_STATUS_LEN);
>>>   }
>>>
>>> -#define SDEBUG_RLUN_ARR_SZ 256
>>> -
>>> -static int resp_report_luns(struct scsi_cmnd * scp,
>>> -                struct sdebug_dev_info * devip)
>>> +/* Even though each pseudo target has a REPORT LUNS "well known
>>> logical unit"
>>> + * (W-LUN), the normal Linux scanning logic does not associate
>>> it with a
>>> + * device (e.g. /dev/sg7). The following magic will make that
>>> association:
>>> + *   "cd /sys/class/scsi_host/host<n> ; echo '- - 49409' > scan"
>>> + * where <n> is a host number. If there are multiple targets in
>>> a host then
>>> + * the above will associate a W-LUN to each target. To only get
>>> a W-LUN
>>> + * for target 2, then use "echo '- 2 49409' > scan" . */
>>> +static int resp_report_luns(struct scsi_cmnd *scp,
>>> +                struct sdebug_dev_info *devip)
>>>   {
>>> +    unsigned char *cmd = scp->cmnd;
>>>       unsigned int alloc_len;
>>> -    int lun_cnt, i, upper, num, n, want_wlun, shortish;
>>> +    unsigned char select_report;
>>>       u64 lun;
>>> -    unsigned char *cmd = scp->cmnd;
>>> -    int select_report = (int)cmd[2];
>>> -    struct scsi_lun *one_lun;
>>> -    unsigned char arr[SDEBUG_RLUN_ARR_SZ];
>>> -    unsigned char * max_addr;
>>> +    struct scsi_lun *lun_p;
>>> +    u8 *arr;
>>> +    unsigned int lun_cnt;    /* normal LUN count (max: 16383) */
>>> +    unsigned int wlun_cnt;    /* report luns W-LUN count */
>>> +    unsigned int tlun_cnt;    /* total LUN count */
>>> +    unsigned int rlen;    /* response length (in bytes) less
>>> header */
>>> +    int i, res;
>>>
>>>       clear_luns_changed_on_target(devip);
>>> -    alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) +
>>> (cmd[6] << 24);
>>> -    shortish = (alloc_len < 4);
>>> -    if (shortish || (select_report > 2)) {
>>> -        mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2,
>>> -1);
>>> +
>>> +    select_report = cmd[2];
>>> +    alloc_len = get_unaligned_be32(cmd + 6);
>>> +
>>> +    if (alloc_len < 4) {
>>> +        pr_err("alloc len too small %d\n", alloc_len);
>>> +        mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
>>>           return check_condition_result;
>>>       }
>>> -    /* can produce response with up to 16k luns (lun 0 to lun
>>> 16383) */
>>> -    memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
>>> +
>>> +    if (select_report > 0x02) {
>>> +        pr_err("select report invalid %d\n", select_report);
>>> +        mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
>>> +        return check_condition_result;
>>> +    }
>>> +
>>>       lun_cnt = sdebug_max_luns;
>>> -    if (1 == select_report)
>>> +    wlun_cnt = 0;
>>> +
>>> +    /* report only w_lun */
>>> +    if (select_report == 0x01)
>>>           lun_cnt = 0;
>>> -    else if (sdebug_no_lun_0 && (lun_cnt > 0))
>>> +
>>> +    if (sdebug_no_lun_0 && (lun_cnt > 0))
>>>           --lun_cnt;
>>> -    want_wlun = (select_report > 0) ? 1 : 0;
>>> -    num = lun_cnt + want_wlun;
>>> -    arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
>>> -    arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
>>> -    n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
>>> -                sizeof(struct scsi_lun)), num);
>>> -    if (n < num) {
>>> -        want_wlun = 0;
>>> -        lun_cnt = n;
>>> -    }
>>> -    one_lun = (struct scsi_lun *) &arr[8];
>>> -    max_addr = arr + SDEBUG_RLUN_ARR_SZ;
>>> -    for (i = 0, lun = (sdebug_no_lun_0 ? 1 : 0);
>>> -             ((i < lun_cnt) && ((unsigned char *)(one_lun + i) <
>>> max_addr));
>>> -         i++, lun++) {
>>> -        upper = (lun >> 8) & 0x3f;
>>> -        if (upper)
>>> -            one_lun[i].scsi_lun[0] =
>>> -                (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
>>> -        one_lun[i].scsi_lun[1] = lun & 0xff;
>>> -    }
>>> -    if (want_wlun) {
>>> -        one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) &
>>> 0xff;
>>> -        one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
>>> -        i++;
>>> -    }
>>> -    alloc_len = (unsigned char *)(one_lun + i) - arr;
>>> -    return fill_from_dev_buffer(scp, arr,
>>> -                    min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
>>> +
>>> +    /* report w_lun */
>>> +    if (select_report == 0x01 || select_report == 0x02)
>>> +        wlun_cnt = 1;
>>> +
>>> +    tlun_cnt = lun_cnt + wlun_cnt;
>>> +    /* can produce response with up to 16k luns (lun 0 to lun
>>> 16383) */
>>> +    arr = kzalloc((tlun_cnt * sizeof(lun_p->scsi_lun)) + 8,
>>> GFP_ATOMIC);
>>> +    if (!arr) {
>>> +        pr_warn("No space for report luns response\n");
>>> +        mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
>>> +                INSUFF_RES_ASCQ);
>>> +        return check_condition_result;
>>> +    }
>>> +    pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n",
>>> +         select_report, lun_cnt, wlun_cnt, sdebug_no_lun_0);
>>> +
>>> +    lun = 0LL;
>>> +    /* luns start at offset 8 after the byte length */
>>> +    lun_p = (struct scsi_lun *)&arr[8];
>>> +
>>> +    /* skip lun 0 */
>>> +    if (sdebug_no_lun_0)
>>> +        lun++;
>>> +    /*
>>> +     * Address method (we use Peripherial = 00b)
>>> +     * 10b - Logical unit
>>> +     * 00b - Peripherial device - Use this one
>>> +     * 01b - Logical device
>>> +     * 11b - reserved
>>> +     */
>>> +    for (i = 0; i < lun_cnt; i++)
>>> +        int_to_scsilun(lun++, lun_p++);
>>> +
>>> +    /* report SCSI_W_LUN_REPORT_LUN */
>>> +    if (wlun_cnt)
>>> +        int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, lun_p++);
>>> +
>>> +    rlen = tlun_cnt * sizeof(struct scsi_lun);
>>> +
>>> +    put_unaligned_be32(rlen, &arr[0]);
>>> +
>>> +    res = fill_from_dev_buffer(scp, arr, rlen + 8);
>>> +    kfree(arr);
>>> +    return res;
>>>   }
>>>
>>>   static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned
>>> long long lba,
>>> @@ -4299,6 +4335,10 @@ static ssize_t max_luns_store(struct
>>> device_driver *ddp, const char *buf,
>>>       bool changed;
>>>
>>>       if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
>>> +        if (n > 16383) {
>>> +            pr_warn("max_luns can be no more than 16383\n");
>>> +            return -EINVAL;
>>> +        }
>>>           changed = (sdebug_max_luns != n);
>>>           sdebug_max_luns = n;
>>>           sdebug_max_tgts_luns();
>>> @@ -4643,6 +4683,10 @@ static int __init scsi_debug_init(void)
>>>           pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp);
>>>           return -EINVAL;
>>>       }
>>> +    if (sdebug_max_luns > 16383) {
>>> +        pr_warn("max_luns can be no more than 16383, use
>>> default\n");
>>> +        sdebug_max_luns = DEF_MAX_LUNS;
>>> +    }
>>>
>>>       if (sdebug_lowest_aligned > 0x3fff) {
>>>           pr_err("lowest_aligned too big: %u\n",
>>> sdebug_lowest_aligned);
>>>
>> Hmm.
>>
>> Have you actually checked this?
> 
> Yes I did and it worked!! It took 13 minutes on my laptop with
> 'max_luns=16383' and after that I could access various LUs across
> that range. You can try it yourself :-)
> 
Oh, I do not doubt that it'll be able to create LUNs with these
numbers. The point being that the LUN numbers beyond 255 generated
with this simple algorithm are non-standard.

>> Thing is, only LUNs 0-255 are numbered sequentially; any higher LUNs
>> has to use one of the various encoding schemes, at which point the
>> sequentiality (sp?) breaks down.
> 
> I checked sam6r01.pdf clause 4.7.5 and you are correct. So the
> comment inherited from Tomas's patch about 16k luns is wrong.
> 
>> So to be correct you probably should be using a loop from 0-255 to
>> generate the low-order LUNs, and another loop from 255 - lun_cnt to
>> construct the higher-order LUNs from the address method + lun number.
> 
> So should I scale max_luns back to no more than 256 (which should
> produce LUNs 0...255 (or if no_lun_0=1 produce LUNs 1...255)), or
> switch to flat space addressing (address_method=1) at LUN 256
> through 16383?
> 
Switch to flat space addressing, please.
(Or, even better, have a flag allowing to select the addressing
method). There is no need to arbitrary restrict ourselves to 256
LUNs (we got plenty of 'real' SCSI targets with do exactly this).
What we need is the ability to validate the SCSI stack (and OS
tooling) against LUN numbers higher than 256, possibly using some of
the more exotic LUN enumeration schemes.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 07/12] scsi_debug: use likely hints on fast path
  2016-04-27  5:25     ` Douglas Gilbert
  2016-04-27  5:33       ` Bart Van Assche
@ 2016-04-27 14:29       ` Bart Van Assche
  1 sibling, 0 replies; 41+ messages in thread
From: Bart Van Assche @ 2016-04-27 14:29 UTC (permalink / raw)
  To: dgilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/26/16 22:25, Douglas Gilbert wrote:
> On 2016-04-26 06:14 PM, Bart Van Assche wrote:
>> On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
>>> -    if ((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&
>>> -        (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
>>> -        ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
>>> +    if (unlikely((SDEBUG_OPT_MEDIUM_ERR & sdebug_opts) &&
>>> +             (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
>>> +             ((lba + num) > OPT_MEDIUM_ERR_ADDR))) {
>>  > [ ... ]
>>> -    if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
>>> +    if (unlikely((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE))) {
>>  > [ ... ]
>>> -    if ((qdepth > 0) && (num_in_q >= qdepth)) {
>>> +    if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) {
>>  > [ ... ]
>>> -    } else if ((sdebug_every_nth != 0) &&
>>> -           (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
>>> -           (scsi_result == 0)) {
>>> +    } else if (unlikely((sdebug_every_nth != 0) &&
>>> +                (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
>>> +                (scsi_result == 0))) {
>>
>> Since you are modifying this code, please remove the superfluous
>> parentheses.
>
> I can find no reference to "superfluous parentheses" in
> Documentation/CodingStyle . As for the improved readability of:
>
>             else if (unlikely(sdebug_every_nth != 0 &&
>                        SDEBUG_OPT_RARE_TSF & sdebug_opts &&
>                        scsi_result == 0)) {
> I have my doubts.

Hello Doug,

With my comment I wanted to refer to the parentheses around comparisons 
only and not to the parentheses around bitwise operations. Leaving out 
these parentheses is the most common style in the Linux kernel. But this 
is a stylistic issue only and hence not that important to me.

Bart.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 08/12] scsi_debug: rework resp_report_luns
  2016-04-25 16:16 ` [PATCH 08/12] scsi_debug: rework resp_report_luns Douglas Gilbert
  2016-04-26  6:26   ` Hannes Reinecke
  2016-04-26  7:33   ` Winkler, Tomas
@ 2016-04-27 23:09   ` Bart Van Assche
  2 siblings, 0 replies; 41+ messages in thread
From: Bart Van Assche @ 2016-04-27 23:09 UTC (permalink / raw)
  To: Douglas Gilbert, linux-scsi; +Cc: martin.petersen, tomas.winkler, emilne

On 04/25/2016 09:16 AM, Douglas Gilbert wrote:
> +	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
> +	arr = kzalloc((tlun_cnt * sizeof(lun_p->scsi_lun)) + 8, GFP_ATOMIC);

kzalloc() allocates contiguous memory. There is no guarantee that a 
large contiguous region will be available. Since kernel memory tends to 
fragment after some time, have you considered to use vmalloc() instead?

> +	/*
> +	 * Address method (we use Peripherial = 00b)
> +	 * 10b - Logical unit
> +	 * 00b - Peripherial device - Use this one
> +	 * 01b - Logical device
> +	 * 11b - reserved
> +	 */

In SAM I found the following spelling "Peripheral" instead of 
"Peripherial" (two occurrences). Although everyone will understand the 
intention of the above comment, using the same spelling as in SAM helps 
people who search through the source code using grep.

Bart.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 00/12] scsi_debug: multiple queue support and cleanup
  2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
                   ` (11 preceding siblings ...)
  2016-04-25 16:16 ` [PATCH 12/12] scsi_debug: use locally assigned naa Douglas Gilbert
@ 2016-04-29 23:53 ` Martin K. Petersen
  2016-04-30  2:06   ` Douglas Gilbert
  12 siblings, 1 reply; 41+ messages in thread
From: Martin K. Petersen @ 2016-04-29 23:53 UTC (permalink / raw)
  To: Douglas Gilbert; +Cc: linux-scsi, martin.petersen, tomas.winkler, emilne

>>>>> "Doug" == Douglas Gilbert <dgilbert@interlog.com> writes:

Doug> Primary reason for this patch series is to add multi queue support
Doug> modelled on the null_blk driver. Ignore host_lock option but keep
Doug> parameter for backward compatibility. Use high resolution timers
Doug> to implement both the jiffy and nanosecond delay
Doug> parameters. Replace the tasklets with work items. Incorporate
Doug> REPORT LUNS patch from Tomas Winkler sent in Febrary 2015. Add
Doug> parameter that permits LU names to use UUIDs (spc5r08.pdf).

I applied 1-7 with minor fixes based on the comments. Sounds like 8 and
9 need a bit of tweaking. 10-12 look fine but don't apply out of order.

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 00/12] scsi_debug: multiple queue support and cleanup
  2016-04-29 23:53 ` [PATCH 00/12] scsi_debug: multiple queue support and cleanup Martin K. Petersen
@ 2016-04-30  2:06   ` Douglas Gilbert
  0 siblings, 0 replies; 41+ messages in thread
From: Douglas Gilbert @ 2016-04-30  2:06 UTC (permalink / raw)
  To: Martin K. Petersen; +Cc: linux-scsi, tomas.winkler, emilne

On 2016-04-29 07:53 PM, Martin K. Petersen wrote:
>>>>>> "Doug" == Douglas Gilbert <dgilbert@interlog.com> writes:
>
> Doug> Primary reason for this patch series is to add multi queue support
> Doug> modelled on the null_blk driver. Ignore host_lock option but keep
> Doug> parameter for backward compatibility. Use high resolution timers
> Doug> to implement both the jiffy and nanosecond delay
> Doug> parameters. Replace the tasklets with work items. Incorporate
> Doug> REPORT LUNS patch from Tomas Winkler sent in Febrary 2015. Add
> Doug> parameter that permits LU names to use UUIDs (spc5r08.pdf).
>
> I applied 1-7 with minor fixes based on the comments. Sounds like 8 and
> 9 need a bit of tweaking. 10-12 look fine but don't apply out of order.

Version 2 of that patchset should appear before this post. I forgot
to note that they had all been acked by Hannes Reinecke apart from
8/12 "rework resp_report_luns". Hopefully his concerns have been
address in v2 (new patch needed for the extras he wanted).

I didn't see any comments on 9/12 "add multiple queue support" but
I get the feeling that something(s) is missing. In testing I see
very little improvement in iops or throughput (well at least it
doesn't degrade things).

Patch 11/12 "uuid for lu name" indicates work is needed in other
areas. For example when the LU name is a UUID, I see no entries
for the that LU in /dev/disk/by-uuid (its partitions yes, but not
the whole LU). Is that a udev issue? Also 'lsscsi -u' needs work,
obviously I can sort that out. My other utilities (i.e. sg_inq,
sg_vpd and sdparm) have been updated but not formally released;
there is a sg3_utils-1.43 beta at:
    http://sg.danny.cz/sg/

Hannes Reinecke has set up a git mirror of my development sg3_utils
(subversion) repository. It is at:
    https://github.com/hreinecke/sg3_utils
and is almost up to date (it was synced yesterday).

Doug Gilbert


^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2016-04-30  2:06 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
2016-04-25 16:16 ` [PATCH 01/12] scsi_debug: cleanup naming and bit crunching Douglas Gilbert
2016-04-26  6:14   ` Hannes Reinecke
2016-04-26 18:13   ` Bart Van Assche
2016-04-26 18:27     ` James Bottomley
2016-04-27  5:25     ` Douglas Gilbert
2016-04-25 16:16 ` [PATCH 02/12] scsi_debug: ignore host lock option Douglas Gilbert
2016-04-26  6:15   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 03/12] scsi_debug: replace jiffy timers with hr timers Douglas Gilbert
2016-04-26  6:17   ` Hannes Reinecke
2016-04-26 18:38   ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 04/12] scsi_debug: make jiffy delay name clearer Douglas Gilbert
2016-04-26  6:17   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 05/12] scsi_debug: replace tasklet with work queue Douglas Gilbert
2016-04-26  6:20   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 06/12] scsi_debug: re-order file scope declarations Douglas Gilbert
2016-04-26  6:21   ` Hannes Reinecke
2016-04-26 20:55   ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 07/12] scsi_debug: use likely hints on fast path Douglas Gilbert
2016-04-26  6:22   ` Hannes Reinecke
2016-04-26 22:14   ` Bart Van Assche
2016-04-27  5:25     ` Douglas Gilbert
2016-04-27  5:33       ` Bart Van Assche
2016-04-27 14:29       ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 08/12] scsi_debug: rework resp_report_luns Douglas Gilbert
2016-04-26  6:26   ` Hannes Reinecke
2016-04-27  4:08     ` Douglas Gilbert
2016-04-27  5:58       ` Hannes Reinecke
2016-04-26  7:33   ` Winkler, Tomas
2016-04-27 23:09   ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 09/12] scsi_debug: add multiple queue support Douglas Gilbert
2016-04-26  6:29   ` Hannes Reinecke
2016-04-26 22:19   ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 10/12] scsi_debug: vpd and mode page work Douglas Gilbert
2016-04-26  6:29   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 11/12] scsi_debug: uuid for lu name Douglas Gilbert
2016-04-26  6:30   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 12/12] scsi_debug: use locally assigned naa Douglas Gilbert
2016-04-26  6:31   ` Hannes Reinecke
2016-04-29 23:53 ` [PATCH 00/12] scsi_debug: multiple queue support and cleanup Martin K. Petersen
2016-04-30  2:06   ` Douglas Gilbert

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.