* [PATCH v2] SG_SCSI_RESET ioctl: add no_escalate values
@ 2013-02-16 19:02 Douglas Gilbert
2013-02-22 21:30 ` Jeremy Linton
0 siblings, 1 reply; 2+ messages in thread
From: Douglas Gilbert @ 2013-02-16 19:02 UTC (permalink / raw)
To: SCSI development list; +Cc: Jeremy Linton, Mike Christie
[-- Attachment #1: Type: text/plain, Size: 1830 bytes --]
Further to the thread titled: "[PATCH] SG_SCSI_RESET ioctl should
only perform requested operation" by Jeremy Linton a patch (v2)
is presented that adds "no_escalate" versions to the existing
ioctl. This requires no changes to SCSI low level drivers (LLDs);
it adds several more finely tuned reset options to the user space.
For example:
/* This call remains the same, with the same escalating semantics
* if the device (LU) reset fail. That is: on failure to try a
* target reset and if that fails, try a bus reset, and if that fails
* try a host (i.e. LLD) reset. */
val = SG_SCSI_RESET_DEVICE;
res = ioctl(sg_or_block_fd, SG_SCSI_RESET, &val);
/* What follows is a new option introduced by this patch. Only a
* device reset is attempted. If that fails then an appropriate
* error code is provided. N.B. There is no reset escalation. */
val = SG_SCSI_RESET_DEVICE + SG_SCSI_RESET_NO_ESCALATE;
res = ioctl(sg_or_block_fd, SG_SCSI_RESET, &val);
This patches applies to lk 3.7.8 and lk 3.8.0-rc7 . I will extend
sg_reset in the sg3_utils package to use it. Note the bsg driver
does not support the SG_SCSI_RESET ioctl and that continues to
be the case.
v2 of this patch modifies the SG_SCSI_RESET ioctl in scsi_ioctl.c
so block device nodes (e.g. /dev/sdb) have this additional
functionality.
ChangeLog:
- modify SG_SCSI_RESET ioctl so the SG_SCSI_RESET_NO_ESCALATE
value may be added to the existing values. If so the existing
device->target->bus->host escalation does not occur. The
SG_SCSI_RESET ioctl is modified in both the sg driver and
scsi_ioctl.c (so block devices can use it).
- modify scsi_reset_provider() in the scsi_error.c file in a
similar way to support this additional functionality.
Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
[-- Attachment #2: scsi_reset_no_escal2.patch --]
[-- Type: text/x-patch, Size: 5786 bytes --]
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index c1b05a8..4ba79c1 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -2013,8 +2013,18 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
break;
/* FALLTHROUGH */
case SCSI_TRY_RESET_HOST:
+ case SCSI_TRY_RESET_HOST + SCSI_TRY_RESET_NO_ESCALATE:
rtn = scsi_try_host_reset(scmd);
break;
+ case SCSI_TRY_RESET_DEVICE + SCSI_TRY_RESET_NO_ESCALATE:
+ rtn = scsi_try_bus_device_reset(scmd);
+ break;
+ case SCSI_TRY_RESET_TARGET + SCSI_TRY_RESET_NO_ESCALATE:
+ rtn = scsi_try_target_reset(scmd);
+ break;
+ case SCSI_TRY_RESET_BUS + SCSI_TRY_RESET_NO_ESCALATE:
+ rtn = scsi_try_bus_reset(scmd);
+ break;
default:
rtn = FAILED;
}
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 06a8790..49d07e9 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -62,11 +62,16 @@ extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
/*
* Reset request from external source
+ * Note: if SCSI_TRY_RESET_DEVICE fails then it will escalate to
+ * SCSI_TRY_RESET_TARGET which if it fails will escalate to
+ * SCSI_TRY_RESET_BUS which if it fails will escalate to SCSI_TRY_RESET_HOST.
+ * To prevent escalation add SCSI_TRY_RESET_NO_ESCALATE.
*/
#define SCSI_TRY_RESET_DEVICE 1
#define SCSI_TRY_RESET_BUS 2
#define SCSI_TRY_RESET_HOST 3
#define SCSI_TRY_RESET_TARGET 4
+#define SCSI_TRY_RESET_NO_ESCALATE 0x100 /* may add to prior defines */
extern int scsi_reset_provider(struct scsi_device *, int);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index be2c9a6..d9226ec 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -810,7 +810,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
{
void __user *p = (void __user *)arg;
int __user *ip = p;
- int result, val, read_only;
+ int result, val, val2, read_only;
Sg_device *sdp;
Sg_fd *sfp;
Sg_request *srp;
@@ -1045,27 +1045,32 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
result = get_user(val, ip);
if (result)
return result;
+ if (val >= SG_SCSI_RESET_NO_ESCALATE) {
+ val -= SG_SCSI_RESET_NO_ESCALATE;
+ val2 = SCSI_TRY_RESET_NO_ESCALATE;
+ } else
+ val2 = 0;
if (SG_SCSI_RESET_NOTHING == val)
return 0;
switch (val) {
case SG_SCSI_RESET_DEVICE:
- val = SCSI_TRY_RESET_DEVICE;
+ val2 += SCSI_TRY_RESET_DEVICE;
break;
case SG_SCSI_RESET_TARGET:
- val = SCSI_TRY_RESET_TARGET;
+ val2 += SCSI_TRY_RESET_TARGET;
break;
case SG_SCSI_RESET_BUS:
- val = SCSI_TRY_RESET_BUS;
+ val2 += SCSI_TRY_RESET_BUS;
break;
case SG_SCSI_RESET_HOST:
- val = SCSI_TRY_RESET_HOST;
+ val2 += SCSI_TRY_RESET_HOST;
break;
default:
return -EINVAL;
}
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
- return (scsi_reset_provider(sdp->device, val) ==
+ return (scsi_reset_provider(sdp->device, val2) ==
SUCCESS) ? 0 : -EIO;
case SCSI_IOCTL_SEND_COMMAND:
if (sdp->detached)
diff --git a/include/scsi/sg.h b/include/scsi/sg.h
index a9f3c6f..8207171 100644
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -204,12 +204,15 @@ typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
/* Returns -EBUSY if occupied. 3rd argument pointer to int (see next) */
#define SG_SCSI_RESET 0x2284
-/* Associated values that can be given to SG_SCSI_RESET follow */
+/* Associated values that can be given to SG_SCSI_RESET follow.
+ * SG_SCSI_RESET_NO_ESCALATE may be added to the _DEVICE, _TARGET, _BUS
+ * or _HOST reset value so only that action is attempted. */
#define SG_SCSI_RESET_NOTHING 0
#define SG_SCSI_RESET_DEVICE 1
#define SG_SCSI_RESET_BUS 2
#define SG_SCSI_RESET_HOST 3
#define SG_SCSI_RESET_TARGET 4
+#define SG_SCSI_RESET_NO_ESCALATE 0x100
/* synchronous SCSI command ioctl, (only in version 3 interface) */
#define SG_IO 0x2285 /* similar effect as write() followed by read() */
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index d9564fb..025982d 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -281,12 +281,13 @@ EXPORT_SYMBOL(scsi_ioctl);
* @sdev: scsi device receiving ioctl
* @cmd: Must be SC_SCSI_RESET
* @arg: pointer to int containing SG_SCSI_RESET_{DEVICE,BUS,HOST}
+ * possibly with SG_SCSI_RESET_NO_ESCALATE added
* @ndelay: file mode O_NDELAY flag
*/
int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
void __user *arg, int ndelay)
{
- int val, result;
+ int val, val2, result;
/* The first set of iocts may be executed even if we're doing
* error processing, as long as the device was opened
@@ -302,27 +303,32 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
result = get_user(val, (int __user *)arg);
if (result)
return result;
+ if (val >= SG_SCSI_RESET_NO_ESCALATE) {
+ val -= SG_SCSI_RESET_NO_ESCALATE;
+ val2 = SCSI_TRY_RESET_NO_ESCALATE;
+ } else
+ val2 = 0;
if (val == SG_SCSI_RESET_NOTHING)
return 0;
switch (val) {
case SG_SCSI_RESET_DEVICE:
- val = SCSI_TRY_RESET_DEVICE;
+ val2 += SCSI_TRY_RESET_DEVICE;
break;
case SG_SCSI_RESET_TARGET:
- val = SCSI_TRY_RESET_TARGET;
+ val2 += SCSI_TRY_RESET_TARGET;
break;
case SG_SCSI_RESET_BUS:
- val = SCSI_TRY_RESET_BUS;
+ val2 += SCSI_TRY_RESET_BUS;
break;
case SG_SCSI_RESET_HOST:
- val = SCSI_TRY_RESET_HOST;
+ val2 += SCSI_TRY_RESET_HOST;
break;
default:
return -EINVAL;
}
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
- return (scsi_reset_provider(sdev, val) ==
+ return (scsi_reset_provider(sdev, val2) ==
SUCCESS) ? 0 : -EIO;
}
return -ENODEV;
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH v2] SG_SCSI_RESET ioctl: add no_escalate values
2013-02-16 19:02 [PATCH v2] SG_SCSI_RESET ioctl: add no_escalate values Douglas Gilbert
@ 2013-02-22 21:30 ` Jeremy Linton
0 siblings, 0 replies; 2+ messages in thread
From: Jeremy Linton @ 2013-02-22 21:30 UTC (permalink / raw)
To: dgilbert@interlog.com; +Cc: SCSI development list, Mike Christie
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Tested-by: Jeremy Linton jlinton@tributary.com
I tested this patch in an environment where the lun and target reset is
"failing" because the target device is misbehaving.
This patch appears to work as advertised.
That said, I changed my testing methodology for this patch (vs the one I
originally posted). The results were "interesting", there are some really
strange things that happen in some of the LLD error paths. Its obvious that
error injection is not part of testing many of them, and what at first glance
should be a fairly straightforward error can create quite a mess. So anyone
sending any kind of reset (especially without the ESCALATE flag which tends to
isolate the error handling) to the LLD's should be aware that behavior between
them can vary significantly.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iQEcBAEBAgAGBQJRJ+NjAAoJEL5i86xrzcy7GI0H/2XKCZvhLmE8WeQtMXlHhVyA
G3Y34fKeEx9ek56Sr6AcipvV9mUBR9uYvydxZfdGjBT83I2bYGRHEfVEx22WKFXr
JShVv43eIl5y/inUr8THNTBfggFcYaBIx21ieLwvR/+cBGWbpiIwi16ktaENX2O7
nHgHVSvFOam9Qy8ewQ2YcULsGFkHQd1SN2LXKSh5bp42eZ998Od4t+agADlNipNz
OShNyJO9fHr4XC/pNMdujjDd+eaOPv5/furYAgkU/aQutxjIs5a0OtDiNi0hzmQ+
ZVfoQWk4Bh4LJdQ2ZiqiKBi54z8YxJu5n2WmbKTzwWcabumOWqebNG8JaYDDYjI=
=2mMo
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-02-22 21:30 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-02-16 19:02 [PATCH v2] SG_SCSI_RESET ioctl: add no_escalate values Douglas Gilbert
2013-02-22 21:30 ` Jeremy Linton
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.