Skip to contentSkip to conversation

Transport affected timeouts...

PATCH In review Smart, James 3 participants 5 messages Apr 22, 2004 – May 19, 2004

Subsystems (2)
lore
Share & tools
lore
#0 lore raw
Quoted 7 lines

I know the way solaris does this is to have a global variable that allows you to raise the timeout. If we simply exposed Brian's proposed
parameter in sysfs, so you could change it from user space, would that be sufficient?

Yes.

-- James S

#1 lore raw
Quoted 9 lines · James
Quoted 5 lines

I know the way solaris does this is to have a global variable that allows you to raise the timeout. If we simply exposed Brian's proposed parameter in sysfs, so you could change it from user space, would that be sufficient?

Yes.

I'll respin the patch.

Signature · 3 lines
Brian King
eServer Storage I/O
IBM Linux Technology Center
#2 lore raw

PATCH 1/1 scsi_timeout_mod

The following patch replaces the sd_timeout_mod patch I submitted earlier. I renamed the field to simply "timeout" and exposed in in sysfs.

Signature · 3 lines
Brian King
eServer Storage I/O
IBM Linux Technology Center

This patch allows LLDs to override the default timeout used for scsi devices and exposes it in sysfs. The default timeout value used is too short for many RAID array devices, such as those created by the ipr driver.

---

include/scsi/scsi_device.h renamed from include/scsi/scsi_device.h~scsi_timeout_mod +2 -0
diff -puN include/scsi/scsi_device.h~scsi_timeout_mod include/scsi/scsi_device.h
@@ -111,6 +111,8 @@ struct scsi_device {
 	unsigned int max_device_blocked; /* what device_blocked counts down from  */
 #define SCSI_DEFAULT_DEVICE_BLOCKED	3
 
+	int timeout;
+
 	struct device		sdev_gendev;
 	struct class_device	sdev_classdev;
 
drivers/scsi/scsi_sysfs.c renamed from drivers/scsi/scsi_sysfs.c~scsi_timeout_mod +21 -0
diff -puN drivers/scsi/scsi_sysfs.c~scsi_timeout_mod drivers/scsi/scsi_sysfs.c
@@ -302,6 +302,26 @@ sdev_rd_attr (model, "%.16s\n");
 sdev_rd_attr (rev, "%.4s\n");
 
 static ssize_t
+sdev_show_timeout (struct device *dev, char *buf)
+{
+	struct scsi_device *sdev;
+	sdev = to_scsi_device(dev);
+	return snprintf (buf, 20, "%d\n", sdev->timeout / HZ);
+}
+
+static ssize_t
+sdev_store_timeout (struct device *dev, const char *buf, size_t count)
+{
+	struct scsi_device *sdev;
+	int timeout;
+	sdev = to_scsi_device(dev);
+	sscanf (buf, "%d\n", &timeout);
+	sdev->timeout = timeout * HZ;
+	return count;
+}
+static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout)
+
+static ssize_t
 store_rescan_field (struct device *dev, const char *buf, size_t count) 
 {
 	scsi_rescan_device(dev);
@@ -367,6 +387,7 @@ static struct device_attribute *scsi_sys
 	&dev_attr_rescan,
 	&dev_attr_delete,
 	&dev_attr_state,
+	&dev_attr_timeout,
 	NULL
 };
 
drivers/scsi/sd.c renamed from drivers/scsi/sd.c~scsi_timeout_mod +8 -3
diff -puN drivers/scsi/sd.c~scsi_timeout_mod drivers/scsi/sd.c
@@ -207,9 +207,7 @@ static int sd_init_command(struct scsi_c
 	sector_t block;
 	struct scsi_device *sdp = SCpnt->device;
 
-	timeout = SD_TIMEOUT;
-	if (SCpnt->device->type != TYPE_DISK)
-		timeout = SD_MOD_TIMEOUT;
+	timeout = sdp->timeout;
 
 	/*
 	 * these are already setup, just copy cdb basically
@@ -1382,6 +1380,13 @@ static int sd_probe(struct device *dev)
 	sdkp->index = index;
 	sdkp->openers = 0;
 
+	if (!sdp->timeout) {
+		if (sdp->type == TYPE_DISK)
+			sdp->timeout = SD_TIMEOUT;
+		else
+			sdp->timeout = SD_MOD_TIMEOUT;
+	}
+
 	devno = make_sd_dev(index, 0);
 	gd->major = MAJOR(devno);
 	gd->first_minor = MINOR(devno);

_

#3 lore raw

Re: [PATCH] scsi_timeout_mod

Hi Brian,

I had a chance to use pseudo-I/O system, I tested your patch and it worked fine.
First, I set the value of timeout to 10 seconds.
Then I accessed the device which doesn't respond to the command. 10 seconds later, scsi midlayer detected timeout and issued abort task message.

Since we consider the early change of broken device/path, this patch is very useful.

Thanks,
Masao Fukuchi

Quoted 10 lines · Brian King

The following patch replaces the sd_timeout_mod patch I submitted earlier. I renamed the field to simply "timeout" and exposed in in sysfs.

Signature · 3 lines
Brian King
eServer Storage I/O
IBM Linux Technology Center
#4 lore raw
In reply to Brian King

The following patch makes st use the timeout field in the scsi_device struct. It requires the scsi_timeout_mod patch I just submitted.

Signature · 3 lines
Brian King
eServer Storage I/O
IBM Linux Technology Center

This patch changes st to use the timeout field in the scsi_device struct for the short timeout. This patch depends on scsi_timeout_mod patch.

---

drivers/scsi/st.h renamed from drivers/scsi/st.h~st_timeout_mod +0 -1
diff -puN drivers/scsi/st.h~st_timeout_mod drivers/scsi/st.h
@@ -100,7 +100,6 @@ typedef struct {
 	unsigned char c_algo;			/* compression algorithm */
 	unsigned char pos_unknown;			/* after reset position unknown */
 	int tape_type;
-	int timeout;		/* timeout for normal commands */
 	int long_timeout;	/* timeout for commands known to take long time */
 
 	unsigned long max_pfn;	/* the maximum page number reachable by the HBA */
drivers/scsi/st.c renamed from drivers/scsi/st.c~st_timeout_mod +19 -19
diff -puN drivers/scsi/st.c~st_timeout_mod drivers/scsi/st.c
@@ -486,7 +486,7 @@ static int cross_eof(Scsi_Tape * STp, in
 		   tape_name(STp), forward ? "forward" : "backward"));
 
 	SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE,
-			   STp->timeout, MAX_RETRIES, TRUE);
+			   STp->device->timeout, MAX_RETRIES, TRUE);
 	if (!SRpnt)
 		return (STp->buffer)->syscall_result;
 
@@ -544,7 +544,7 @@ static int flush_write_buffer(Scsi_Tape 
 		cmd[4] = blks;
 
 		SRpnt = st_do_scsi(NULL, STp, cmd, transfer, SCSI_DATA_WRITE,
-				   STp->timeout, MAX_WRITE_RETRIES, TRUE);
+				   STp->device->timeout, MAX_WRITE_RETRIES, TRUE);
 		if (!SRpnt)
 			return (STp->buffer)->syscall_result;
 
@@ -867,7 +867,7 @@ static int check_tape(Scsi_Tape *STp, st
 		memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
 		cmd[0] = READ_BLOCK_LIMITS;
 
-		SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->timeout,
+		SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->device->timeout,
 				   MAX_READY_RETRIES, TRUE);
 		if (!SRpnt) {
 			retval = (STp->buffer)->syscall_result;
@@ -894,7 +894,7 @@ static int check_tape(Scsi_Tape *STp, st
 	cmd[0] = MODE_SENSE;
 	cmd[4] = 12;
 
-	SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->timeout,
+	SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->device->timeout,
 			   MAX_READY_RETRIES, TRUE);
 	if (!SRpnt) {
 		retval = (STp->buffer)->syscall_result;
@@ -1115,7 +1115,7 @@ static int st_flush(struct file *filp)
 		cmd[4] = 1 + STp->two_fm;
 
 		SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE,
-				   STp->timeout, MAX_WRITE_RETRIES, TRUE);
+				   STp->device->timeout, MAX_WRITE_RETRIES, TRUE);
 		if (!SRpnt) {
 			result = (STp->buffer)->syscall_result;
 			goto out;
@@ -1506,7 +1506,7 @@ static ssize_t
 		cmd[4] = blks;
 
 		SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
-				   STp->timeout, MAX_WRITE_RETRIES, !async_write);
+				   STp->device->timeout, MAX_WRITE_RETRIES, !async_write);
 		if (!SRpnt) {
 			retval = STbp->syscall_result;
 			goto out;
@@ -1676,7 +1676,7 @@ static long read_tape(Scsi_Tape *STp, lo
 
 	SRpnt = *aSRpnt;
 	SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, SCSI_DATA_READ,
-			   STp->timeout, MAX_RETRIES, TRUE);
+			   STp->device->timeout, MAX_RETRIES, TRUE);
 	release_buffering(STp);
 	*aSRpnt = SRpnt;
 	if (!SRpnt)
@@ -2075,7 +2075,7 @@ static int st_set_options(Scsi_Tape *STp
 			printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name,
 			       (value & ~MT_ST_SET_LONG_TIMEOUT));
 		} else {
-			STp->timeout = value * HZ;
+			STp->device->timeout = value * HZ;
 			printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n",
                                name, value);
 		}
@@ -2183,7 +2183,7 @@ static int read_mode_page(Scsi_Tape *STp
 	cmd[4] = 255;
 
 	SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ,
-			   STp->timeout, 0, TRUE);
+			   STp->device->timeout, 0, TRUE);
 	if (SRpnt == NULL)
 		return (STp->buffer)->syscall_result;
 
@@ -2214,7 +2214,7 @@ static int write_mode_page(Scsi_Tape *ST
 	(STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR;
 
 	SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE,
-			   (slow ? STp->long_timeout : STp->timeout), 0, TRUE);
+			   (slow ? STp->long_timeout : STp->device->timeout), 0, TRUE);
 	if (SRpnt == NULL)
 		return (STp->buffer)->syscall_result;
 
@@ -2326,7 +2326,7 @@ static int do_load_unload(Scsi_Tape *STp
 	}
 	if (STp->immediate) {
 		cmd[1] = 1;	/* Don't wait for completion */
-		timeout = STp->timeout;
+		timeout = STp->device->timeout;
 	}
 	else
 		timeout = STp->long_timeout;
@@ -2506,7 +2506,7 @@ static int st_int_ioctl(Scsi_Tape *STp, 
 		cmd[2] = (arg >> 16);
 		cmd[3] = (arg >> 8);
 		cmd[4] = arg;
-		timeout = STp->timeout;
+		timeout = STp->device->timeout;
                 DEBC(
                      if (cmd_in == MTWEOF)
                                printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name,
@@ -2524,7 +2524,7 @@ static int st_int_ioctl(Scsi_Tape *STp, 
 		cmd[0] = REZERO_UNIT;
 		if (STp->immediate) {
 			cmd[1] = 1;	/* Don't wait for completion */
-			timeout = STp->timeout;
+			timeout = STp->device->timeout;
 		}
                 DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name));
 		fileno = blkno = at_sm = 0;
@@ -2537,7 +2537,7 @@ static int st_int_ioctl(Scsi_Tape *STp, 
 		cmd[0] = START_STOP;
 		if (STp->immediate) {
 			cmd[1] = 1;	/* Don't wait for completion */
-			timeout = STp->timeout;
+			timeout = STp->device->timeout;
 		}
 		cmd[4] = 3;
                 DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name));
@@ -2570,7 +2570,7 @@ static int st_int_ioctl(Scsi_Tape *STp, 
 		cmd[1] = (arg ? 1 : 0);	/* Long erase with non-zero argument */
 		if (STp->immediate) {
 			cmd[1] |= 2;	/* Don't wait for completion */
-			timeout = STp->timeout;
+			timeout = STp->device->timeout;
 		}
 		else
 			timeout = STp->long_timeout * 8;
@@ -2622,7 +2622,7 @@ static int st_int_ioctl(Scsi_Tape *STp, 
 		(STp->buffer)->b_data[9] = (ltmp >> 16);
 		(STp->buffer)->b_data[10] = (ltmp >> 8);
 		(STp->buffer)->b_data[11] = ltmp;
-		timeout = STp->timeout;
+		timeout = STp->device->timeout;
                 DEBC(
 			if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK)
 				printk(ST_DEB_MSG
@@ -2803,7 +2803,7 @@ static int get_location(Scsi_Tape *STp, 
 		if (!logical && !STp->scsi2_logical)
 			scmd[1] = 1;
 	}
-	SRpnt = st_do_scsi(NULL, STp, scmd, 20, SCSI_DATA_READ, STp->timeout,
+	SRpnt = st_do_scsi(NULL, STp, scmd, 20, SCSI_DATA_READ, STp->device->timeout,
 			   MAX_READY_RETRIES, TRUE);
 	if (!SRpnt)
 		return (STp->buffer)->syscall_result;
@@ -2905,7 +2905,7 @@ static int set_location(Scsi_Tape *STp, 
 	}
 	if (STp->immediate) {
 		scmd[1] |= 1;		/* Don't wait for completion */
-		timeout = STp->timeout;
+		timeout = STp->device->timeout;
 	}
 
 	SRpnt = st_do_scsi(NULL, STp, scmd, 0, SCSI_DATA_NONE,
@@ -3844,7 +3844,7 @@ static int st_probe(struct device *dev)
 	tpnt->partition = 0;
 	tpnt->new_partition = 0;
 	tpnt->nbr_partitions = 0;
-	tpnt->timeout = ST_TIMEOUT;
+	tpnt->device->timeout = ST_TIMEOUT;
 	tpnt->long_timeout = ST_LONG_TIMEOUT;
 	tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma;
 

_