public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] add SCSI reset ioctls to scsi_ioctl.c (and sd and sr)
@ 2004-09-18 16:57 James Bottomley
  2004-09-18 19:49 ` Kai Makisara
  2004-09-20  5:48 ` Douglas Gilbert
  0 siblings, 2 replies; 6+ messages in thread
From: James Bottomley @ 2004-09-18 16:57 UTC (permalink / raw)
  To: SCSI Mailing List; +Cc: Jens Axboe, Kai Makisara

The purpose of this patch is to allow a SCSI reset to be issued directly
to the devices without having to go via sg.  Because the reset may be
issued even while the device is in recovery, this had to be done via a
new api (sd won't invoke scsi_ioctl() while the device is in recovery).

Kai, do you want me to plum this into st as well?

James

===== drivers/scsi/scsi_ioctl.c 1.30 vs edited =====
--- 1.30/drivers/scsi/scsi_ioctl.c	2004-08-25 11:21:41 -05:00
+++ edited/drivers/scsi/scsi_ioctl.c	2004-09-18 11:35:17 -05:00
@@ -20,6 +20,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_request.h>
+#include <scsi/sg.h>
 
 #include "scsi_logging.h"
 
@@ -456,3 +457,51 @@
 	}
 	return -EINVAL;
 }
+
+/*
+ * the scsi_nonblock_ioctl() function is designed for ioctls which may
+ * be executed even if the device is in recovery.
+ */
+int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
+			    void __user *arg, struct file *filp)
+{
+	int val, result;
+
+	/* The first set of iocts may be executed even if we're doing
+	 * error processing, as long as the device was opened
+	 * non-blocking */
+	if (filp && filp->f_flags & O_NONBLOCK) {
+		if (test_bit(SHOST_RECOVERY,
+			     &sdev->host->shost_state))
+			return -ENODEV;
+	} else if (!scsi_block_when_processing_errors(sdev))
+		return -ENODEV;
+
+	switch (cmd) {
+	case SG_SCSI_RESET:
+		result = get_user(val, (int __user *)arg);
+		if (result)
+			return result;
+		if (val == SG_SCSI_RESET_NOTHING)
+			return 0;
+		switch (val) {
+		case SG_SCSI_RESET_DEVICE:
+			val = SCSI_TRY_RESET_DEVICE;
+			break;
+		case SG_SCSI_RESET_BUS:
+			val = SCSI_TRY_RESET_BUS;
+			break;
+		case SG_SCSI_RESET_HOST:
+			val = 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) ==
+			SUCCESS) ? 0 : -EIO;
+	}
+	return -ENODEV;
+}
+EXPORT_SYMBOL(scsi_nonblockable_ioctl);
===== drivers/scsi/sd.c 1.159 vs edited =====
--- 1.159/drivers/scsi/sd.c	2004-09-01 12:35:48 -05:00
+++ edited/drivers/scsi/sd.c	2004-09-18 11:37:41 -05:00
@@ -575,7 +575,7 @@
 	 * access to the device is prohibited.
 	 */
 	if (!scsi_block_when_processing_errors(sdp))
-		return -ENODEV;
+		return scsi_nonblockable_ioctl(sdp, cmd, p, filp);
 
 	if (cmd == HDIO_GETGEO) {
 		if (!arg)
===== drivers/scsi/sr_ioctl.c 1.36 vs edited =====
--- 1.36/drivers/scsi/sr_ioctl.c	2004-08-18 21:45:43 -05:00
+++ edited/drivers/scsi/sr_ioctl.c	2004-09-18 11:34:40 -05:00
@@ -549,5 +549,17 @@
 		 unsigned int cmd, unsigned long arg)
 {
 	Scsi_CD *cd = cdi->handle;
+	int ret;
+	
+	ret = scsi_nonblockable_ioctl(cd->device, cmd,
+				      (void __user *)arg, NULL);
+	/*
+	 * ENODEV means that we didn't recognise the ioctl, or that we
+	 * cannot execute it in the current device state.  In either
+	 * case fall through to scsi_ioctl, which will return ENDOEV again
+	 * if it doesn't recognise the ioctl
+	 */
+	if (ret != -ENODEV)
+		return ret;
 	return scsi_ioctl(cd->device, cmd, (void __user *)arg);
 }
===== include/scsi/scsi_ioctl.h 1.4 vs edited =====
--- 1.4/include/scsi/scsi_ioctl.h	2004-06-18 09:38:19 -05:00
+++ edited/include/scsi/scsi_ioctl.h	2004-09-18 11:31:04 -05:00
@@ -43,6 +43,8 @@
 extern int scsi_ioctl(struct scsi_device *, int, void __user *);
 extern int scsi_ioctl_send_command(struct scsi_device *,
 				   struct scsi_ioctl_command __user *);
+extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
+				   void __user *arg, struct file *filp);
 
 #endif /* __KERNEL__ */
 #endif /* _SCSI_IOCTL_H */


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] add SCSI reset ioctls to scsi_ioctl.c (and sd and sr)
  2004-09-18 16:57 [PATCH] add SCSI reset ioctls to scsi_ioctl.c (and sd and sr) James Bottomley
@ 2004-09-18 19:49 ` Kai Makisara
  2004-09-19  2:39   ` James Bottomley
  2004-09-20  5:48 ` Douglas Gilbert
  1 sibling, 1 reply; 6+ messages in thread
From: Kai Makisara @ 2004-09-18 19:49 UTC (permalink / raw)
  To: James Bottomley; +Cc: SCSI Mailing List, Jens Axboe

On Sat, 18 Sep 2004, James Bottomley wrote:

> The purpose of this patch is to allow a SCSI reset to be issued directly
> to the devices without having to go via sg.  Because the reset may be
> issued even while the device is in recovery, this had to be done via a
> new api (sd won't invoke scsi_ioctl() while the device is in recovery).
> 
> Kai, do you want me to plum this into st as well?
> 
Yes, please do that. I would like st to have the same generic capabilities 
as the other high-level drivers as far as possible and I don't see any 
problems in adding this feature. It is useful to have an easy way to reset 
a tape drive. Some drives seem to be lock up easily when they see a bad tape.

-- 
Kai

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] add SCSI reset ioctls to scsi_ioctl.c (and sd and sr)
  2004-09-18 19:49 ` Kai Makisara
@ 2004-09-19  2:39   ` James Bottomley
  0 siblings, 0 replies; 6+ messages in thread
From: James Bottomley @ 2004-09-19  2:39 UTC (permalink / raw)
  To: Kai Makisara; +Cc: SCSI Mailing List, Jens Axboe

On Sat, 2004-09-18 at 15:49, Kai Makisara wrote:
> Yes, please do that. I would like st to have the same generic capabilities 
> as the other high-level drivers as far as possible and I don't see any 
> problems in adding this feature. It is useful to have an easy way to reset 
> a tape drive. Some drives seem to be lock up easily when they see a bad tape.

OK, I added st.  The attached actually works (I even tested it) for sd.

James

===== drivers/scsi/scsi_ioctl.c 1.30 vs edited =====
--- 1.30/drivers/scsi/scsi_ioctl.c	2004-08-25 11:21:41 -05:00
+++ edited/drivers/scsi/scsi_ioctl.c	2004-09-18 21:31:05 -05:00
@@ -20,6 +20,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_request.h>
+#include <scsi/sg.h>
 
 #include "scsi_logging.h"
 
@@ -456,3 +457,51 @@
 	}
 	return -EINVAL;
 }
+
+/*
+ * the scsi_nonblock_ioctl() function is designed for ioctls which may
+ * be executed even if the device is in recovery.
+ */
+int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
+			    void __user *arg, struct file *filp)
+{
+	int val, result;
+
+	/* The first set of iocts may be executed even if we're doing
+	 * error processing, as long as the device was opened
+	 * non-blocking */
+	if (filp && filp->f_flags & O_NONBLOCK) {
+		if (test_bit(SHOST_RECOVERY,
+			     &sdev->host->shost_state))
+			return -ENODEV;
+	} else if (!scsi_block_when_processing_errors(sdev))
+		return -ENODEV;
+
+	switch (cmd) {
+	case SG_SCSI_RESET:
+		result = get_user(val, (int __user *)arg);
+		if (result)
+			return result;
+		if (val == SG_SCSI_RESET_NOTHING)
+			return 0;
+		switch (val) {
+		case SG_SCSI_RESET_DEVICE:
+			val = SCSI_TRY_RESET_DEVICE;
+			break;
+		case SG_SCSI_RESET_BUS:
+			val = SCSI_TRY_RESET_BUS;
+			break;
+		case SG_SCSI_RESET_HOST:
+			val = 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) ==
+			SUCCESS) ? 0 : -EIO;
+	}
+	return -ENODEV;
+}
+EXPORT_SYMBOL(scsi_nonblockable_ioctl);
===== drivers/scsi/sd.c 1.159 vs edited =====
--- 1.159/drivers/scsi/sd.c	2004-09-01 12:35:48 -05:00
+++ edited/drivers/scsi/sd.c	2004-09-18 16:23:46 -05:00
@@ -574,8 +574,9 @@
 	 * may try and take the device offline, in which case all further
 	 * access to the device is prohibited.
 	 */
-	if (!scsi_block_when_processing_errors(sdp))
-		return -ENODEV;
+	error = scsi_nonblockable_ioctl(sdp, cmd, p, filp);
+	if (!scsi_block_when_processing_errors(sdp) || !error)
+		return error;
 
 	if (cmd == HDIO_GETGEO) {
 		if (!arg)
===== drivers/scsi/sr_ioctl.c 1.36 vs edited =====
--- 1.36/drivers/scsi/sr_ioctl.c	2004-08-18 21:45:43 -05:00
+++ edited/drivers/scsi/sr_ioctl.c	2004-09-18 11:34:40 -05:00
@@ -549,5 +549,17 @@
 		 unsigned int cmd, unsigned long arg)
 {
 	Scsi_CD *cd = cdi->handle;
+	int ret;
+	
+	ret = scsi_nonblockable_ioctl(cd->device, cmd,
+				      (void __user *)arg, NULL);
+	/*
+	 * ENODEV means that we didn't recognise the ioctl, or that we
+	 * cannot execute it in the current device state.  In either
+	 * case fall through to scsi_ioctl, which will return ENDOEV again
+	 * if it doesn't recognise the ioctl
+	 */
+	if (ret != -ENODEV)
+		return ret;
 	return scsi_ioctl(cd->device, cmd, (void __user *)arg);
 }
===== drivers/scsi/st.c 1.94 vs edited =====
--- 1.94/drivers/scsi/st.c	2004-09-14 14:30:18 -05:00
+++ edited/drivers/scsi/st.c	2004-09-18 16:29:29 -05:00
@@ -3128,10 +3128,10 @@
 	 * may try and take the device offline, in which case all further
 	 * access to the device is prohibited.
 	 */
-	if (!scsi_block_when_processing_errors(STp->device)) {
-		retval = (-ENXIO);
+	retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p, file);
+	if (!scsi_block_when_processing_errors(STp->device) || !retval)
 		goto out;
-	}
+
 	cmd_type = _IOC_TYPE(cmd_in);
 	cmd_nr = _IOC_NR(cmd_in);
 
===== include/scsi/scsi_ioctl.h 1.4 vs edited =====
--- 1.4/include/scsi/scsi_ioctl.h	2004-06-18 09:38:19 -05:00
+++ edited/include/scsi/scsi_ioctl.h	2004-09-18 11:31:04 -05:00
@@ -43,6 +43,8 @@
 extern int scsi_ioctl(struct scsi_device *, int, void __user *);
 extern int scsi_ioctl_send_command(struct scsi_device *,
 				   struct scsi_ioctl_command __user *);
+extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
+				   void __user *arg, struct file *filp);
 
 #endif /* __KERNEL__ */
 #endif /* _SCSI_IOCTL_H */


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] add SCSI reset ioctls to scsi_ioctl.c (and sd and sr)
  2004-09-18 16:57 [PATCH] add SCSI reset ioctls to scsi_ioctl.c (and sd and sr) James Bottomley
  2004-09-18 19:49 ` Kai Makisara
@ 2004-09-20  5:48 ` Douglas Gilbert
  2004-09-20 13:49   ` James Bottomley
  2004-09-20 14:53   ` Luben Tuikov
  1 sibling, 2 replies; 6+ messages in thread
From: Douglas Gilbert @ 2004-09-20  5:48 UTC (permalink / raw)
  To: James Bottomley; +Cc: SCSI Mailing List

James Bottomley wrote:
> The purpose of this patch is to allow a SCSI reset to be issued directly
> to the devices without having to go via sg.  Because the reset may be
> issued even while the device is in recovery, this had to be done via a
> new api (sd won't invoke scsi_ioctl() while the device is in recovery).

James,
Perhaps there should be a new reset called:
     ...RESET_LOGICAL_UNIT

as this is now defined as a task management function in SAM-3.
If so ...RESET_DEVICE might get a synonym: ...RESET_TARGET.
Most transports support a RESET_TARGET while RESET_BUS is
SPI specific (is there an FCP equivalent?).

Doug Gilbert

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] add SCSI reset ioctls to scsi_ioctl.c (and sd and sr)
  2004-09-20  5:48 ` Douglas Gilbert
@ 2004-09-20 13:49   ` James Bottomley
  2004-09-20 14:53   ` Luben Tuikov
  1 sibling, 0 replies; 6+ messages in thread
From: James Bottomley @ 2004-09-20 13:49 UTC (permalink / raw)
  To: Douglas Gilbert; +Cc: SCSI Mailing List

On Mon, 2004-09-20 at 01:48, Douglas Gilbert wrote:
> Perhaps there should be a new reset called:
>      ...RESET_LOGICAL_UNIT
> 
> as this is now defined as a task management function in SAM-3.
> If so ...RESET_DEVICE might get a synonym: ...RESET_TARGET.
> Most transports support a RESET_TARGET while RESET_BUS is
> SPI specific (is there an FCP equivalent?).

Well, perhaps ... also one that takes an actual value for the reset type
instead of a pointer to a value that requires compat processing. 
However, the goal of this exercise was simply to provide backwards
compatibility.

Probably, longer term, the reset ioctls should be provided by the
transport class, since they're pretty much transport specific.

James



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] add SCSI reset ioctls to scsi_ioctl.c (and sd and sr)
  2004-09-20  5:48 ` Douglas Gilbert
  2004-09-20 13:49   ` James Bottomley
@ 2004-09-20 14:53   ` Luben Tuikov
  1 sibling, 0 replies; 6+ messages in thread
From: Luben Tuikov @ 2004-09-20 14:53 UTC (permalink / raw)
  To: dougg; +Cc: James Bottomley, SCSI Mailing List

> Perhaps there should be a new reset called:
>      ...RESET_LOGICAL_UNIT
> 
> as this is now defined as a task management function in SAM-3.
> If so ...RESET_DEVICE might get a synonym: ...RESET_TARGET.
> Most transports support a RESET_TARGET while RESET_BUS is
> SPI specific (is there an FCP equivalent?).

Very good idea.  Most likely TMF LU Reset should be
directly addressable to the LLDD, either via a separate
LLDD stub or through a common LLDD::int do_tmf(int tmf, void *data)
stub, so that the LLDD knows LU Reset is wanted.

The point is that the LLDD (and the target on the other end)
would know best how to do this (and other) TMFs. (More so
for newer protocols/transports.)

As to FCP, why not just do I_T Nexus loss or Transport
Reset (best). Ref. SAM3r13, sec 6 and FCP3r3c (4.9, 4.11, 4.12).
And possibly have the SCSI events into SCSI Core, for
all types of transports.

So, recovery would resolve to issuing a TMF (or two)
and if this doesn't work _and_ we haven't gotten a SCSI event,
we can _force_ an event,  else we just act on the
event gotten.

	Luben

P.S. We have to allow LLDDs, to mask out
"forcing" of those events, as the recovery thread
in SCSI Core shouldn't be so "trigger happy".




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-09-20 14:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-18 16:57 [PATCH] add SCSI reset ioctls to scsi_ioctl.c (and sd and sr) James Bottomley
2004-09-18 19:49 ` Kai Makisara
2004-09-19  2:39   ` James Bottomley
2004-09-20  5:48 ` Douglas Gilbert
2004-09-20 13:49   ` James Bottomley
2004-09-20 14:53   ` Luben Tuikov

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