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>
This commit is contained in:
Douglas Gilbert 2014-11-24 20:18:02 -05:00 committed by Christoph Hellwig
parent 22017ed2de
commit 817fd66beb

View File

@ -209,6 +209,14 @@ static const char *scsi_debug_version_date = "20141022";
#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
#endif
struct sdebug_scmd_extra_t {
bool inj_recovered;
bool inj_transport;
bool inj_dif;
bool inj_dix;
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;
@ -248,6 +256,7 @@ 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 sdebug_any_injecting_opt;
static atomic_t sdebug_cmnd_count;
static atomic_t sdebug_completions;
@ -3416,6 +3425,16 @@ 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;
atomic_set(&sdebug_cmnd_count, 0);
atomic_set(&sdebug_a_tsf, 0);
return count;
@ -4563,6 +4582,41 @@ sdebug_change_qtype(struct scsi_device *sdev, int qtype)
return qtype;
}
static int
check_inject(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(scsi_debug_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)
return 1; /* ignore command causing timeout */
else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_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)
ep->inj_recovered = true;
else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
ep->inj_transport = true;
else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
ep->inj_dif = true;
else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
ep->inj_dix = true;
else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
ep->inj_short = true;
}
}
return 0;
}
static struct scsi_host_template sdebug_driver_template = {
.show_info = scsi_debug_show_info,
.write_info = scsi_debug_write_info,
@ -4589,11 +4643,13 @@ 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)
{
int error = 0;
int opts;
struct sdebug_host_info *sdbg_host;
struct Scsi_Host *hpnt;
int host_prot;
@ -4662,6 +4718,18 @@ static int sdebug_driver_probe(struct device * dev)
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;
error = scsi_add_host(hpnt, &sdbg_host->dev);
if (error) {
printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);