From: Douglas Gilbert <dougg@torque.net>
To: linux-scsi@vger.kernel.org
Cc: kurt@garloff.de
Subject: [PATCH] scsi_debug in 2.5.64
Date: Sun, 09 Mar 2003 23:02:53 +1000 [thread overview]
Message-ID: <3E6B3B7D.6060601@torque.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 911 bytes --]
Here is a second attempt to patch scsi_debug in
2.5.64 . My reference version was out of sync in
my previous posting.
Changelog:
- add recovered error injection (this is a bit
different to the patch proposed by Kurt Garloff)
- fix flakiness in scsi_cmnd::result when errors
are being injected
- fix medium error injection
- make "every_nth" writeable in sysfs
- small re-arrangement of error flags in "opts"
- clean up some of the naming
Updated http://www.torque.net/sg/sdebug25.html
This patch does not include Mike Anderson's sysfs
probe() cleanup.
In 2.5.64 scsi error handling is flaky and sysfs is
especially flaky in 2.5.64-bk3. I'll send some finding
to the list when things stabilize a bit. [For anyone
who is bored, try following the tortured sequence
of scsi commands generated by the block/sd/mid-level
layers in response to a persistent medium error.]
Doug Gilbert
[-- Attachment #2: scsi_debug_2564_168_2.diff --]
[-- Type: text/plain, Size: 12803 bytes --]
--- linux/drivers/scsi/scsi_debug.c 2003-03-09 10:51:44.000000000 +1000
+++ linux/drivers/scsi/scsi_debug.c2564_168 2003-03-09 21:38:24.000000000 +1000
@@ -54,7 +54,7 @@
#include "scsi_debug.h"
-static const char * scsi_debug_version_str = "Version: 1.67 (20021221)";
+static const char * scsi_debug_version_str = "Version: 1.68 (20030309)";
#ifndef SCSI_CMD_READ_16
#define SCSI_CMD_READ_16 0x88
@@ -68,7 +68,7 @@
/* Default values for driver parameters */
#define DEF_NUM_DEVS 1
#define DEF_DEV_SIZE_MB 8
-#define DEF_EVERY_NTH 100
+#define DEF_EVERY_NTH 0
#define DEF_DELAY 1
#define DEF_MAX_LUNS 2
#define DEF_SCSI_LEVEL 3
@@ -80,9 +80,17 @@
/* bit mask values for scsi_debug_opts */
#define SCSI_DEBUG_OPT_NOISE 1
#define SCSI_DEBUG_OPT_MEDIUM_ERR 2
-#define SCSI_DEBUG_OPT_EVERY_NTH 4
+#define SCSI_DEBUG_OPT_TIMEOUT 4
+#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
+/* When "every_nth" > 0 then modulo "every_nth" commands:
+ * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
+ * - a RECOVERED_ERROR is simulated on successful read and write
+ * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ */
-#define OPT_MEDIUM_ERR_ADDR 0x1234
+/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
+ * sector on read commands: */
+#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
static int scsi_debug_num_devs = DEF_NUM_DEVS;
@@ -161,6 +169,9 @@
.devclass = &shost_devclass,
};
+static const int check_condition_result =
+ (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
/* function declarations */
static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
int bufflen, struct sdebug_dev_info * devip);
@@ -222,6 +233,7 @@
unsigned long capac;
struct sdebug_dev_info * devip = NULL;
unsigned char * sbuff;
+ int inj_recovered = 0;
if (done == NULL)
return 0; /* assume mid level reprocessing command */
@@ -255,11 +267,13 @@
return schedule_resp(SCpnt, NULL, done,
DID_NO_CONNECT << 16, 0);
- if ((SCSI_DEBUG_OPT_EVERY_NTH & scsi_debug_opts) &&
- (scsi_debug_every_nth > 0) &&
+ if ((scsi_debug_every_nth > 0) &&
(++scsi_debug_cmnd_count >= scsi_debug_every_nth)) {
scsi_debug_cmnd_count =0;
- return 0; /* ignore command causing timeout */
+ if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
+ return 0; /* ignore command causing timeout */
+ else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
+ inj_recovered = 1; /* to reads and writes below */
}
switch (*cmd) {
@@ -269,8 +283,8 @@
case REQUEST_SENSE: /* mandatory */
/* Since this driver indicates autosense by placing the
* sense buffer in the scsi_cmnd structure in the response
- * (when CHECK_CONDITION is set), the mid level shouldn't
- * need to call REQUEST_SENSE */
+ * (when SAM_STAT_CHECK_CONDITION is set), the mid level
+ * shouldn't need to call REQUEST_SENSE */
if (devip) {
sbuff = devip->sense_buff;
memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ?
@@ -355,6 +369,10 @@
num = cmd[4];
}
errsts = resp_read(SCpnt, upper_blk, block, num, devip);
+ if (inj_recovered && (0 == errsts)) {
+ mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14);
+ errsts = check_condition_result;
+ }
break;
case REPORT_LUNS:
errsts = resp_report_luns(cmd, buff, bufflen, devip);
@@ -388,6 +406,10 @@
num = cmd[4];
}
errsts = resp_write(SCpnt, upper_blk, block, num, devip);
+ if (inj_recovered && (0 == errsts)) {
+ mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14);
+ errsts = check_condition_result;
+ }
break;
case MODE_SENSE:
case MODE_SENSE_10:
@@ -400,7 +422,7 @@
if ((errsts = check_reset(SCpnt, devip)))
break;
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14);
- errsts = (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ errsts = check_condition_result;
break;
}
return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay);
@@ -420,7 +442,7 @@
if (devip->reset) {
devip->reset = 0;
mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14);
- return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ return check_condition_result;
}
return 0;
}
@@ -481,7 +503,7 @@
arr[0] = pq_pdt;
if (0x2 & cmd[1]) { /* CMDDT bit set */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
- return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ return check_condition_result;
} else if (0x1 & cmd[1]) { /* EVPD bit set */
int dev_id_num, len;
char dev_id_str[6];
@@ -506,7 +528,7 @@
} else {
/* Illegal request, invalid field in cdb */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
- return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ return check_condition_result;
}
memcpy(buff, arr, min_len);
return 0;
@@ -619,7 +641,7 @@
memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
if (0x3 == pcontrol) { /* Saving values not supported */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14);
- return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ return check_condition_result;
}
dev_spec = DEV_READONLY(target) ? 0x80 : 0x0;
if (msense_6) {
@@ -662,7 +684,7 @@
break;
default:
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
- return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ return check_condition_result;
}
if (msense_6)
arr[0] = offset - 1;
@@ -686,14 +708,14 @@
if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
- return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ return check_condition_result;
}
if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
- (block >= OPT_MEDIUM_ERR_ADDR) &&
- (block < (OPT_MEDIUM_ERR_ADDR + num))) {
+ (block <= OPT_MEDIUM_ERR_ADDR) &&
+ ((block + num) > OPT_MEDIUM_ERR_ADDR)) {
mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14);
/* claim unrecoverable read error */
- return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ return check_condition_result;
}
read_lock_irqsave(&atomic_rw, iflags);
sgcount = 0;
@@ -735,7 +757,7 @@
if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
- return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ return check_condition_result;
}
write_lock_irqsave(&atomic_rw, iflags);
@@ -776,7 +798,7 @@
alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
if ((alloc_len < 16) || (select_report > 2)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
- return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
+ return check_condition_result;
}
if (bufflen > 3) {
lun_cnt = min((int)(bufflen / sizeof(ScsiLun)),
@@ -810,8 +832,10 @@
return;
}
sqcp->in_use = 0;
- if (sqcp->done_funct)
+ if (sqcp->done_funct) {
+ sqcp->a_cmnd->result = sqcp->scsi_result;
sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */
+ }
sqcp->done_funct = NULL;
spin_unlock_irqrestore(&queued_arr_lock, iflags);
}
@@ -1063,7 +1087,7 @@
}
if (cmnd && devip) {
/* simulate autosense by this driver */
- if (CHECK_CONDITION == status_byte(scsi_result))
+ if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff))
memcpy(cmnd->sense_buffer, devip->sense_buff,
(SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ?
SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE);
@@ -1099,6 +1123,8 @@
sqcp->cmnd_timer.expires = jiffies + delta_jiff;
add_timer(&sqcp->cmnd_timer);
spin_unlock_irqrestore(&queued_arr_lock, iflags);
+ if (cmnd)
+ cmnd->result = 0;
return 0;
}
}
@@ -1163,7 +1189,7 @@
if (1 != sscanf(arr, "%d", &pos))
return -EINVAL;
scsi_debug_opts = pos;
- if (SCSI_DEBUG_OPT_EVERY_NTH & scsi_debug_opts)
+ if (scsi_debug_every_nth > 0)
scsi_debug_cmnd_count = 0;
return length;
}
@@ -1192,12 +1218,12 @@
return len;
}
-static ssize_t sdebug_delay_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf)
{
- return sprintf(buf, "%d\n", scsi_debug_delay);
+ return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
}
-static ssize_t sdebug_delay_write(struct device_driver * ddp,
+static ssize_t sdebug_delay_store(struct device_driver * ddp,
const char * buf, size_t count)
{
int delay;
@@ -1211,15 +1237,15 @@
}
return -EINVAL;
}
-DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_read,
- sdebug_delay_write)
+DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show,
+ sdebug_delay_store)
-static ssize_t sdebug_opts_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf)
{
- return sprintf(buf, "0x%x\n", scsi_debug_opts);
+ return snprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
}
-static ssize_t sdebug_opts_write(struct device_driver * ddp,
+static ssize_t sdebug_opts_store(struct device_driver * ddp,
const char * buf, size_t count)
{
int opts;
@@ -1237,48 +1263,62 @@
return -EINVAL;
opts_done:
scsi_debug_opts = opts;
+ scsi_debug_cmnd_count = 0;
return count;
}
-DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_read,
- sdebug_opts_write)
+DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show,
+ sdebug_opts_store)
-static ssize_t sdebug_num_devs_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_num_devs_show(struct device_driver * ddp, char * buf)
{
- return sprintf(buf, "%d\n", scsi_debug_num_devs);
+ return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_devs);
}
-DRIVER_ATTR(num_devs, S_IRUGO, sdebug_num_devs_read, NULL)
+DRIVER_ATTR(num_devs, S_IRUGO, sdebug_num_devs_show, NULL)
-static ssize_t sdebug_dev_size_mb_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf)
{
- return sprintf(buf, "%d\n", scsi_debug_dev_size_mb);
+ return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
}
-DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_read, NULL)
+DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL)
-static ssize_t sdebug_every_nth_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf)
{
- return sprintf(buf, "%d\n", scsi_debug_every_nth);
+ return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
}
-DRIVER_ATTR(every_nth, S_IRUGO, sdebug_every_nth_read, NULL)
+static ssize_t sdebug_every_nth_store(struct device_driver * ddp,
+ const char * buf, size_t count)
+{
+ int nth;
-static ssize_t sdebug_max_luns_read(struct device_driver * ddp, char * buf)
+ if ((count > 0) && (1 == sscanf(buf, "%d", &nth)) && (nth >= 0)) {
+ scsi_debug_every_nth = nth;
+ scsi_debug_cmnd_count = 0;
+ return count;
+ }
+ return -EINVAL;
+}
+DRIVER_ATTR(every_nth, S_IRUGO | S_IWUSR, sdebug_every_nth_show,
+ sdebug_every_nth_store)
+
+static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf)
{
- return sprintf(buf, "%d\n", scsi_debug_max_luns);
+ return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
}
-DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_read, NULL)
+DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_show, NULL)
-static ssize_t sdebug_scsi_level_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf)
{
- return sprintf(buf, "%d\n", scsi_debug_scsi_level);
+ return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
}
-DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_read, NULL)
+DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL)
-static ssize_t sdebug_add_host_read(struct device_driver * ddp, char * buf)
+static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf)
{
- return sprintf(buf, "%d\n", scsi_debug_add_host);
+ return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
}
-static ssize_t sdebug_add_host_write(struct device_driver * ddp,
- const char * buf, size_t count)
+static ssize_t sdebug_add_host_store(struct device_driver * ddp,
+ const char * buf, size_t count)
{
int delta_hosts, k;
char work[20];
@@ -1322,8 +1362,8 @@
}
return count;
}
-DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_read,
- sdebug_add_host_write)
+DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
+ sdebug_add_host_store)
static void do_create_driverfs_files()
{
reply other threads:[~2003-03-09 13:02 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3E6B3B7D.6060601@torque.net \
--to=dougg@torque.net \
--cc=kurt@garloff.de \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox