public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] scsi_debug in 2.5.64
@ 2003-03-09 13:02 Douglas Gilbert
  0 siblings, 0 replies; only message in thread
From: Douglas Gilbert @ 2003-03-09 13:02 UTC (permalink / raw)
  To: linux-scsi; +Cc: kurt

[-- 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()
 {

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-03-09 13:02 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-03-09 13:02 [PATCH] scsi_debug in 2.5.64 Douglas Gilbert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox