diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-16 07:06:26 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-16 07:06:26 +0200 |
commit | 72f02ba66bd83b54054da20eae550123de84da6f (patch) | |
tree | 96a8360400e040aa2e38e7352594dbbc485461db /drivers/scsi/scsi_debug.c | |
parent | Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cl... (diff) | |
parent | scsi: core: use blk_mq_run_hw_queues in scsi_kick_queue (diff) | |
download | linux-72f02ba66bd83b54054da20eae550123de84da6f.tar.xz linux-72f02ba66bd83b54054da20eae550123de84da6f.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This is mostly updates to the usual drivers: mpt3sas, lpfc, qla2xxx,
hisi_sas, smartpqi, megaraid_sas, arcmsr.
In addition, with the continuing absence of Nic we have target updates
for tcmu and target core (all with reviews and acks).
The biggest observable change is going to be that we're (again) trying
to switch to mulitqueue as the default (a user can still override the
setting on the kernel command line).
Other major core stuff is the removal of the remaining Microchannel
drivers, an update of the internal timers and some reworks of
completion and result handling"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (203 commits)
scsi: core: use blk_mq_run_hw_queues in scsi_kick_queue
scsi: ufs: remove unnecessary query(DM) UPIU trace
scsi: qla2xxx: Fix issue reported by static checker for qla2x00_els_dcmd2_sp_done()
scsi: aacraid: Spelling fix in comment
scsi: mpt3sas: Fix calltrace observed while running IO & reset
scsi: aic94xx: fix an error code in aic94xx_init()
scsi: st: remove redundant pointer STbuffer
scsi: qla2xxx: Update driver version to 10.00.00.08-k
scsi: qla2xxx: Migrate NVME N2N handling into state machine
scsi: qla2xxx: Save frame payload size from ICB
scsi: qla2xxx: Fix stalled relogin
scsi: qla2xxx: Fix race between switch cmd completion and timeout
scsi: qla2xxx: Fix Management Server NPort handle reservation logic
scsi: qla2xxx: Flush mailbox commands on chip reset
scsi: qla2xxx: Fix unintended Logout
scsi: qla2xxx: Fix session state stuck in Get Port DB
scsi: qla2xxx: Fix redundant fc_rport registration
scsi: qla2xxx: Silent erroneous message
scsi: qla2xxx: Prevent sysfs access when chip is down
scsi: qla2xxx: Add longer window for chip reset
...
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 364e71861bfd..60bcc6df97a9 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -164,29 +164,29 @@ static const char *sdebug_version_date = "20180128"; #define SDEBUG_OPT_RESET_NOISE 0x2000 #define SDEBUG_OPT_NO_CDB_NOISE 0x4000 #define SDEBUG_OPT_HOST_BUSY 0x8000 +#define SDEBUG_OPT_CMD_ABORT 0x10000 #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 | \ - SDEBUG_OPT_HOST_BUSY) + SDEBUG_OPT_HOST_BUSY | \ + SDEBUG_OPT_CMD_ABORT) /* When "every_nth" > 0 then modulo "every_nth" commands: * - 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. + * - similarly for DIF_ERR, DIX_ERR, SHORT_TRANSFER, HOST_BUSY and + * CMD_ABORT * - * When "every_nth" < 0 then after "- every_nth" commands: - * - 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 _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). + * When "every_nth" < 0 then after "- every_nth" commands the selected + * error will be injected. The error will be injected on every subsequent + * command until some other action occurs; for example, the user writing + * a new value (other than -1 or 1) to every_nth: + * echo 0 > /sys/bus/pseudo/drivers/scsi_debug/every_nth */ /* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs) are returned in @@ -281,6 +281,7 @@ struct sdebug_defer { int issuing_cpu; bool init_hrt; bool init_wq; + bool aborted; /* true when blk_abort_request() already called */ enum sdeb_defer_type defer_t; }; @@ -296,6 +297,7 @@ struct sdebug_queued_cmd { unsigned int inj_dix:1; unsigned int inj_short:1; unsigned int inj_host_busy:1; + unsigned int inj_cmd_abort:1; }; struct sdebug_queue { @@ -3792,6 +3794,7 @@ static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd) /* Queued (deferred) command completions converge here. */ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) { + bool aborted = sd_dp->aborted; int qc_idx; int retiring = 0; unsigned long iflags; @@ -3801,6 +3804,8 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) struct sdebug_dev_info *devip; sd_dp->defer_t = SDEB_DEFER_NONE; + if (unlikely(aborted)) + sd_dp->aborted = false; qc_idx = sd_dp->qc_idx; sqp = sdebug_q_arr + sd_dp->sqa_idx; if (sdebug_statistics) { @@ -3852,6 +3857,11 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp) atomic_set(&retired_max_queue, k + 1); } spin_unlock_irqrestore(&sqp->qc_lock, iflags); + if (unlikely(aborted)) { + if (sdebug_verbose) + pr_info("bypassing scsi_done() due to aborted cmd\n"); + return; + } scp->scsi_done(scp); /* callback to mid level */ } @@ -4312,7 +4322,8 @@ static void setup_inject(struct sdebug_queue *sqp, if (sdebug_every_nth > 0) sqcp->inj_recovered = sqcp->inj_transport = sqcp->inj_dif - = sqcp->inj_dix = sqcp->inj_short = 0; + = sqcp->inj_dix = sqcp->inj_short + = sqcp->inj_host_busy = sqcp->inj_cmd_abort = 0; return; } sqcp->inj_recovered = !!(SDEBUG_OPT_RECOVERED_ERR & sdebug_opts); @@ -4321,6 +4332,7 @@ static void setup_inject(struct sdebug_queue *sqp, sqcp->inj_dix = !!(SDEBUG_OPT_DIX_ERR & sdebug_opts); sqcp->inj_short = !!(SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts); sqcp->inj_host_busy = !!(SDEBUG_OPT_HOST_BUSY & sdebug_opts); + sqcp->inj_cmd_abort = !!(SDEBUG_OPT_CMD_ABORT & sdebug_opts); } /* Complete the processing of the thread that queued a SCSI command to this @@ -4458,7 +4470,14 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, if (sdebug_statistics) sd_dp->issuing_cpu = raw_smp_processor_id(); sd_dp->defer_t = SDEB_DEFER_WQ; + if (unlikely(sqcp->inj_cmd_abort)) + sd_dp->aborted = true; schedule_work(&sd_dp->ew.work); + if (unlikely(sqcp->inj_cmd_abort)) { + sdev_printk(KERN_INFO, sdp, "abort request tag %d\n", + cmnd->request->tag); + blk_abort_request(cmnd->request); + } } if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && (scsi_result == device_qfull_result))) @@ -4844,12 +4863,11 @@ static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, (unsigned long)sdebug_dev_size_mb * 1048576; - fake_storep = vmalloc(sz); + fake_storep = vzalloc(sz); if (NULL == fake_storep) { pr_err("out of memory, 9\n"); return -ENOMEM; } - memset(fake_storep, 0, sz); } sdebug_fake_rw = n; } @@ -5391,13 +5409,12 @@ static int __init scsi_debug_init(void) } if (sdebug_fake_rw == 0) { - fake_storep = vmalloc(sz); + fake_storep = vzalloc(sz); if (NULL == fake_storep) { pr_err("out of memory, 1\n"); ret = -ENOMEM; goto free_q_arr; } - memset(fake_storep, 0, sz); if (sdebug_num_parts > 0) sdebug_build_parts(fake_storep, sz); } @@ -5790,11 +5807,13 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost, fini: if (F_DELAY_OVERR & flags) return schedule_resp(scp, devip, errsts, pfp, 0, 0); - else if ((sdebug_jdelay || sdebug_ndelay) && (flags & F_LONG_DELAY)) { + else if ((flags & F_LONG_DELAY) && (sdebug_jdelay > 0 || + sdebug_ndelay > 10000)) { /* - * If any delay is active, for F_SSU_DELAY want at least 1 - * second and if sdebug_jdelay>0 want a long delay of that - * many seconds; for F_SYNC_DELAY want 1/20 of that. + * Skip long delays if ndelay <= 10 microseconds. Otherwise + * for Start Stop Unit (SSU) want at least 1 second delay and + * if sdebug_jdelay>1 want a long delay of that many seconds. + * For Synchronize Cache want 1/20 of SSU's delay. */ int jdelay = (sdebug_jdelay < 2) ? 1 : sdebug_jdelay; int denom = (flags & F_SYNC_DELAY) ? 20 : 1; |