Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 817fd66b authored by Douglas Gilbert's avatar Douglas Gilbert Committed by Christoph Hellwig
Browse files

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: default avatarDouglas Gilbert <dgilbert@interlog.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 22017ed2
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -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__);