From 01123ef4c3fc9b9ff3062df2e10dee9b139b46b4 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Tue, 5 Aug 2014 12:20:02 +0200 Subject: scsi_debug: scsi_cmnd->cmnd check and casts unnecessary This patch removes a NULL check for the scsi_cmnd::cmnd pointer since many other instances in this driver and elsewhere assume it is valid. Also redundant casts to 'unsigned char *' are removed as the pointer has that type. Signed-off-by: Douglas Gilbert Reviewed-by: Martin K. Petersen Signed-off-by: Christoph Hellwig --- drivers/scsi/scsi_debug.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/scsi/scsi_debug.c') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index d19c0e3c7f4..07d224aa9b4 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -929,7 +929,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target, { unsigned char pq_pdt; unsigned char * arr; - unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char *cmd = scp->cmnd; int alloc_len, n, ret; alloc_len = (cmd[3] << 8) + cmd[4]; @@ -1075,7 +1075,7 @@ static int resp_requests(struct scsi_cmnd * scp, struct sdebug_dev_info * devip) { unsigned char * sbuff; - unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char *cmd = scp->cmnd; unsigned char arr[SCSI_SENSE_BUFFERSIZE]; int want_dsense; int len = 18; @@ -1115,7 +1115,7 @@ static int resp_requests(struct scsi_cmnd * scp, static int resp_start_stop(struct scsi_cmnd * scp, struct sdebug_dev_info * devip) { - unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char *cmd = scp->cmnd; int power_cond, errsts, start; errsts = check_readiness(scp, UAS_ONLY, devip); @@ -1177,7 +1177,7 @@ static int resp_readcap(struct scsi_cmnd * scp, static int resp_readcap16(struct scsi_cmnd * scp, struct sdebug_dev_info * devip) { - unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char *cmd = scp->cmnd; unsigned char arr[SDEBUG_READCAP16_ARR_SZ]; unsigned long long capac; int errsts, k, alloc_len; @@ -1222,7 +1222,7 @@ static int resp_readcap16(struct scsi_cmnd * scp, static int resp_report_tgtpgs(struct scsi_cmnd * scp, struct sdebug_dev_info * devip) { - unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char *cmd = scp->cmnd; unsigned char * arr; int host_no = devip->sdbg_host->shost->host_no; int n, ret, alen, rlen; @@ -1468,7 +1468,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, int k, alloc_len, msense_6, offset, len, errsts, target_dev_id; unsigned char * ap; unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; - unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char *cmd = scp->cmnd; errsts = check_readiness(scp, UAS_ONLY, devip); if (errsts) @@ -1630,7 +1630,7 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, int pf, sp, ps, md_len, bd_len, off, spf, pg_len; int param_len, res, errsts, mpage; unsigned char arr[SDEBUG_MAX_MSELECT_SZ]; - unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char *cmd = scp->cmnd; errsts = check_readiness(scp, UAS_ONLY, devip); if (errsts) @@ -1739,7 +1739,7 @@ static int resp_log_sense(struct scsi_cmnd * scp, { int ppc, sp, pcontrol, pcode, subpcode, alloc_len, errsts, len, n; unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; - unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char *cmd = scp->cmnd; errsts = check_readiness(scp, UAS_ONLY, devip); if (errsts) @@ -2414,7 +2414,7 @@ static int resp_report_luns(struct scsi_cmnd * scp, unsigned int alloc_len; int lun_cnt, i, upper, num, n; u64 wlun, lun; - unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char *cmd = scp->cmnd; int select_report = (int)cmd[2]; struct scsi_lun *one_lun; unsigned char arr[SDEBUG_RLUN_ARR_SZ]; @@ -4085,7 +4085,7 @@ static void sdebug_remove_adapter(void) static int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt) { - unsigned char *cmd = (unsigned char *) SCpnt->cmnd; + unsigned char *cmd = SCpnt->cmnd; int len, k; unsigned int num; unsigned long long lba; @@ -4103,7 +4103,7 @@ scsi_debug_queuecommand(struct scsi_cmnd *SCpnt) scsi_set_resid(SCpnt, 0); if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && - !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts) && cmd) { + !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) { char b[120]; int n; -- cgit v1.2.3-70-g09d2 From cd62b7dae245dd3bb3a21eaadcf01d93ec4fcc7c Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Tue, 5 Aug 2014 12:20:46 +0200 Subject: scsi_debug: give unit attention and other errors precedence over TSF Give existing errors priority over the generation of Task Set Full (TSF) errors. So that max_queue is not exceeded, existing errors may be sent back in the invocation thread. This is done so errors like Unit Attentions are not hidden and lost by either max_queue exceeded or real/injected TSFs. Signed-off-by: Douglas Gilbert Reviewed-by: Martin K. Petersen Signed-off-by: Christoph Hellwig --- drivers/scsi/scsi_debug.c | 67 +++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 34 deletions(-) (limited to 'drivers/scsi/scsi_debug.c') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 07d224aa9b4..693f2fa327e 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -3006,7 +3006,7 @@ 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, tsf, qdepth, inject; + int k, num_in_q, qdepth, inject; struct sdebug_queued_cmd *sqcp = NULL; struct scsi_device *sdp = cmnd->device; @@ -3019,55 +3019,48 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", __func__, scsi_result); - if (delta_jiff == 0) { - /* using same thread to call back mid-layer */ - cmnd->result = scsi_result; - cmnd->scsi_done(cmnd); - return 0; - } + if (delta_jiff == 0) + goto respond_in_thread; - /* deferred response cases */ + /* schedule the response at a later time if resources permit */ spin_lock_irqsave(&queued_arr_lock, iflags); num_in_q = atomic_read(&devip->num_in_q); qdepth = cmnd->device->queue_depth; - k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue); - tsf = 0; inject = 0; - if ((qdepth > 0) && (num_in_q >= qdepth)) - tsf = 1; - else if ((scsi_debug_every_nth != 0) && - (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts)) { + if ((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 ((scsi_debug_every_nth != 0) && + (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) && + (scsi_result == 0)) { if ((num_in_q == (qdepth - 1)) && (atomic_inc_return(&sdebug_a_tsf) >= abs(scsi_debug_every_nth))) { atomic_set(&sdebug_a_tsf, 0); inject = 1; - tsf = 1; + scsi_result = device_qfull_result; } } - /* if (tsf) simulate device reporting SCSI status of TASK SET FULL. - * Might override existing CHECK CONDITION. */ - if (tsf) - scsi_result = device_qfull_result; + k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue); if (k >= scsi_debug_max_queue) { - if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts) - tsf = 1; spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (scsi_result) + goto respond_in_thread; + else if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts) + scsi_result = device_qfull_result; if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) sdev_printk(KERN_INFO, sdp, - "%s: num_in_q=%d, bypass q, %s%s\n", - __func__, num_in_q, - (inject ? " " : ""), - (tsf ? "status: TASK SET FULL" : - "report: host busy")); - if (tsf) { - /* queued_arr full so respond in same thread */ - cmnd->result = scsi_result; - cmnd->scsi_done(cmnd); - /* As scsi_done() is called "inline" must return 0 */ - return 0; - } else + "%s: max_queue=%d exceeded, %s\n", + __func__, scsi_debug_max_queue, + (scsi_result ? "status: TASK SET FULL" : + "report: host busy")); + if (scsi_result) + goto respond_in_thread; + else return SCSI_MLQUEUE_HOST_BUSY; } __set_bit(k, queued_in_use_bm); @@ -3117,12 +3110,18 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, else tasklet_schedule(sqcp->tletp); } - if (tsf && (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)) + if ((SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_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 ? " " : ""), "status: TASK SET FULL"); return 0; + +respond_in_thread: /* call back to mid-layer using invocation thread */ + cmnd->result = scsi_result; + cmnd->scsi_done(cmnd); + return 0; } /* Note: The following macros create attribute files in the -- cgit v1.2.3-70-g09d2 From e46b0344be9b50e8254ddd74e3c5b439d5fca3ce Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Tue, 5 Aug 2014 12:21:53 +0200 Subject: scsi_debug: bump inquiry version to SPC-4, update version descriptors Since a lot of functionality from SPC-4 is supported by this driver (e.g. LBP and PI) then bump the default INQUIRY version from SPC-3 to SPC-4. Also update the INQUIRY version descriptors. Signed-off-by: Douglas Gilbert Reviewed-by: Martin K. Petersen Signed-off-by: Christoph Hellwig --- drivers/scsi/scsi_debug.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/scsi/scsi_debug.c') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 693f2fa327e..1c475e9a46a 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -123,7 +123,7 @@ static const char *scsi_debug_version_date = "20140706"; #define DEF_PHYSBLK_EXP 0 #define DEF_PTYPE 0 #define DEF_REMOVABLE false -#define DEF_SCSI_LEVEL 5 /* INQUIRY, byte2 [5->SPC-3] */ +#define DEF_SCSI_LEVEL 6 /* INQUIRY, byte2 [6->SPC-4] */ #define DEF_SECTOR_SIZE 512 #define DEF_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ #define DEF_UNMAP_ALIGNMENT 0 @@ -1056,15 +1056,15 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target, 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] = 0x77; /* SAM-3 ANSI */ - arr[60] = 0x3; arr[61] = 0x14; /* SPC-3 ANSI */ + 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) { - arr[n++] = 0x3; arr[n++] = 0x3d; /* SBC-2 ANSI */ + arr[n++] = 0x4; arr[n++] = 0xc5; /* SBC-4 rev 36 */ } else if (scsi_debug_ptype == 1) { - arr[n++] = 0x3; arr[n++] = 0x60; /* SSC-2 no version */ + arr[n++] = 0x5; arr[n++] = 0x25; /* SSC-4 rev 3 */ } - arr[n++] = 0xc; arr[n++] = 0xf; /* SAS-1.1 rev 10 */ + arr[n++] = 0x20; arr[n++] = 0xe6; /* SPL-3 rev 7 */ ret = fill_from_dev_buffer(scp, arr, min(alloc_len, SDEBUG_LONG_INQ_SZ)); kfree(arr); @@ -3205,7 +3205,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=5[SPC-3])"); +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(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"); MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)"); -- cgit v1.2.3-70-g09d2 From db525fce95f0ee39102f06f8599ced3f3f3af128 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Sun, 31 Aug 2014 19:09:59 -0400 Subject: scsi_debug: deadlock between completions and surprise module removal A deadlock has been reported when the completion of SCSI commands (simulated by a timer) was surprised by a module removal. This patch removes one half of the offending locks around timer deletions. This fix is applied both to stop_all_queued() which is were the deadlock was discovered and stop_queued_cmnd() which has very similar logic. This patch should be applied both to the lk 3.17 tree and Christoph's drivers-for-3.18 tree. Tested-and-reported-by: Milan Broz Signed-off-by: Douglas Gilbert Signed-off-by: Christoph Hellwig --- drivers/scsi/scsi_debug.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers/scsi/scsi_debug.c') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 1c475e9a46a..2b6d447ad6d 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -2743,6 +2743,13 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) 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 (scsi_debug_ndelay > 0) { if (sqcp->sd_hrtp) hrtimer_cancel( @@ -2755,18 +2762,13 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) if (sqcp->tletp) tasklet_kill(sqcp->tletp); } - __clear_bit(k, queued_in_use_bm); - devip = (struct sdebug_dev_info *) - cmnd->device->hostdata; - if (devip) - atomic_dec(&devip->num_in_q); - sqcp->a_cmnd = NULL; - break; + clear_bit(k, queued_in_use_bm); + return 1; } } } spin_unlock_irqrestore(&queued_arr_lock, iflags); - return (k < qmax) ? 1 : 0; + return 0; } /* Deletes (stops) timers or tasklets of all queued commands */ @@ -2782,6 +2784,13 @@ static void stop_all_queued(void) 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 (scsi_debug_ndelay > 0) { if (sqcp->sd_hrtp) hrtimer_cancel( @@ -2794,12 +2803,8 @@ static void stop_all_queued(void) if (sqcp->tletp) tasklet_kill(sqcp->tletp); } - __clear_bit(k, queued_in_use_bm); - devip = (struct sdebug_dev_info *) - sqcp->a_cmnd->device->hostdata; - if (devip) - atomic_dec(&devip->num_in_q); - sqcp->a_cmnd = NULL; + clear_bit(k, queued_in_use_bm); + spin_lock_irqsave(&queued_arr_lock, iflags); } } } -- cgit v1.2.3-70-g09d2 From 48a968763dba039972623caea2355fc573b559ba Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 13 Oct 2014 15:54:44 -0700 Subject: scsi: replace strnicmp with strncasecmp The kernel used to contain two functions for length-delimited, case-insensitive string comparison, strnicmp with correct semantics and a slightly buggy strncasecmp. The latter is the POSIX name, so strnicmp was renamed to strncasecmp, and strnicmp made into a wrapper for the new strncasecmp to avoid breaking existing users. To allow the compat wrapper strnicmp to be removed at some point in the future, and to avoid the extra indirection cost, do s/strnicmp/strncasecmp/g. Signed-off-by: Rasmus Villemoes Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/ips.c | 2 +- drivers/scsi/scsi_debug.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/scsi_debug.c') diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 52a216f21ae..e5afc3884d7 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -528,7 +528,7 @@ ips_setup(char *ips_str) * Update the variables */ for (i = 0; i < ARRAY_SIZE(options); i++) { - if (strnicmp + if (strncasecmp (key, options[i].option_name, strlen(options[i].option_name)) == 0) { if (value) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 2b6d447ad6d..238e06f13b8 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -3371,7 +3371,7 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf, char work[20]; if (1 == sscanf(buf, "%10s", work)) { - if (0 == strnicmp(work,"0x", 2)) { + if (0 == strncasecmp(work,"0x", 2)) { if (1 == sscanf(&work[2], "%x", &opts)) goto opts_done; } else { -- cgit v1.2.3-70-g09d2