This patch is motivated by a response in the thread:
Re: [PATCH 0/5]stop normal completion path entering a timeout req
by Jianchao Wang . It generalizes the error injection of
blk_abort_request() to use scsi_debug's "every_nth" mechanism.
Ref with original patch to scsi_debug:
https://lore.kernel.org/lkml/a68ad043-26a1-d3d8-2009-504ba4230...@oracle.com/
Also convert two vmalloc/memset(0) to vzalloc() calls.
Signed-off-by: Douglas Gilbert
---
Changes since original version:
- thanks to changes/fixes suggested by Bart Van Assche, mainly
to avoid calling scsi_done() in worker in the abort case,
this version works
The scsi mid-level call scsi_debug_abort but at the time this driver
has already removed the command context so the abort is ignored.
One small wrinkle:
...
sd 0:0:0:0: scsi_debug: tag=0x4d, cmd 28 00 00 00 27 c0 00 00 10 00
scsi_debug: tag=0xa7, cmd 28 00 00 00 27 d0 00 00 10 00
sd 0:0:0:0: abort request tag 167
scsi_debug:sdebug_q_cmd_complete: bypassing scsi_done() due to aborted cmd
scsi_debug_abort: command not found
scsi_debug: tag=0xa7, cmd 28 00 00 00 27 e0 00 00 10 00
scsi_debug: tag=0xaa, cmd 28 00 00 00 27 f0 00 00 10 00
...
My ddpt utility is sending those READs to /dev/sg0 using
ioctl(SG_IO_v3) and is not informed that the READ on LBA
0x27d0 has failed.
The patch is against MKP's 4.19/scsi-queue branch.
drivers/scsi/scsi_debug.c | 47 ++-
1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 4dda192b8fba..2c816ecb0a92 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_NOISE0x4000
#define SDEBUG_OPT_HOST_BUSY 0x8000
+#define SDEBUG_OPT_CMD_ABORT 0x1
#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