diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2014-11-24 20:18:02 -0500 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-11-25 09:42:56 -0500 |
commit | 817fd66beb779dbbe44c46dd11e64d8275efb593 (patch) | |
tree | e57cf120d2634f2c55ef42b039ae892aa5209b9e /drivers/scsi/scsi_debug.c | |
parent | 22017ed2de64b8f7a2ec0abe59dd6ca92f693391 (diff) |
scsi_debug: append inject error flags onto scsi_cmnd object
The way the existing scsi_debug command parser associated various
inject error flags to a command was difficult to replicate in the
table driven parser. This patch adds infrastructure to append those
flags to the end of a scsi_cmnd object with the cmd_size host
template option.
Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index a1bca60ae83d..d337eaa128d0 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -209,6 +209,14 @@ static const char *scsi_debug_version_date = "20141022"; | |||
209 | #warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE" | 209 | #warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE" |
210 | #endif | 210 | #endif |
211 | 211 | ||
212 | struct sdebug_scmd_extra_t { | ||
213 | bool inj_recovered; | ||
214 | bool inj_transport; | ||
215 | bool inj_dif; | ||
216 | bool inj_dix; | ||
217 | bool inj_short; | ||
218 | }; | ||
219 | |||
212 | static int scsi_debug_add_host = DEF_NUM_HOST; | 220 | static int scsi_debug_add_host = DEF_NUM_HOST; |
213 | static int scsi_debug_ato = DEF_ATO; | 221 | static int scsi_debug_ato = DEF_ATO; |
214 | static int scsi_debug_delay = DEF_DELAY; | 222 | static int scsi_debug_delay = DEF_DELAY; |
@@ -248,6 +256,7 @@ static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH; | |||
248 | static bool scsi_debug_removable = DEF_REMOVABLE; | 256 | static bool scsi_debug_removable = DEF_REMOVABLE; |
249 | static bool scsi_debug_clustering; | 257 | static bool scsi_debug_clustering; |
250 | static bool scsi_debug_host_lock = DEF_HOST_LOCK; | 258 | static bool scsi_debug_host_lock = DEF_HOST_LOCK; |
259 | static bool sdebug_any_injecting_opt; | ||
251 | 260 | ||
252 | static atomic_t sdebug_cmnd_count; | 261 | static atomic_t sdebug_cmnd_count; |
253 | static atomic_t sdebug_completions; | 262 | static atomic_t sdebug_completions; |
@@ -3416,6 +3425,16 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf, | |||
3416 | return -EINVAL; | 3425 | return -EINVAL; |
3417 | opts_done: | 3426 | opts_done: |
3418 | scsi_debug_opts = opts; | 3427 | scsi_debug_opts = opts; |
3428 | if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts) | ||
3429 | sdebug_any_injecting_opt = true; | ||
3430 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts) | ||
3431 | sdebug_any_injecting_opt = true; | ||
3432 | else if (SCSI_DEBUG_OPT_DIF_ERR & opts) | ||
3433 | sdebug_any_injecting_opt = true; | ||
3434 | else if (SCSI_DEBUG_OPT_DIX_ERR & opts) | ||
3435 | sdebug_any_injecting_opt = true; | ||
3436 | else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts) | ||
3437 | sdebug_any_injecting_opt = true; | ||
3419 | atomic_set(&sdebug_cmnd_count, 0); | 3438 | atomic_set(&sdebug_cmnd_count, 0); |
3420 | atomic_set(&sdebug_a_tsf, 0); | 3439 | atomic_set(&sdebug_a_tsf, 0); |
3421 | return count; | 3440 | return count; |
@@ -4563,6 +4582,41 @@ sdebug_change_qtype(struct scsi_device *sdev, int qtype) | |||
4563 | return qtype; | 4582 | return qtype; |
4564 | } | 4583 | } |
4565 | 4584 | ||
4585 | static int | ||
4586 | check_inject(struct scsi_cmnd *scp) | ||
4587 | { | ||
4588 | struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp); | ||
4589 | |||
4590 | memset(ep, 0, sizeof(struct sdebug_scmd_extra_t)); | ||
4591 | |||
4592 | if (atomic_inc_return(&sdebug_cmnd_count) >= | ||
4593 | abs(scsi_debug_every_nth)) { | ||
4594 | atomic_set(&sdebug_cmnd_count, 0); | ||
4595 | if (scsi_debug_every_nth < -1) | ||
4596 | scsi_debug_every_nth = -1; | ||
4597 | if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) | ||
4598 | return 1; /* ignore command causing timeout */ | ||
4599 | else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts && | ||
4600 | scsi_medium_access_command(scp)) | ||
4601 | return 1; /* time out reads and writes */ | ||
4602 | if (sdebug_any_injecting_opt) { | ||
4603 | int opts = scsi_debug_opts; | ||
4604 | |||
4605 | if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts) | ||
4606 | ep->inj_recovered = true; | ||
4607 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts) | ||
4608 | ep->inj_transport = true; | ||
4609 | else if (SCSI_DEBUG_OPT_DIF_ERR & opts) | ||
4610 | ep->inj_dif = true; | ||
4611 | else if (SCSI_DEBUG_OPT_DIX_ERR & opts) | ||
4612 | ep->inj_dix = true; | ||
4613 | else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts) | ||
4614 | ep->inj_short = true; | ||
4615 | } | ||
4616 | } | ||
4617 | return 0; | ||
4618 | } | ||
4619 | |||
4566 | static struct scsi_host_template sdebug_driver_template = { | 4620 | static struct scsi_host_template sdebug_driver_template = { |
4567 | .show_info = scsi_debug_show_info, | 4621 | .show_info = scsi_debug_show_info, |
4568 | .write_info = scsi_debug_write_info, | 4622 | .write_info = scsi_debug_write_info, |
@@ -4589,11 +4643,13 @@ static struct scsi_host_template sdebug_driver_template = { | |||
4589 | .use_clustering = DISABLE_CLUSTERING, | 4643 | .use_clustering = DISABLE_CLUSTERING, |
4590 | .module = THIS_MODULE, | 4644 | .module = THIS_MODULE, |
4591 | .track_queue_depth = 1, | 4645 | .track_queue_depth = 1, |
4646 | .cmd_size = sizeof(struct sdebug_scmd_extra_t), | ||
4592 | }; | 4647 | }; |
4593 | 4648 | ||
4594 | static int sdebug_driver_probe(struct device * dev) | 4649 | static int sdebug_driver_probe(struct device * dev) |
4595 | { | 4650 | { |
4596 | int error = 0; | 4651 | int error = 0; |
4652 | int opts; | ||
4597 | struct sdebug_host_info *sdbg_host; | 4653 | struct sdebug_host_info *sdbg_host; |
4598 | struct Scsi_Host *hpnt; | 4654 | struct Scsi_Host *hpnt; |
4599 | int host_prot; | 4655 | int host_prot; |
@@ -4662,6 +4718,18 @@ static int sdebug_driver_probe(struct device * dev) | |||
4662 | else | 4718 | else |
4663 | scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC); | 4719 | scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC); |
4664 | 4720 | ||
4721 | opts = scsi_debug_opts; | ||
4722 | if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts) | ||
4723 | sdebug_any_injecting_opt = true; | ||
4724 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts) | ||
4725 | sdebug_any_injecting_opt = true; | ||
4726 | else if (SCSI_DEBUG_OPT_DIF_ERR & opts) | ||
4727 | sdebug_any_injecting_opt = true; | ||
4728 | else if (SCSI_DEBUG_OPT_DIX_ERR & opts) | ||
4729 | sdebug_any_injecting_opt = true; | ||
4730 | else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts) | ||
4731 | sdebug_any_injecting_opt = true; | ||
4732 | |||
4665 | error = scsi_add_host(hpnt, &sdbg_host->dev); | 4733 | error = scsi_add_host(hpnt, &sdbg_host->dev); |
4666 | if (error) { | 4734 | if (error) { |
4667 | printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); | 4735 | printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); |