* [PATCH 1/5] SCSI scanning and removal fixes
@ 2005-07-26 14:12 Alan Stern
2005-09-07 15:16 ` James Bottomley
0 siblings, 1 reply; 30+ messages in thread
From: Alan Stern @ 2005-07-26 14:12 UTC (permalink / raw)
To: James Bottomley; +Cc: SCSI development list
James:
This patch (as542) fixes a few loose ends left by Mike's patches. It adds
a declaration for the new scsi_host_set_state routine, adds an allowed
transition from the SHOST_RECOVERY state to the SHOST_CANCEL state, and
avoids returning an uninitialized value in __scsi_add_device.
Alan Stern
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Index: 2613/include/scsi/scsi_host.h
===================================================================
--- 2613.orig/include/scsi/scsi_host.h
+++ 2613/include/scsi/scsi_host.h
@@ -636,6 +636,7 @@ extern void scsi_remove_host(struct Scsi
extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
extern void scsi_host_put(struct Scsi_Host *t);
extern struct Scsi_Host *scsi_host_lookup(unsigned short);
+extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
extern const char *scsi_host_state_name(enum scsi_host_state);
extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
Index: 2613/drivers/scsi/hosts.c
===================================================================
--- 2613.orig/drivers/scsi/hosts.c
+++ 2613/drivers/scsi/hosts.c
@@ -97,6 +97,7 @@ int scsi_host_set_state(struct Scsi_Host
switch (oldstate) {
case SHOST_CREATED:
case SHOST_RUNNING:
+ case SHOST_RECOVERY:
break;
default:
goto illegal;
Index: 2613/drivers/scsi/scsi_scan.c
===================================================================
--- 2613.orig/drivers/scsi/scsi_scan.c
+++ 2613/drivers/scsi/scsi_scan.c
@@ -1210,25 +1210,28 @@ struct scsi_device *__scsi_add_device(st
uint id, uint lun, void *hostdata)
{
struct scsi_device *sdev;
- struct device *parent = &shost->shost_gendev;
- int res;
- struct scsi_target *starget = scsi_alloc_target(parent, channel, id);
-
- if (!starget)
- return ERR_PTR(-ENOMEM);
+ struct scsi_target *starget;
- get_device(&starget->dev);
down(&shost->scan_mutex);
- if (scsi_host_scan_allowed(shost)) {
- res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
- hostdata);
- if (res != SCSI_SCAN_LUN_PRESENT)
- sdev = ERR_PTR(-ENODEV);
+ if (!scsi_host_scan_allowed(shost)) {
+ sdev = ERR_PTR(-ENODEV);
+ goto out;
}
- up(&shost->scan_mutex);
+ starget = scsi_alloc_target(&shost->shost_gendev, channel, id);
+ if (!starget) {
+ sdev = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ get_device(&starget->dev);
+ if (scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata)
+ != SCSI_SCAN_LUN_PRESENT)
+ sdev = ERR_PTR(-ENODEV);
scsi_target_reap(starget);
put_device(&starget->dev);
+ out:
+ up(&shost->scan_mutex);
return sdev;
}
EXPORT_SYMBOL(__scsi_add_device);
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-07-26 14:12 [PATCH 1/5] SCSI scanning and removal fixes Alan Stern
@ 2005-09-07 15:16 ` James Bottomley
2005-09-07 18:27 ` Alan Stern
0 siblings, 1 reply; 30+ messages in thread
From: James Bottomley @ 2005-09-07 15:16 UTC (permalink / raw)
To: Alan Stern; +Cc: SCSI development list
On Tue, 2005-07-26 at 10:12 -0400, Alan Stern wrote:
> This patch (as542) fixes a few loose ends left by Mike's patches. It adds
> a declaration for the new scsi_host_set_state routine, adds an allowed
> transition from the SHOST_RECOVERY state to the SHOST_CANCEL state, and
> avoids returning an uninitialized value in __scsi_add_device.
The first part (external declaration) is already in.
The second (allow RECOVERY->CANCEL) isn't really an answer. The correct
thing, I suppose, is to have scsi_remove_host() wait for the error
handler to finish if the state transition cannot be accomodated
(otherwise the error handler will try to transition ->RUNNING part way
through the removal).
The third (don't allow uninitialised return from __scsi_add_device) is
correct, but the return is universally ignored (the only actual user
being ipr). Unfortunately, now I look at this, ipr gets it wrong too.
This API currently returns an sdev with an incremented refcount. If you
ignore the return, as ipr does, you're leaking refcounts. So, since the
only user gets it wrong all the time, I'd vote for modifying the API not
to return a device.
James
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 15:16 ` James Bottomley
@ 2005-09-07 18:27 ` Alan Stern
2005-09-07 18:37 ` Luben Tuikov
` (2 more replies)
0 siblings, 3 replies; 30+ messages in thread
From: Alan Stern @ 2005-09-07 18:27 UTC (permalink / raw)
To: James Bottomley; +Cc: SCSI development list
On Wed, 7 Sep 2005, James Bottomley wrote:
> On Tue, 2005-07-26 at 10:12 -0400, Alan Stern wrote:
> > This patch (as542) fixes a few loose ends left by Mike's patches. It adds
> > a declaration for the new scsi_host_set_state routine, adds an allowed
> > transition from the SHOST_RECOVERY state to the SHOST_CANCEL state, and
> > avoids returning an uninitialized value in __scsi_add_device.
>
> The first part (external declaration) is already in.
>
> The second (allow RECOVERY->CANCEL) isn't really an answer. The correct
> thing, I suppose, is to have scsi_remove_host() wait for the error
> handler to finish if the state transition cannot be accomodated
> (otherwise the error handler will try to transition ->RUNNING part way
> through the removal).
I'm going to argue strongly about this. scsi_remove_host should _not_
wait for error recovery to complete -- to do so will invite deadlocks.
(Suppose the error handler is waiting for a bus reset, but the bus reset
routine requires a semaphore held by the LLD during the call to
scsi_remove_host?) Furthermore, error recovery can potentially take quite
a long time -- much longer than we want to wait during a removal event.
Instead, the error handler should not be allowed to make the transition to
RUNNING once the removal has started.
> The third (don't allow uninitialised return from __scsi_add_device) is
> correct, but the return is universally ignored (the only actual user
> being ipr). Unfortunately, now I look at this, ipr gets it wrong too.
> This API currently returns an sdev with an incremented refcount. If you
> ignore the return, as ipr does, you're leaking refcounts. So, since the
> only user gets it wrong all the time, I'd vote for modifying the API not
> to return a device.
Changing the API is fine with me, but the existing code is still shaky
because it calls scsi_alloc_target before checking scsi_host_scan_allowed.
Maybe that's not an out-and-out mistake, but better to avoid it.
Would you like me to submit an updated patch?
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 18:27 ` Alan Stern
@ 2005-09-07 18:37 ` Luben Tuikov
2005-09-07 18:42 ` Luben Tuikov
2005-09-07 19:58 ` James Bottomley
2 siblings, 0 replies; 30+ messages in thread
From: Luben Tuikov @ 2005-09-07 18:37 UTC (permalink / raw)
To: Alan Stern; +Cc: James Bottomley, SCSI development list
On 09/07/05 14:27, Alan Stern wrote:
> On Wed, 7 Sep 2005, James Bottomley wrote:
>
>
>>On Tue, 2005-07-26 at 10:12 -0400, Alan Stern wrote:
>>
>>>This patch (as542) fixes a few loose ends left by Mike's patches. It adds
>>>a declaration for the new scsi_host_set_state routine, adds an allowed
>>>transition from the SHOST_RECOVERY state to the SHOST_CANCEL state, and
>>>avoids returning an uninitialized value in __scsi_add_device.
>>
>>The first part (external declaration) is already in.
>>
>>The second (allow RECOVERY->CANCEL) isn't really an answer. The correct
>>thing, I suppose, is to have scsi_remove_host() wait for the error
>>handler to finish if the state transition cannot be accomodated
>>(otherwise the error handler will try to transition ->RUNNING part way
>>through the removal).
>
>
> I'm going to argue strongly about this. scsi_remove_host should _not_
> wait for error recovery to complete -- to do so will invite deadlocks.
> (Suppose the error handler is waiting for a bus reset, but the bus reset
> routine requires a semaphore held by the LLD during the call to
> scsi_remove_host?) Furthermore, error recovery can potentially take quite
> a long time -- much longer than we want to wait during a removal event.
> Instead, the error handler should not be allowed to make the transition to
> RUNNING once the removal has started.
Hey guys,
I haven't looked at Alan's patches in detail, but would just like
to mention that my driver supports hot plugging _and_unplugging_
of devices and _whole_domains_ (many devices at the same time,
plug and unplug).
scsi hosts are also dynamically created and destroyed.
Currently there is absolutely no problems with any deadlocks or anything
like that. (Of course the driver implements its own eh+timeout hooks.)
Make sure you guys do not break something. ;-)
Luben
>
>
>>The third (don't allow uninitialised return from __scsi_add_device) is
>>correct, but the return is universally ignored (the only actual user
>>being ipr). Unfortunately, now I look at this, ipr gets it wrong too.
>>This API currently returns an sdev with an incremented refcount. If you
>>ignore the return, as ipr does, you're leaking refcounts. So, since the
>>only user gets it wrong all the time, I'd vote for modifying the API not
>>to return a device.
>
>
> Changing the API is fine with me, but the existing code is still shaky
> because it calls scsi_alloc_target before checking scsi_host_scan_allowed.
> Maybe that's not an out-and-out mistake, but better to avoid it.
>
> Would you like me to submit an updated patch?
>
> Alan Stern
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 18:27 ` Alan Stern
2005-09-07 18:37 ` Luben Tuikov
@ 2005-09-07 18:42 ` Luben Tuikov
2005-09-07 19:31 ` Alan Stern
2005-09-07 19:58 ` James Bottomley
2 siblings, 1 reply; 30+ messages in thread
From: Luben Tuikov @ 2005-09-07 18:42 UTC (permalink / raw)
To: Alan Stern; +Cc: James Bottomley, SCSI development list
On 09/07/05 14:27, Alan Stern wrote:
> On Wed, 7 Sep 2005, James Bottomley wrote:
>
>
>>On Tue, 2005-07-26 at 10:12 -0400, Alan Stern wrote:
>>
>>>This patch (as542) fixes a few loose ends left by Mike's patches. It adds
>>>a declaration for the new scsi_host_set_state routine, adds an allowed
>>>transition from the SHOST_RECOVERY state to the SHOST_CANCEL state, and
>>>avoids returning an uninitialized value in __scsi_add_device.
>>
>>The first part (external declaration) is already in.
>>
>>The second (allow RECOVERY->CANCEL) isn't really an answer. The correct
>>thing, I suppose, is to have scsi_remove_host() wait for the error
>>handler to finish if the state transition cannot be accomodated
>>(otherwise the error handler will try to transition ->RUNNING part way
>>through the removal).
>
>
> I'm going to argue strongly about this. scsi_remove_host should _not_
> wait for error recovery to complete -- to do so will invite deadlocks.
> (Suppose the error handler is waiting for a bus reset, but the bus reset
> routine requires a semaphore held by the LLD during the call to
> scsi_remove_host?) Furthermore, error recovery can potentially take quite
> a long time -- much longer than we want to wait during a removal event.
> Instead, the error handler should not be allowed to make the transition to
> RUNNING once the removal has started.
Alan, this tells me one thing: the _layering_ infrastructure is broken,
and in this case, it looks like is not SCSI Core.
E.g. why is the LLDD messing with semas of the host? (rhetorical, please
do not answer as this would go into another thread...)
BTW, since the eh is a _function of the host_, James is correct that
scsi_remove_host should wait for the eh to finish.
This makes me believe that maybe USB storage would need an overhaul
of the event infra: removing and adding, and/or implement its own
eh.
Luben
>
>
>>The third (don't allow uninitialised return from __scsi_add_device) is
>>correct, but the return is universally ignored (the only actual user
>>being ipr). Unfortunately, now I look at this, ipr gets it wrong too.
>>This API currently returns an sdev with an incremented refcount. If you
>>ignore the return, as ipr does, you're leaking refcounts. So, since the
>>only user gets it wrong all the time, I'd vote for modifying the API not
>>to return a device.
>
>
> Changing the API is fine with me, but the existing code is still shaky
> because it calls scsi_alloc_target before checking scsi_host_scan_allowed.
> Maybe that's not an out-and-out mistake, but better to avoid it.
>
> Would you like me to submit an updated patch?
>
> Alan Stern
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 18:42 ` Luben Tuikov
@ 2005-09-07 19:31 ` Alan Stern
2005-09-07 20:00 ` Mike Anderson
2005-09-07 20:43 ` Luben Tuikov
0 siblings, 2 replies; 30+ messages in thread
From: Alan Stern @ 2005-09-07 19:31 UTC (permalink / raw)
To: Luben Tuikov; +Cc: James Bottomley, SCSI development list
On Wed, 7 Sep 2005, Luben Tuikov wrote:
> On 09/07/05 14:27, Alan Stern wrote:
> > I'm going to argue strongly about this. scsi_remove_host should _not_
> > wait for error recovery to complete -- to do so will invite deadlocks.
> > (Suppose the error handler is waiting for a bus reset, but the bus reset
> > routine requires a semaphore held by the LLD during the call to
> > scsi_remove_host?) Furthermore, error recovery can potentially take quite
> > a long time -- much longer than we want to wait during a removal event.
> > Instead, the error handler should not be allowed to make the transition to
> > RUNNING once the removal has started.
>
> Alan, this tells me one thing: the _layering_ infrastructure is broken,
> and in this case, it looks like is not SCSI Core.
>
> E.g. why is the LLDD messing with semas of the host? (rhetorical, please
> do not answer as this would go into another thread...)
>
> BTW, since the eh is a _function of the host_, James is correct that
> scsi_remove_host should wait for the eh to finish.
That's a very good point. It hadn't occurred to me before, but you're
absolutely right. scsi_remove_host should indeed wait for the error
handler to finish. But first it should set things up so that the
everything the error handler does will fail-fast, so that the eh can
return quickly. That will include putting the device into the SDEV_CANCEL
state, so it remains true that the error handler better not try to move
from CANCEL back to RUNNING.
As for layering violations and deadlocks... Unfortunately the violation
is unavoidable. It's related to the way the error handler sometimes tries
to fix a non-working device by doing a bus reset, which will also affect
all the other devices on the same bus. The same sort of thing applies to
USB. Fortunately the deadlock _is_ avoidable; in fact the USB driver
already has code in place to fail the reset attempt if it takes too long
to acquire the lock. So that's no longer an issue.
> This makes me believe that maybe USB storage would need an overhaul
> of the event infra: removing and adding, and/or implement its own
> eh.
In the long run that might be good, but for now I think we'll be okay.
The important thing is to make sure that once the device has moved to the
CANCEL state, everything fails quickly.
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 18:27 ` Alan Stern
2005-09-07 18:37 ` Luben Tuikov
2005-09-07 18:42 ` Luben Tuikov
@ 2005-09-07 19:58 ` James Bottomley
2005-09-07 22:05 ` James Bottomley
` (2 more replies)
2 siblings, 3 replies; 30+ messages in thread
From: James Bottomley @ 2005-09-07 19:58 UTC (permalink / raw)
To: Alan Stern; +Cc: SCSI development list
On Wed, 2005-09-07 at 14:27 -0400, Alan Stern wrote:
> > The second (allow RECOVERY->CANCEL) isn't really an answer. The correct
> > thing, I suppose, is to have scsi_remove_host() wait for the error
> > handler to finish if the state transition cannot be accomodated
> > (otherwise the error handler will try to transition ->RUNNING part way
> > through the removal).
>
> I'm going to argue strongly about this. scsi_remove_host should _not_
> wait for error recovery to complete -- to do so will invite deadlocks.
> (Suppose the error handler is waiting for a bus reset, but the bus reset
> routine requires a semaphore held by the LLD during the call to
> scsi_remove_host?) Furthermore, error recovery can potentially take quite
> a long time -- much longer than we want to wait during a removal event.
> Instead, the error handler should not be allowed to make the transition to
> RUNNING once the removal has started.
I agree (about the deadlocks). However, as things stand RECOVERY is a
state in the model and the model can only be in a single state. If you
permit the transition, and recovery is going on in parallel with
removal, they'll race to set the final state (removal wants DEL and the
eh thread will set it to RUNNING).
Either we go back to having an in_recovery flag (i.e. lift recovery out
of the state model) or we make the model more complex to cope with this.
Since really the only thing we test is in_recovery, we could do a more
complex model; something like:
created
|
v <---------
running ---------> recovery
| |
v <---------- v
cancel ----------> recover/cancel
| |
v -----------> v
del <------------ recover/del
I also think I'd like not to go from del -> recover/del, but unless del
actually means that all devices have completed their I/O for deletion
that can't be avoided.
> Changing the API is fine with me, but the existing code is still shaky
> because it calls scsi_alloc_target before checking scsi_host_scan_allowed.
> Maybe that's not an out-and-out mistake, but better to avoid it.
Actually, alloc_target is properly guarded so it doesn't need the scan
mutex. It might be nice to update the SDEV_ state model to include a
"scanning" state, that way we could properly guard the sdev_alloc as
well and dump the scan mutex ... that's probably more than a slight
change, though.
> Would you like me to submit an updated patch?
Yes, please. It's been suggested that we should have a scsi_add_target
that returns zero on success or error on failure (with no ref to the
sdev) and keep the old behaviour of __scsi_add_target().
James
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 19:31 ` Alan Stern
@ 2005-09-07 20:00 ` Mike Anderson
2005-09-07 20:43 ` Luben Tuikov
1 sibling, 0 replies; 30+ messages in thread
From: Mike Anderson @ 2005-09-07 20:00 UTC (permalink / raw)
To: Alan Stern; +Cc: Luben Tuikov, James Bottomley, SCSI development list
Alan Stern <stern@rowland.harvard.edu> wrote:
> On Wed, 7 Sep 2005, Luben Tuikov wrote:
>
> > On 09/07/05 14:27, Alan Stern wrote:
>
> > > I'm going to argue strongly about this. scsi_remove_host should _not_
> > > wait for error recovery to complete -- to do so will invite deadlocks.
> > > (Suppose the error handler is waiting for a bus reset, but the bus reset
> > > routine requires a semaphore held by the LLD during the call to
> > > scsi_remove_host?) Furthermore, error recovery can potentially take quite
> > > a long time -- much longer than we want to wait during a removal event.
> > > Instead, the error handler should not be allowed to make the transition to
> > > RUNNING once the removal has started.
> >
> > Alan, this tells me one thing: the _layering_ infrastructure is broken,
> > and in this case, it looks like is not SCSI Core.
> >
> > E.g. why is the LLDD messing with semas of the host? (rhetorical, please
> > do not answer as this would go into another thread...)
> >
> > BTW, since the eh is a _function of the host_, James is correct that
> > scsi_remove_host should wait for the eh to finish.
>
> That's a very good point. It hadn't occurred to me before, but you're
> absolutely right. scsi_remove_host should indeed wait for the error
> handler to finish. But first it should set things up so that the
> everything the error handler does will fail-fast, so that the eh can
> return quickly. That will include putting the device into the SDEV_CANCEL
> state, so it remains true that the error handler better not try to move
> from CANCEL back to RUNNING.
>
Well the scsi_device_set_state function / model will not let us move a
device from SDEV_CANCEL to SDEV_RUNNING again.
To fail faster (I assumed you mean the concept not the flag) we would need
to add a few checks during the start of some of the functions. It would be
good to make these as efficient as possibly, but I guess we are already in
the error handler so we have take a time hit already.
-andmike
--
Michael Anderson
andmike@us.ibm.com
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 19:31 ` Alan Stern
2005-09-07 20:00 ` Mike Anderson
@ 2005-09-07 20:43 ` Luben Tuikov
2005-09-07 21:34 ` Stefan Richter
2005-09-08 15:19 ` Alan Stern
1 sibling, 2 replies; 30+ messages in thread
From: Luben Tuikov @ 2005-09-07 20:43 UTC (permalink / raw)
To: Alan Stern; +Cc: James Bottomley, SCSI development list
On 09/07/05 15:31, Alan Stern wrote:
>
> As for layering violations and deadlocks... Unfortunately the violation
> is unavoidable. It's related to the way the error handler sometimes tries
> to fix a non-working device by doing a bus reset, which will also affect
> all the other devices on the same bus.
Yes, that's a good point.
Is it possible to implement LU Reset TMF for USB storage devices?
If so, then you do not need to do a "bus reset".
*General note:* It is very bad to have to punish all devices on the
"bus" just because one device failed. Isn't there a better way
to recover(*) a failed USB Storage device?
(*) That doesn't necessarily mean "bring back to life", it could
also mean "remove".
That is, a "bus reset" means that also any other device on the "bus" is
unreachable. If this is _not_ the case, then a "bus" reset must _not_
take place.
>>This makes me believe that maybe USB storage would need an overhaul
>>of the event infra: removing and adding, and/or implement its own
>>eh.
>
> In the long run that might be good, but for now I think we'll be okay.
> The important thing is to make sure that once the device has moved to the
> CANCEL state, everything fails quickly.
If you have the means to do transport checking of the state of the
device, (and it seems like you can for USB Storage, since it is USB after
all), then you _must_ implement your own eh handler. This is what
it is for. Please, consider.
Luben
P.S. It may actually simplify things in the USB transport layer _and_ in
SCSI Core (i.e. no need for those patches).
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 20:43 ` Luben Tuikov
@ 2005-09-07 21:34 ` Stefan Richter
2005-09-08 15:19 ` Alan Stern
1 sibling, 0 replies; 30+ messages in thread
From: Stefan Richter @ 2005-09-07 21:34 UTC (permalink / raw)
To: Luben Tuikov; +Cc: Alan Stern, James Bottomley, SCSI development list
Luben Tuikov wrote:
> It is very bad to have to punish all devices on the
> "bus" just because one device failed. Isn't there a better way
> to recover(*) a failed USB Storage device?
usb-storage implements scsi_mod bus reset as USB port reset. This
affects only the failing device.
There is one scsi_mod bus per SCSI target in usb-storage. There is no
mapping from scsi_mod bus to USB bus. The same is true for sbp2.
Usb-storage and sbp2 actually don't care at all for the bus a device is
attached to.
(Or at least that's how I understand the USB subsystem; I'm sure about
the 1394 subsystem.)
--
Stefan Richter
-=====-=-=-= =--= --===
http://arcgraph.de/sr/
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 19:58 ` James Bottomley
@ 2005-09-07 22:05 ` James Bottomley
2005-09-08 15:59 ` Alan Stern
2005-09-08 16:08 ` Alan Stern
2 siblings, 0 replies; 30+ messages in thread
From: James Bottomley @ 2005-09-07 22:05 UTC (permalink / raw)
To: Alan Stern; +Cc: SCSI development list
On Wed, 2005-09-07 at 14:58 -0500, James Bottomley wrote:
> On Wed, 2005-09-07 at 14:27 -0400, Alan Stern wrote:
> > I'm going to argue strongly about this. scsi_remove_host should _not_
> > wait for error recovery to complete -- to do so will invite deadlocks.
> > (Suppose the error handler is waiting for a bus reset, but the bus reset
> > routine requires a semaphore held by the LLD during the call to
> > scsi_remove_host?) Furthermore, error recovery can potentially take quite
> > a long time -- much longer than we want to wait during a removal event.
> > Instead, the error handler should not be allowed to make the transition to
> > RUNNING once the removal has started.
>
> I agree (about the deadlocks). However, as things stand RECOVERY is a
> state in the model and the model can only be in a single state. If you
> permit the transition, and recovery is going on in parallel with
> removal, they'll race to set the final state (removal wants DEL and the
> eh thread will set it to RUNNING).
>
> Either we go back to having an in_recovery flag (i.e. lift recovery out
> of the state model) or we make the model more complex to cope with this.
> Since really the only thing we test is in_recovery, we could do a more
> complex model; something like:
OK, try this as an implementation of that model (except I junked the DEL
-> DEL_RECOVERY path).
There's a few nasties in this (notably that timed out commands will be
finished without error recovery from the DEL state).
James
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -98,6 +98,7 @@ int scsi_host_set_state(struct Scsi_Host
switch (oldstate) {
case SHOST_CREATED:
case SHOST_RUNNING:
+ case SHOST_CANCEL_RECOVERY:
break;
default:
goto illegal;
@@ -107,12 +108,31 @@ int scsi_host_set_state(struct Scsi_Host
case SHOST_DEL:
switch (oldstate) {
case SHOST_CANCEL:
+ case SHOST_DEL_RECOVERY:
break;
default:
goto illegal;
}
break;
+ case SHOST_CANCEL_RECOVERY:
+ switch (oldstate) {
+ case SHOST_CANCEL:
+ case SHOST_RECOVERY:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case SHOST_DEL_RECOVERY:
+ switch (oldstate) {
+ case SHOST_CANCEL_RECOVERY:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
}
shost->shost_state = state;
return 0;
@@ -135,12 +155,17 @@ EXPORT_SYMBOL(scsi_host_set_state);
void scsi_remove_host(struct Scsi_Host *shost)
{
down(&shost->scan_mutex);
- scsi_host_set_state(shost, SHOST_CANCEL);
+ if (!scsi_host_set_state(shost, SHOST_CANCEL))
+ if (!scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) {
+ up(&shost->scan_mutex);
+ return;
+ }
up(&shost->scan_mutex);
scsi_forget_host(shost);
scsi_proc_host_rm(shost);
- scsi_host_set_state(shost, SHOST_DEL);
+ if (!scsi_host_set_state(shost, SHOST_DEL))
+ BUG_ON(!scsi_host_set_state(shost, SHOST_DEL_RECOVERY));
transport_unregister_device(&shost->shost_gendev);
class_device_unregister(&shost->shost_classdev);
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -68,19 +68,24 @@ int scsi_eh_scmd_add(struct scsi_cmnd *s
{
struct Scsi_Host *shost = scmd->device->host;
unsigned long flags;
+ int ret = 0;
if (shost->eh_wait == NULL)
return 0;
spin_lock_irqsave(shost->host_lock, flags);
+ if (!scsi_host_set_state(shost, SHOST_RECOVERY))
+ if (!scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY))
+ goto out_unlock;
+ ret = 1;
scmd->eh_eflags |= eh_flag;
list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
- scsi_host_set_state(shost, SHOST_RECOVERY);
shost->host_failed++;
scsi_eh_wakeup(shost);
+ out_unlock:
spin_unlock_irqrestore(shost->host_lock, flags);
- return 1;
+ return ret;
}
/**
@@ -176,8 +181,8 @@ void scsi_times_out(struct scsi_cmnd *sc
}
if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
- panic("Error handler thread not present at %p %p %s %d",
- scmd, scmd->device->host, __FILE__, __LINE__);
+ scmd->result |= DID_TIME_OUT << 16;
+ __scsi_done(scmd);
}
}
@@ -196,8 +201,7 @@ int scsi_block_when_processing_errors(st
{
int online;
- wait_event(sdev->host->host_wait, (sdev->host->shost_state !=
- SHOST_RECOVERY));
+ wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host));
online = scsi_device_online(sdev);
@@ -1460,7 +1464,9 @@ static void scsi_restart_operations(stru
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
__FUNCTION__));
- scsi_host_set_state(shost, SHOST_RUNNING);
+ if (!scsi_host_set_state(shost, SHOST_RUNNING))
+ if (!scsi_host_set_state(shost, SHOST_CANCEL))
+ BUG_ON(!scsi_host_set_state(shost, SHOST_DEL));
wake_up(&shost->host_wait);
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -458,7 +458,7 @@ int scsi_nonblockable_ioctl(struct scsi_
* error processing, as long as the device was opened
* non-blocking */
if (filp && filp->f_flags & O_NONBLOCK) {
- if (sdev->host->shost_state == SHOST_RECOVERY)
+ if (scsi_host_in_recovery(sdev->host))
return -ENODEV;
} else if (!scsi_block_when_processing_errors(sdev))
return -ENODEV;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -424,7 +424,7 @@ void scsi_device_unbusy(struct scsi_devi
spin_lock_irqsave(shost->host_lock, flags);
shost->host_busy--;
- if (unlikely((shost->shost_state == SHOST_RECOVERY) &&
+ if (unlikely(scsi_host_in_recovery(shost) &&
shost->host_failed))
scsi_eh_wakeup(shost);
spin_unlock(shost->host_lock);
@@ -1306,7 +1306,7 @@ static inline int scsi_host_queue_ready(
struct Scsi_Host *shost,
struct scsi_device *sdev)
{
- if (shost->shost_state == SHOST_RECOVERY)
+ if (scsi_host_in_recovery(shost))
return 0;
if (shost->host_busy == 0 && shost->host_blocked) {
/*
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -57,6 +57,8 @@ static struct {
{ SHOST_CANCEL, "cancel" },
{ SHOST_DEL, "deleted" },
{ SHOST_RECOVERY, "recovery" },
+ { SHOST_CANCEL_RECOVERY, "cancel/recovery" },
+ { SHOST_DEL_RECOVERY, "deleted/recovery", },
};
const char *scsi_host_state_name(enum scsi_host_state state)
{
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1027,7 +1027,7 @@ sg_ioctl(struct inode *inode, struct fil
if (sdp->detached)
return -ENODEV;
if (filp->f_flags & O_NONBLOCK) {
- if (sdp->device->host->shost_state == SHOST_RECOVERY)
+ if (scsi_host_in_recovery(sdp->device->host))
return -EBUSY;
} else if (!scsi_block_when_processing_errors(sdp->device))
return -EBUSY;
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -439,6 +439,8 @@ enum scsi_host_state {
SHOST_CANCEL,
SHOST_DEL,
SHOST_RECOVERY,
+ SHOST_CANCEL_RECOVERY,
+ SHOST_DEL_RECOVERY,
};
struct Scsi_Host {
@@ -621,6 +623,13 @@ static inline struct Scsi_Host *dev_to_s
return container_of(dev, struct Scsi_Host, shost_gendev);
}
+static inline int scsi_host_in_recovery(struct Scsi_Host *shost)
+{
+ return shost->shost_state == SHOST_RECOVERY ||
+ shost->shost_state == SHOST_CANCEL_RECOVERY ||
+ shost->shost_state == SHOST_DEL_RECOVERY;
+}
+
extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
extern void scsi_flush_work(struct Scsi_Host *);
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 20:43 ` Luben Tuikov
2005-09-07 21:34 ` Stefan Richter
@ 2005-09-08 15:19 ` Alan Stern
2005-09-08 16:07 ` Luben Tuikov
1 sibling, 1 reply; 30+ messages in thread
From: Alan Stern @ 2005-09-08 15:19 UTC (permalink / raw)
To: Stefan Richter, Luben Tuikov; +Cc: James Bottomley, SCSI development list
On Wed, 7 Sep 2005, Stefan Richter wrote:
> usb-storage implements scsi_mod bus reset as USB port reset. This
> affects only the failing device.
Correct, but you're forgetting that in USB a single device can contain
more than one "interface", and drivers bind to interfaces, not devices.
Doing a USB port reset has implications beyond those of the single
interface controlled by usb-storage, since it affects the entire device.
In fact, the current version refuses to do a port reset if there are other
interfaces present.
> There is one scsi_mod bus per SCSI target in usb-storage.
That's not quite entirely true. There are a few obscure USB mass-storage
devices that actually are a SCSI host adapter and control a real SCSI bus.
But for all practical purposes we can forget about them.
On Wed, 7 Sep 2005, Luben Tuikov wrote:
> Is it possible to implement LU Reset TMF for USB storage devices?
> If so, then you do not need to do a "bus reset".
Sorry, I don't know that acronym. What is TMF?
> *General note:* It is very bad to have to punish all devices on the
> "bus" just because one device failed. Isn't there a better way
> to recover(*) a failed USB Storage device?
No. There are only two reset mechanisms available for USB Mass Storage.
One is a class-specific reset command (which usb-storage issues when asked
to do a device reset), and the other is a USB port reset (which
usb-storage issues when asked to do a bus reset).
In practice, it turns out that many (perhaps even most) USB Storage
devices don't implement the class-specific reset command correctly.
Windows doesn't use it at all, so far as I know. This means our only
realistic option is the USB port reset.
> (*) That doesn't necessarily mean "bring back to life", it could
> also mean "remove".
Well, usb-storage doesn't need to "remove" a failed device. The SCSI core
does a perfectly good job just by setting it off-line. And since there
aren't other targets sharing the bus, that's good enough.
> That is, a "bus reset" means that also any other device on the "bus" is
> unreachable. If this is _not_ the case, then a "bus" reset must _not_
> take place.
I'm not sure what that first sentence is intended to mean. The SCSI error
handler _does_ issue bus resets even when other devices on the bus are
still reachable, doesn't it? Provided the others are idle at the time,
there shouldn't be any harm in it.
> If you have the means to do transport checking of the state of the
> device, (and it seems like you can for USB Storage, since it is USB after
> all), then you _must_ implement your own eh handler. This is what
> it is for. Please, consider.
>
> Luben
>
> P.S. It may actually simplify things in the USB transport layer _and_ in
> SCSI Core (i.e. no need for those patches).
We are sort of moving in that direction. usb-storage already does its
own unsolicited resets when unexpected error occur. But we don't have
anything like the error-handler's mechanism for recovering from timeouts
(TUR, then device reset, then TUR, then bus reset, ...). There doesn't
seem to be any point in reinventing all that code.
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 19:58 ` James Bottomley
2005-09-07 22:05 ` James Bottomley
@ 2005-09-08 15:59 ` Alan Stern
2005-09-08 16:15 ` James Bottomley
2005-09-08 16:08 ` Alan Stern
2 siblings, 1 reply; 30+ messages in thread
From: Alan Stern @ 2005-09-08 15:59 UTC (permalink / raw)
To: James Bottomley; +Cc: SCSI development list
On Wed, 7 Sep 2005, James Bottomley wrote:
> I agree (about the deadlocks). However, as things stand RECOVERY is a
> state in the model and the model can only be in a single state. If you
> permit the transition, and recovery is going on in parallel with
> removal, they'll race to set the final state (removal wants DEL and the
> eh thread will set it to RUNNING).
>
> Either we go back to having an in_recovery flag (i.e. lift recovery out
> of the state model) or we make the model more complex to cope with this.
> Since really the only thing we test is in_recovery, we could do a more
> complex model; something like:
>
> created
> |
> v <---------
> running ---------> recovery
> | |
> v <---------- v
> cancel ----------> recover/cancel
> | |
> v -----------> v
> del <------------ recover/del
>
> I also think I'd like not to go from del -> recover/del, but unless del
> actually means that all devices have completed their I/O for deletion
> that can't be avoided.
I don't understand your reasoning. With your new system, you end up with
two threads doing this:
Removal thread Error handler thread
------------------------- ---------------------------
Go from RUNNING to RECOVERY
Try to go to CANCEL, fail
Go to CANCEL_RECOVERY
race: Go to DEL_RECOVERY Try to go to RUNNING, fail
Whereas the old system has the two threads doing this:
Removal thread Error handler thread
------------------------- ---------------------------
Go from RUNNING to RECOVERY
Go to CANCEL
race: Go to DEL Try to go to RUNNING, fail
At least, that's how it would work if you allow the RECOVERY -> CANCEL
transition. Either way you end up in the correct state. So what's wrong
with the old (current) system?
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 15:19 ` Alan Stern
@ 2005-09-08 16:07 ` Luben Tuikov
2005-09-08 18:36 ` Alan Stern
0 siblings, 1 reply; 30+ messages in thread
From: Luben Tuikov @ 2005-09-08 16:07 UTC (permalink / raw)
To: Alan Stern; +Cc: Stefan Richter, James Bottomley, SCSI development list
On 09/08/05 11:19, Alan Stern wrote:
> On Wed, 7 Sep 2005, Luben Tuikov wrote:
>
>
>>Is it possible to implement LU Reset TMF for USB storage devices?
>>If so, then you do not need to do a "bus reset".
>
>
> Sorry, I don't know that acronym. What is TMF?
Good morning Alan,
I meant Task Management Function. (SAM from T10.org, section 7).
All newer storage transports are requred to have a direct mapping
of TMFs to transport units, e.g. SAS.
>>*General note:* It is very bad to have to punish all devices on the
>>"bus" just because one device failed. Isn't there a better way
>>to recover(*) a failed USB Storage device?
>
> No. There are only two reset mechanisms available for USB Mass Storage.
I see.
> One is a class-specific reset command (which usb-storage issues when asked
> to do a device reset),
So as far as I can see it sends a reset on the wire to the device?
> and the other is a USB port reset (which
> usb-storage issues when asked to do a bus reset).
As far as I see this resets the port on the host side and then
rediscovers the devices?
> In practice, it turns out that many (perhaps even most) USB Storage
> devices don't implement the class-specific reset command correctly.
> Windows doesn't use it at all, so far as I know. This means our only
> realistic option is the USB port reset.
>
>
>>(*) That doesn't necessarily mean "bring back to life", it could
>>also mean "remove".
>
>
> Well, usb-storage doesn't need to "remove" a failed device. The SCSI core
> does a perfectly good job just by setting it off-line. And since there
> aren't other targets sharing the bus, that's good enough.
Well what happens when I just unplug the device?
>>That is, a "bus reset" means that also any other device on the "bus" is
>>unreachable. If this is _not_ the case, then a "bus" reset must _not_
>>take place.
>
> I'm not sure what that first sentence is intended to mean. The SCSI error
> handler _does_ issue bus resets even when other devices on the bus are
> still reachable, doesn't it? Provided the others are idle at the time,
> there shouldn't be any harm in it.
Ok, I see where the confusion is.
>>If you have the means to do transport checking of the state of the
>>device, (and it seems like you can for USB Storage, since it is USB after
>>all), then you _must_ implement your own eh handler. This is what
>>it is for. Please, consider.
>>
>> Luben
>>
>>P.S. It may actually simplify things in the USB transport layer _and_ in
>>SCSI Core (i.e. no need for those patches).
>
>
> We are sort of moving in that direction. usb-storage already does its
> own unsolicited resets when unexpected error occur. But we don't have
> anything like the error-handler's mechanism for recovering from timeouts
> (TUR, then device reset, then TUR, then bus reset, ...). There doesn't
> seem to be any point in reinventing all that code.
What code? What reinvention?
You _need_ to implement a timeout and eh hook if you want to do this
in any sane way.
You also need to implement kref via kobject for the devices which you/USB Storage
represent to SCSI Core. You also need to get rid of that horrible patchwork
of a solution: dev_semaphore. Maybe you can take a look in the SAS code and
see how this is all done?
Luben
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-07 19:58 ` James Bottomley
2005-09-07 22:05 ` James Bottomley
2005-09-08 15:59 ` Alan Stern
@ 2005-09-08 16:08 ` Alan Stern
2 siblings, 0 replies; 30+ messages in thread
From: Alan Stern @ 2005-09-08 16:08 UTC (permalink / raw)
To: James Bottomley, Mike Anderson; +Cc: SCSI development list
On Wed, 7 Sep 2005, James Bottomley wrote:
> Actually, alloc_target is properly guarded so it doesn't need the scan
> mutex. It might be nice to update the SDEV_ state model to include a
> "scanning" state, that way we could properly guard the sdev_alloc as
> well and dump the scan mutex ... that's probably more than a slight
> change, though.
Probably not a good idea, either. The "scanning" state applies to the
host, not a particular device -- the idea is to prevent one thread from
adding new devices while another thread is trying to get rid of all the
devices because the host is going away. (Not to mention, preventing two
threads from adding the same target at the same time!)
And this needs to be a mutex, since host removal must wait until scanning
finishes. Making it a state instead won't work well.
> > Would you like me to submit an updated patch?
>
> Yes, please. It's been suggested that we should have a scsi_add_target
> that returns zero on success or error on failure (with no ref to the
> sdev) and keep the old behaviour of __scsi_add_target().
On Wed, 7 Sep 2005, Mike Anderson wrote:
> On as542. The first hunk of the diff is already in (declare of
> scsi_host_set_state). The second hunk looks good (SHOST_RECOVERY label).
> The third hunk I will take in combination with the other patch that
> effects the scan code. This should have probably been
> another patch.
At this point, maybe it's best for me to step back and let Mike look
through the issues first. There's Patrick's patch to be combined with the
one I sent, and other things that need to be straightened out.
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 15:59 ` Alan Stern
@ 2005-09-08 16:15 ` James Bottomley
2005-09-08 18:58 ` Alan Stern
0 siblings, 1 reply; 30+ messages in thread
From: James Bottomley @ 2005-09-08 16:15 UTC (permalink / raw)
To: Alan Stern; +Cc: SCSI development list
On Thu, 2005-09-08 at 11:59 -0400, Alan Stern wrote:
> I don't understand your reasoning. With your new system, you end up with
> two threads doing this:
>
> Removal thread Error handler thread
> ------------------------- ---------------------------
> Go from RUNNING to RECOVERY
> Try to go to CANCEL, fail
> Go to CANCEL_RECOVERY
> race: Go to DEL_RECOVERY Try to go to RUNNING, fail
Actually, no, that's why we have the parallel EH states ... let me put
in the events that trigger state transitions so you can see what
happens:
EH thread finishes
<---------------
EH thread begins
---------------->
<---------
running ---------> recovery
| |
| | scsi_remove_host() called
v <---------- v
cancel ----------> recover/cancel
| |
| | scsi_remove_host finishes visibility removal
v v
del <------------ recover/del
So the EH is allowed to activate in either running or cancel states, but
goes through its own state transition eventually coming back to del when
it finishes. Once the EH gets into recover/cancel it can never
transition back to running.
> At least, that's how it would work if you allow the RECOVERY -> CANCEL
> transition. Either way you end up in the correct state. So what's wrong
> with the old (current) system?
It's just nasty on two counts:
1) we have an incorrect bifurcation in the state model and
2) we never actually enforce any of the state transitions.
James
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 16:07 ` Luben Tuikov
@ 2005-09-08 18:36 ` Alan Stern
2005-09-08 23:59 ` Luben Tuikov
0 siblings, 1 reply; 30+ messages in thread
From: Alan Stern @ 2005-09-08 18:36 UTC (permalink / raw)
To: Luben Tuikov; +Cc: SCSI development list
On Thu, 8 Sep 2005, Luben Tuikov wrote:
> > No. There are only two reset mechanisms available for USB Mass Storage.
>
> I see.
>
> > One is a class-specific reset command (which usb-storage issues when asked
> > to do a device reset),
>
> So as far as I can see it sends a reset on the wire to the device?
Sort of. It's not a low-level hardware reset, it's rather high-level.
If the device's firmware is busy doing something else, or is hung, or
doesn't implement resets correctly, then the reset won't work.
> > and the other is a USB port reset (which
> > usb-storage issues when asked to do a bus reset).
>
> As far as I see this resets the port on the host side and then
> rediscovers the devices?
That's right. (Except there's only one device to rediscover.) This is a
much lower-level action than the other sort, and is much more likely to
succeed.
> > Well, usb-storage doesn't need to "remove" a failed device. The SCSI core
> > does a perfectly good job just by setting it off-line. And since there
> > aren't other targets sharing the bus, that's good enough.
>
> Well what happens when I just unplug the device?
For a brief time (maybe 1/4 second) all commands will return DID_ERROR
and resets will return FAILED. Then usbcore will realize that the device
has been unplugged and will call the usb-storage disconnect method, which
in turn will call scsi_remove_host.
Does that answer your question? For more, see below.
> > We are sort of moving in that direction. usb-storage already does its
> > own unsolicited resets when unexpected error occur. But we don't have
> > anything like the error-handler's mechanism for recovering from timeouts
> > (TUR, then device reset, then TUR, then bus reset, ...). There doesn't
> > seem to be any point in reinventing all that code.
>
> What code? What reinvention?
scsi_unjam_host plus the things that it calls. Why add a private version
of all that to usb-storage when it already exists in scsi_error.c?
> You _need_ to implement a timeout and eh hook if you want to do this
> in any sane way.
No I don't. There already is a timeout in the SCSI core
(scmd->eh_timeout); I don't need to add another one.
> You also need to implement kref via kobject for the devices which you/USB Storage
> represent to SCSI Core.
Again, I don't need to. The data used by usb-storage belongs to the
private portion of the scsi_host, so it's already protected by the host's
kref.
> You also need to get rid of that horrible patchwork
> of a solution: dev_semaphore. Maybe you can take a look in the SAS code and
> see how this is all done?
I assume you're referring to the way dev_semaphore is used in the
bus_reset routine? It's sort of a preventative measure, because the SCSI
core and the driver core haven't quite settled down yet.
Here's the idea. We want to protect against a race between the error
handler doing a bus reset and the user doing rmmod usb-storage. With the
current code, I believe scsi_remove_host does not wait for devices to go
out of error recovery. Here is what might happen without dev_semaphore:
Error handler thread Rmmod thread
-------------------- ------------
eh calls usb-storage's bus_reset
-> calls usb_stor_port_reset
-> calls usb_lock_device_for_reset
-> calls usb_reset_device
Driver core calls usb-storage's
remove method
storage_disconnect calls
quiesce_and_remove_host
-> locks & releases dev_semaphore (*)
-> calls scsi_remove_host
(doesn't wait for eh)
-> returns to driver core
-> usb_reset_device does
the port reset
(This picture is over-simplified because the driver core does some locking
of its own before calling the remove method. Let's not worry about that.)
Now see what has happened. usb-storage's remove method has returned, so
it has given up all claims to the device. It shouldn't do anything more
that will affect the device. And yet in the eh thread it's about to do a
port reset!
Since in reality the bus_reset routine acquires dev_semaphore, the rmmod
thread will wait at (*) until the reset has finished. Alternatively, if
scsi_remove_host waited until the device was out of error recovery, then
we would be okay without using dev_semaphore.
The complication exists inside usb_lock_device_for_reset. That routine
ends up calling down_trylock and looping with a timeout, because of the
potential for a complicated deadlock that I have described before.
There's one more thing worth mentioning. Thanks to the resets carried out
internally by usb-storage, we may decide it's easiest not to implement the
bus_reset method at all! That would certainly solve all the problems with
dev_semaphore. :-)
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 16:15 ` James Bottomley
@ 2005-09-08 18:58 ` Alan Stern
2005-09-08 20:15 ` James Bottomley
0 siblings, 1 reply; 30+ messages in thread
From: Alan Stern @ 2005-09-08 18:58 UTC (permalink / raw)
To: James Bottomley; +Cc: SCSI development list
On Thu, 8 Sep 2005, James Bottomley wrote:
> Actually, no, that's why we have the parallel EH states ... let me put
> in the events that trigger state transitions so you can see what
> happens:
>
>
> EH thread finishes
> <---------------
>
> EH thread begins
> ---------------->
>
>
> <---------
> running ---------> recovery
> | |
> | | scsi_remove_host() called
> v <---------- v
> cancel ----------> recover/cancel
> | |
> | | scsi_remove_host finishes visibility removal
> v v
> del <------------ recover/del
>
> So the EH is allowed to activate in either running or cancel states, but
> goes through its own state transition eventually coming back to del when
> it finishes. Once the EH gets into recover/cancel it can never
> transition back to running.
Why allow cancel -> recover/cancel? Once the device is in the cancel
state, there isn't anything useful the error handler can accomplish, is
there? Failed or timed-out commands should simply return an error.
And if you accept that, then what point is there in distinguishing between
cancel and recover/cancel? As far as I can see, the only significant
difference is that in recover/cancel the error handler is running (but not
accomplishing anything). Is this related to 1) below?
> > At least, that's how it would work if you allow the RECOVERY -> CANCEL
> > transition. Either way you end up in the correct state. So what's wrong
> > with the old (current) system?
>
> It's just nasty on two counts:
>
> 1) we have an incorrect bifurcation in the state model and
> 2) we never actually enforce any of the state transitions.
Can you explain 1) more fully? I don't really understand what you're
getting at.
As for 2), what do you mean? In 2.6.13, scsi_device_set_state does not
change the state if the transition is illegal.
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 18:58 ` Alan Stern
@ 2005-09-08 20:15 ` James Bottomley
2005-09-09 0:18 ` Luben Tuikov
2005-09-09 14:16 ` Alan Stern
0 siblings, 2 replies; 30+ messages in thread
From: James Bottomley @ 2005-09-08 20:15 UTC (permalink / raw)
To: Alan Stern; +Cc: SCSI development list
On Thu, 2005-09-08 at 14:58 -0400, Alan Stern wrote:
> On Thu, 8 Sep 2005, James Bottomley wrote:
> > Actually, no, that's why we have the parallel EH states ... let me put
> > in the events that trigger state transitions so you can see what
> > happens:
> >
> >
> > EH thread finishes
> > <---------------
> >
> > EH thread begins
> > ---------------->
> >
> >
> > <---------
> > running ---------> recovery
> > | |
> > | | scsi_remove_host() called
> > v <---------- v
> > cancel ----------> recover/cancel
> > | |
> > | | scsi_remove_host finishes visibility removal
> > v v
> > del <------------ recover/del
> >
> > So the EH is allowed to activate in either running or cancel states, but
> > goes through its own state transition eventually coming back to del when
> > it finishes. Once the EH gets into recover/cancel it can never
> > transition back to running.
>
> Why allow cancel -> recover/cancel? Once the device is in the cancel
> state, there isn't anything useful the error handler can accomplish, is
> there? Failed or timed-out commands should simply return an error.
>
> And if you accept that, then what point is there in distinguishing between
> cancel and recover/cancel? As far as I can see, the only significant
> difference is that in recover/cancel the error handler is running (but not
> accomplishing anything). Is this related to 1) below?
Yes, a state machine like I've shown can only be in one state at any
given time. The problem is what happens if the error handler is running
when you try to remove the device. We can reach in and try to stop it,
but under a state model we'd have to wait until the error handler put
the device back to running unless we allow a set of state transitions
that the error handler can go through in parallel with the removal
(which is the model I've shown above).
The idea of allowing the error handler to start up in cancel is that not
every device removal is a forced removal, so you want to permit the
shutdown commands (like sync cache) and consequent error handling on
those commands.
> > It's just nasty on two counts:
> >
> > 1) we have an incorrect bifurcation in the state model and
> > 2) we never actually enforce any of the state transitions.
>
> Can you explain 1) more fully? I don't really understand what you're
> getting at.
Does the explanation above cover this?
> As for 2), what do you mean? In 2.6.13, scsi_device_set_state does not
> change the state if the transition is illegal.
Yes, but we never act on the return value. if the state is illegal, we
shouldn't be taking actions believing we're in that state, so we should
always be checking the returns.
James
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 18:36 ` Alan Stern
@ 2005-09-08 23:59 ` Luben Tuikov
2005-09-09 14:44 ` Alan Stern
2005-09-09 17:08 ` Stefan Richter
0 siblings, 2 replies; 30+ messages in thread
From: Luben Tuikov @ 2005-09-08 23:59 UTC (permalink / raw)
To: Alan Stern; +Cc: SCSI development list
On 09/08/05 14:36, Alan Stern wrote:
> On Thu, 8 Sep 2005, Luben Tuikov wrote:
>
>
>>>No. There are only two reset mechanisms available for USB Mass Storage.
>>
>>I see.
>>
>>
>>>One is a class-specific reset command (which usb-storage issues when asked
>>>to do a device reset),
>>
>>So as far as I can see it sends a reset on the wire to the device?
>
>
> Sort of. It's not a low-level hardware reset, it's rather high-level.
> If the device's firmware is busy doing something else, or is hung, or
> doesn't implement resets correctly, then the reset won't work.
So this is perfect for LU Reset.
>>>and the other is a USB port reset (which
>>>usb-storage issues when asked to do a bus reset).
>>
>>As far as I see this resets the port on the host side and then
>>rediscovers the devices?
>
>
> That's right. (Except there's only one device to rediscover.) This is a
> much lower-level action than the other sort, and is much more likely to
> succeed.
So this is perfect for I_T Nexus Reset.
>>>Well, usb-storage doesn't need to "remove" a failed device. The SCSI core
>>>does a perfectly good job just by setting it off-line. And since there
>>>aren't other targets sharing the bus, that's good enough.
>>
>>Well what happens when I just unplug the device?
>
>
> For a brief time (maybe 1/4 second) all commands will return DID_ERROR
> and resets will return FAILED. Then usbcore will realize that the device
Perfectly ok.
> has been unplugged and will call the usb-storage disconnect method, which
> in turn will call scsi_remove_host.
This is fine. I haven't looked closely at the code, but note that
scsi_remove_host() should absolutely be called last.
>>What code? What reinvention?
>
> scsi_unjam_host plus the things that it calls. Why add a private version
> of all that to usb-storage when it already exists in scsi_error.c?
Because it is not implemented correctly.
Think about this:
EH is function of scsi_host.
You can define YOUR OWN EH! in usb storage, which you control!
So that when you want to remove the host you know what position
you're at. ;-)
>>You _need_ to implement a timeout and eh hook if you want to do this
>>in any sane way.
>
>
> No I don't. There already is a timeout in the SCSI core
> (scmd->eh_timeout); I don't need to add another one.
Eh, you're missing my point completely.
Hopefully one day you can see what I mean.
>>You also need to implement kref via kobject for the devices which you/USB Storage
>>represent to SCSI Core.
>
> Again, I don't need to. The data used by usb-storage belongs to the
> private portion of the scsi_host, so it's already protected by the host's
> kref.
Well then, if your code is so correct, why are all these problems?
>> You also need to get rid of that horrible patchwork
>>of a solution: dev_semaphore. Maybe you can take a look in the SAS code and
>>see how this is all done?
>
> I assume you're referring to the way dev_semaphore is used in the
> bus_reset routine? It's sort of a preventative measure, because the SCSI
> core and the driver core haven't quite settled down yet.
"Settled down" -- you mean, litte design if ever has been done writing this
thing? Or do you mean: "one is waiting for the other to change in certain
ways to make it work"?
> Here's the idea. We want to protect against a race between the error
> handler doing a bus reset and the user doing rmmod usb-storage. With the
> current code, I believe scsi_remove_host does not wait for devices to go
> out of error recovery. Here is what might happen without dev_semaphore:
>
> Error handler thread Rmmod thread
> -------------------- ------------
> eh calls usb-storage's bus_reset
> -> calls usb_stor_port_reset
> -> calls usb_lock_device_for_reset
> -> calls usb_reset_device
> Driver core calls usb-storage's
> remove method
> storage_disconnect calls
> quiesce_and_remove_host
> -> locks & releases dev_semaphore (*)
> -> calls scsi_remove_host
> (doesn't wait for eh)
> -> returns to driver core
How can all this happen if a kref (module count) is upped by one,
due to SCSI Core using usb-storage?
> -> usb_reset_device does
> the port reset
>
> (This picture is over-simplified because the driver core does some locking
> of its own before calling the remove method. Let's not worry about that.)
>
> Now see what has happened. usb-storage's remove method has returned, so
> it has given up all claims to the device. It shouldn't do anything more
> that will affect the device. And yet in the eh thread it's about to do a
> port reset!
Yes, this is because eh should be in USB Storage.
>
> Since in reality the bus_reset routine acquires dev_semaphore, the rmmod
> thread will wait at (*) until the reset has finished. Alternatively, if
OMG!
> scsi_remove_host waited until the device was out of error recovery, then
> we would be okay without using dev_semaphore.
>
> The complication exists inside usb_lock_device_for_reset. That routine
> ends up calling down_trylock and looping with a timeout, because of the
> potential for a complicated deadlock that I have described before.
OMG!
> There's one more thing worth mentioning. Thanks to the resets carried out
> internally by usb-storage, we may decide it's easiest not to implement the
> bus_reset method at all! That would certainly solve all the problems with
> dev_semaphore. :-)
What would solve your problem is implementing your own eh and timer hook.
More so for transports such as USB.
Luben
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 20:15 ` James Bottomley
@ 2005-09-09 0:18 ` Luben Tuikov
2005-09-09 14:16 ` Alan Stern
1 sibling, 0 replies; 30+ messages in thread
From: Luben Tuikov @ 2005-09-09 0:18 UTC (permalink / raw)
To: James Bottomley; +Cc: Alan Stern, SCSI development list
On 09/08/05 16:15, James Bottomley wrote:
> On Thu, 2005-09-08 at 14:58 -0400, Alan Stern wrote:
>
>>On Thu, 8 Sep 2005, James Bottomley wrote:
>>
>>>Actually, no, that's why we have the parallel EH states ... let me put
>>>in the events that trigger state transitions so you can see what
>>>happens:
>>>
>>>
>>> EH thread finishes
>>> <---------------
>>>
>>> EH thread begins
>>> ---------------->
>>>
>>>
>>> <---------
>>> running ---------> recovery
>>> | |
>>> | | scsi_remove_host() called
>>> v <---------- v
>>> cancel ----------> recover/cancel
>>> | |
>>> | | scsi_remove_host finishes visibility removal
>>> v v
>>> del <------------ recover/del
>>>
>>>So the EH is allowed to activate in either running or cancel states, but
>>>goes through its own state transition eventually coming back to del when
>>>it finishes. Once the EH gets into recover/cancel it can never
>>>transition back to running.
>>
>>Why allow cancel -> recover/cancel? Once the device is in the cancel
>>state, there isn't anything useful the error handler can accomplish, is
>>there? Failed or timed-out commands should simply return an error.
>>
>>And if you accept that, then what point is there in distinguishing between
>>cancel and recover/cancel? As far as I can see, the only significant
>>difference is that in recover/cancel the error handler is running (but not
>>accomplishing anything). Is this related to 1) below?
>
>
> Yes, a state machine like I've shown can only be in one state at any
> given time.
And this is fine.
> The problem is what happens if the error handler is running
> when you try to remove the device. We can reach in and try to stop it,
> but under a state model we'd have to wait until the error handler put
> the device back to running unless we allow a set of state transitions
> that the error handler can go through in parallel with the removal
> (which is the model I've shown above).
I'd suggest "waiting" until EH is done. EH is just another user
of the SDS. Thus if the device is physically removed, all tasks
fail and new ones are returned with failed delivery (the SDS tells
you this).
So one state at a time is the way to go.
In effect, a device remove _event_ is queued up, _after_ the
_recover_event_, and executed thereafter, when the state process
of _recover_event_ has finished and the state machine is ready
to transition.
Luben
> The idea of allowing the error handler to start up in cancel is that not
> every device removal is a forced removal, so you want to permit the
> shutdown commands (like sync cache) and consequent error handling on
> those commands.
>
>
>>>It's just nasty on two counts:
>>>
>>>1) we have an incorrect bifurcation in the state model and
>>>2) we never actually enforce any of the state transitions.
>>
>>Can you explain 1) more fully? I don't really understand what you're
>>getting at.
>
>
> Does the explanation above cover this?
>
>
>>As for 2), what do you mean? In 2.6.13, scsi_device_set_state does not
>>change the state if the transition is illegal.
>
>
> Yes, but we never act on the return value. if the state is illegal, we
> shouldn't be taking actions believing we're in that state, so we should
> always be checking the returns.
>
> James
>
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 20:15 ` James Bottomley
2005-09-09 0:18 ` Luben Tuikov
@ 2005-09-09 14:16 ` Alan Stern
2005-09-09 14:44 ` James Bottomley
1 sibling, 1 reply; 30+ messages in thread
From: Alan Stern @ 2005-09-09 14:16 UTC (permalink / raw)
To: James Bottomley; +Cc: SCSI development list
On Thu, 8 Sep 2005, James Bottomley wrote:
> Yes, a state machine like I've shown can only be in one state at any
> given time. The problem is what happens if the error handler is running
> when you try to remove the device. We can reach in and try to stop it,
> but under a state model we'd have to wait until the error handler put
> the device back to running unless we allow a set of state transitions
> that the error handler can go through in parallel with the removal
> (which is the model I've shown above).
>
> The idea of allowing the error handler to start up in cancel is that not
> every device removal is a forced removal, so you want to permit the
> shutdown commands (like sync cache) and consequent error handling on
> those commands.
I see. You must be making an unstated assumption, something along the
lines of "If the error handler is running then the host is in a *RECOVERY
state." Given that, there definitely is a need for a separate
CANCEL_RECOVERY and DEL_RECOVERY.
> > As for 2), what do you mean? In 2.6.13, scsi_device_set_state does not
> > change the state if the transition is illegal.
>
> Yes, but we never act on the return value. if the state is illegal, we
> shouldn't be taking actions believing we're in that state, so we should
> always be checking the returns.
Hmmm, well looking through the patch you posted yesterday, there are a few
problems. If the ->CANCEL transition fails, scsi_remove_host then tries
->CANCEL_RECOVERY. But the failed transition still writes a error message
to the log, even though it's not really an error.
Also, you've got a race between scsi_remove_host doing ->CANCEL_RECOVERY
and the error handler doing ->RUNNING. If both happen at the same time,
you can end up in the wrong state. To make this work, the state
transitions should only be made under protection of the host's spinlock.
And to avoid the error messages, the choice of next state should be made
depending on the current state (like, if the current state is RECOVERY
then go to CANCEL_RECOVERY, otherwise go to CANCEL).
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 23:59 ` Luben Tuikov
@ 2005-09-09 14:44 ` Alan Stern
2005-09-09 17:08 ` Stefan Richter
1 sibling, 0 replies; 30+ messages in thread
From: Alan Stern @ 2005-09-09 14:44 UTC (permalink / raw)
To: Luben Tuikov; +Cc: SCSI development list
On Thu, 8 Sep 2005, Luben Tuikov wrote:
> >>So as far as I can see it sends a reset on the wire to the device?
> >
> >
> > Sort of. It's not a low-level hardware reset, it's rather high-level.
> > If the device's firmware is busy doing something else, or is hung, or
> > doesn't implement resets correctly, then the reset won't work.
>
> So this is perfect for LU Reset.
>
> >>>and the other is a USB port reset (which
> >>>usb-storage issues when asked to do a bus reset).
> >>
> >>As far as I see this resets the port on the host side and then
> >>rediscovers the devices?
> >
> >
> > That's right. (Except there's only one device to rediscover.) This is a
> > much lower-level action than the other sort, and is much more likely to
> > succeed.
>
> So this is perfect for I_T Nexus Reset.
Forgive me; I haven't read the SAM document and I'm not familiar with all
the strange SCSI terms even in the regular SCSI spec. You're agreeing
that usb-storage uses the appropriate sort of reset operations at the
correct spots, right?
> >>What code? What reinvention?
> >
> > scsi_unjam_host plus the things that it calls. Why add a private version
> > of all that to usb-storage when it already exists in scsi_error.c?
>
> Because it is not implemented correctly.
Are you saying the scsi_unjam_host is wrong ("implemented incorrectly")?
Can you point out any particular errors in it, or send in a patch to fix
the implementation?
> Think about this:
> EH is function of scsi_host.
> You can define YOUR OWN EH! in usb storage, which you control!
> So that when you want to remove the host you know what position
> you're at. ;-)
Well yes, that's true. But doing it will add extra code to the
usb-storage driver without making it better or improving its behavior in
any way.
> Eh, you're missing my point completely.
> Hopefully one day you can see what I mean.
And maybe you'll see what I mean. (I really _am_ trying to understand,
but it's always hard to communicate subtle meanings over email.)
> >>You also need to implement kref via kobject for the devices which you/USB Storage
> >>represent to SCSI Core.
> >
> > Again, I don't need to. The data used by usb-storage belongs to the
> > private portion of the scsi_host, so it's already protected by the host's
> > kref.
>
> Well then, if your code is so correct, why are all these problems?
All what problems? There aren't any problems in usb-storage. There's an
awkward bit of code in one routine (usb_lock_device_for_reset), but that's
inevitable because of the layering violation implicit in its job.
> >> You also need to get rid of that horrible patchwork
> >>of a solution: dev_semaphore. Maybe you can take a look in the SAS code and
> >>see how this is all done?
> >
> > I assume you're referring to the way dev_semaphore is used in the
> > bus_reset routine? It's sort of a preventative measure, because the SCSI
> > core and the driver core haven't quite settled down yet.
>
> "Settled down" -- you mean, litte design if ever has been done writing this
> thing? Or do you mean: "one is waiting for the other to change in certain
> ways to make it work"?
What I mean is: I wasn't sure whether scsi_remove_host would wait for the
error handler to finish. Until recently it would. Now with Mike's
changes it place, it doesn't. With the changes you've been proposing,
once again it would.
Since I couldn't depend on any particular behavior, I had to write the
bus_reset routine in usb-storage so that it would work either way. That
meant it needed to acquire the dev_semaphore lock.
After thinking it over last night, I decided that the details of
scsi_remove_host's behavior really should remain private to the SCSI core.
So far as I'm concerned, it's okay if it doesn't wait for the error
handler to finish and it's okay if it does. The one _crucial_
requirement is this: It must synchronize with the error handler. That is,
if the error handler is executing a command or a reset at the time
scsi_remove_host is called, then scsi_remove_host must not return until
the command or reset has completed. How long it chooses to wait after
that is unimportant.
If scsi_remove_host would make that guarantee, then dev_semaphore could be
removed from usb-storage's bus_reset. (It wouldn't hurt to add a comment
to scsi_remove_host, documenting the guarantee so that it doesn't get
changed in the future.)
> > Here's the idea. We want to protect against a race between the error
> > handler doing a bus reset and the user doing rmmod usb-storage. With the
> > current code, I believe scsi_remove_host does not wait for devices to go
> > out of error recovery. Here is what might happen without dev_semaphore:
> >
> > Error handler thread Rmmod thread
> > -------------------- ------------
> > eh calls usb-storage's bus_reset
> > -> calls usb_stor_port_reset
> > -> calls usb_lock_device_for_reset
> > -> calls usb_reset_device
> > Driver core calls usb-storage's
> > remove method
> > storage_disconnect calls
> > quiesce_and_remove_host
> > -> locks & releases dev_semaphore (*)
> > -> calls scsi_remove_host
> > (doesn't wait for eh)
> > -> returns to driver core
>
> How can all this happen if a kref (module count) is upped by one,
> due to SCSI Core using usb-storage?
I do have a blind spot for that, don't I? All right, this can't happen by
way of rmmod. But it can happen if the user unbinds usb-storage via
sysfs.
> > -> usb_reset_device does
> > the port reset
> >
> > (This picture is over-simplified because the driver core does some locking
> > of its own before calling the remove method. Let's not worry about that.)
> >
> > Now see what has happened. usb-storage's remove method has returned, so
> > it has given up all claims to the device. It shouldn't do anything more
> > that will affect the device. And yet in the eh thread it's about to do a
> > port reset!
>
> Yes, this is because eh should be in USB Storage.
No, that wouldn't make any difference! Particularly since the part that
does the port reset already _is_ in usb-storage.
What matters is whether or not scsi_remove_host waits for the reset to
complete. Adding a private error handler to usb-storage won't affect
that.
> What would solve your problem is implementing your own eh and timer hook.
> More so for transports such as USB.
But there isn't a problem to solve! Everything works as it is.
The only part one might object to is the awkward code in
usb_lock_device_for_reset. However, that code will have to remain awkward
no matter what. Even with a private error handler for usb-storage that
will still be true.
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-09 14:16 ` Alan Stern
@ 2005-09-09 14:44 ` James Bottomley
2005-09-09 15:16 ` Alan Stern
0 siblings, 1 reply; 30+ messages in thread
From: James Bottomley @ 2005-09-09 14:44 UTC (permalink / raw)
To: Alan Stern; +Cc: SCSI development list
On Fri, 2005-09-09 at 10:16 -0400, Alan Stern wrote:
> I see. You must be making an unstated assumption, something along the
> lines of "If the error handler is running then the host is in a *RECOVERY
> state." Given that, there definitely is a need for a separate
> CANCEL_RECOVERY and DEL_RECOVERY.
Sorry, yes ... it wasn't stated because I thought it was apparent in the
diagram.
> Hmmm, well looking through the patch you posted yesterday, there are a few
> problems. If the ->CANCEL transition fails, scsi_remove_host then tries
> ->CANCEL_RECOVERY. But the failed transition still writes a error message
> to the log, even though it's not really an error.
Well ... the log is just that, a log. It's not active unless someone
asks to see it and all its entries don't necessarily represent errors.
However, we can probably tone down the logging to KERN_NOTICE.
> Also, you've got a race between scsi_remove_host doing ->CANCEL_RECOVERY
> and the error handler doing ->RUNNING. If both happen at the same time,
> you can end up in the wrong state. To make this work, the state
> transitions should only be made under protection of the host's spinlock.
> And to avoid the error messages, the choice of next state should be made
> depending on the current state (like, if the current state is RECOVERY
> then go to CANCEL_RECOVERY, otherwise go to CANCEL).
Yes ... we definitely use the lock for device transitions. Since all of
this is done with user context, a semaphore would be the most
appropriate, but since we already have a host lock, it's probably better
to use it.
So which way do you want to go? Either we wait in recovery for the
error handler to finish and transition the host state to RUNNING or we
introduce the parallel states for the error handler.
James
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-09 14:44 ` James Bottomley
@ 2005-09-09 15:16 ` Alan Stern
2005-09-09 15:37 ` James Bottomley
0 siblings, 1 reply; 30+ messages in thread
From: Alan Stern @ 2005-09-09 15:16 UTC (permalink / raw)
To: James Bottomley; +Cc: SCSI development list
On Fri, 9 Sep 2005, James Bottomley wrote:
> So which way do you want to go? Either we wait in recovery for the
> error handler to finish and transition the host state to RUNNING or we
> introduce the parallel states for the error handler.
For usb-storage it won't make any difference on the whole, as far as I can
see. The important thing is that scsi_remove_host needs to synchronize
somehow with the error handler. Waiting for the host state to go back to
RUNNING would be valid. Introducing the parallel states would mean
waiting for the host to go from CANCEL_RECOVERY to CANCEL, right?
Either way should work. Would there be more of a difference for drivers
that allow non-forced removal? And without the parallel states, would you
worry about the possibility of starving scsi_remove_host (every time it
tries to go from RUNNING to CANCEL, the error handler gets there first and
changes the state to RECOVERY)?
In the absence of other considerations, my vote goes for adding the least
amount of additional code.
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-09 15:16 ` Alan Stern
@ 2005-09-09 15:37 ` James Bottomley
2005-09-09 16:17 ` Alan Stern
0 siblings, 1 reply; 30+ messages in thread
From: James Bottomley @ 2005-09-09 15:37 UTC (permalink / raw)
To: Alan Stern; +Cc: SCSI development list
On Fri, 2005-09-09 at 11:16 -0400, Alan Stern wrote:
> > So which way do you want to go? Either we wait in recovery for the
> > error handler to finish and transition the host state to RUNNING or we
> > introduce the parallel states for the error handler.
>
> For usb-storage it won't make any difference on the whole, as far as I can
> see. The important thing is that scsi_remove_host needs to synchronize
> somehow with the error handler. Waiting for the host state to go back to
> RUNNING would be valid. Introducing the parallel states would mean
> waiting for the host to go from CANCEL_RECOVERY to CANCEL, right?
Actually, no, there would be no waiting. Once the host gets to DEL or
CANCEL_DEL, then all the devices should be in DEL and the mid-layer will
begin rejecting any commands the error handler makes. So it can
continue until it's exhausted. It keeps a reference to the devices it
needs to operate, so they'll be finally freed when it stops.
Since the eh has references, module removal would have to wait until it
had finished, but everything else can proceed without it.
> Either way should work. Would there be more of a difference for drivers
> that allow non-forced removal? And without the parallel states, would you
> worry about the possibility of starving scsi_remove_host (every time it
> tries to go from RUNNING to CANCEL, the error handler gets there first and
> changes the state to RECOVERY)?
Not really. Starting the eh is quite a long and involved process, so
the chances of it restarting before scsi_remove_host gets scheduled is
small (not impossible, but small).
> In the absence of other considerations, my vote goes for adding the least
> amount of additional code.
Actually, they're both about the same amount of code.
James
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-09 15:37 ` James Bottomley
@ 2005-09-09 16:17 ` Alan Stern
2005-09-09 16:47 ` Mike Anderson
0 siblings, 1 reply; 30+ messages in thread
From: Alan Stern @ 2005-09-09 16:17 UTC (permalink / raw)
To: James Bottomley; +Cc: SCSI development list
On Fri, 9 Sep 2005, James Bottomley wrote:
> On Fri, 2005-09-09 at 11:16 -0400, Alan Stern wrote:
> > > So which way do you want to go? Either we wait in recovery for the
> > > error handler to finish and transition the host state to RUNNING or we
> > > introduce the parallel states for the error handler.
> >
> > For usb-storage it won't make any difference on the whole, as far as I can
> > see. The important thing is that scsi_remove_host needs to synchronize
> > somehow with the error handler. Waiting for the host state to go back to
> > RUNNING would be valid. Introducing the parallel states would mean
> > waiting for the host to go from CANCEL_RECOVERY to CANCEL, right?
>
> Actually, no, there would be no waiting.
You mean that there would be no waiting if the parallel states are used --
without them we have to wait for the state to go to RUNNING.
> Once the host gets to DEL or
> CANCEL_DEL, then all the devices should be in DEL and the mid-layer will
> begin rejecting any commands the error handler makes. So it can
> continue until it's exhausted. It keeps a reference to the devices it
> needs to operate, so they'll be finally freed when it stops.
>
> Since the eh has references, module removal would have to wait until it
> had finished, but everything else can proceed without it.
Then what about making scsi_remove_host wait for the current command or
reset to complete? If you don't wait for the state to change from
CANCEL_RECOVERY to CANCEL before moving to DEL then scsi_remove_host might
return too early, while the error handler is still using the host. (On
the plus side, if scsi_remove_host always waits for the state to be CANCEL
before making the transition to DEL, then there's no need for DEL_RECOVERY
at all. The error handler can simply refuse to start when the state is
already DEL.)
The conundrum I'm facing is how to make sure that when scsi_remove_host
returns, the mid-layer is no longer sending anything to the host. Sure,
no new commands will be issued once the state is set to DEL (or
DEL_RECOVERY). But what about commands/resets that were already in
progress at that time? (Especially if they were issued before
scsi_remove_host was called.) The routine shouldn't return until they
have completed. This applies to commands coming from either the
high-level driver or from the error handler.
I don't know what the best approach is. The issue may be unrelated to
whether you use the parallel states; if it is, then I don't care whether
the parallel states are used or not.
Alan Stern
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-09 16:17 ` Alan Stern
@ 2005-09-09 16:47 ` Mike Anderson
0 siblings, 0 replies; 30+ messages in thread
From: Mike Anderson @ 2005-09-09 16:47 UTC (permalink / raw)
To: Alan Stern; +Cc: James Bottomley, SCSI development list
Alan Stern <stern@rowland.harvard.edu> wrote:
> The conundrum I'm facing is how to make sure that when scsi_remove_host
> returns, the mid-layer is no longer sending anything to the host. Sure,
> no new commands will be issued once the state is set to DEL (or
> DEL_RECOVERY). But what about commands/resets that were already in
> progress at that time? (Especially if they were issued before
> scsi_remove_host was called.) The routine shouldn't return until they
> have completed. This applies to commands coming from either the
> high-level driver or from the error handler.
>
I do not understand why we would not want to wait on the eh thread and
shut it down before returning from scsi_remove_host. In the end we are
really going to wait on this action anyways.
Currently scsi_send_eh_cmnd does not go through scsi_dispatch_cmd and eh_*
calls have no checks besides SUCCESS and FAILED. The scsi_send_eh_cmnd
should be updated to follow the same model that scsi_dispatch_cmd uses and
the eh_* calls good be improved if we allowed another return code that the
LLDDs could use to indicate that no device was present. These would only
be an optimization to reduce the wait time on the eh thread and if not
implemented would just increase the wait time.
-andmike
--
Michael Anderson
andmike@us.ibm.com
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-08 23:59 ` Luben Tuikov
2005-09-09 14:44 ` Alan Stern
@ 2005-09-09 17:08 ` Stefan Richter
2005-09-09 17:15 ` Luben Tuikov
1 sibling, 1 reply; 30+ messages in thread
From: Stefan Richter @ 2005-09-09 17:08 UTC (permalink / raw)
To: SCSI development list; +Cc: Luben Tuikov, Alan Stern
Luben Tuikov wrote:
> Think about this:
> EH is function of scsi_host.
The host does not use the EH. The EH uses the host.
> You can define YOUR OWN EH! in usb storage, which you control!
There are a few hotpluggable low-level providers besides usb-storage.
--
Stefan Richter
-=====-=-=-= =--= -=--=
http://arcgraph.de/sr/
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] SCSI scanning and removal fixes
2005-09-09 17:08 ` Stefan Richter
@ 2005-09-09 17:15 ` Luben Tuikov
0 siblings, 0 replies; 30+ messages in thread
From: Luben Tuikov @ 2005-09-09 17:15 UTC (permalink / raw)
To: Stefan Richter; +Cc: SCSI development list, Alan Stern
On 09/09/05 13:08, Stefan Richter wrote:
> Luben Tuikov wrote:
>
>>Think about this:
>> EH is function of scsi_host.
>
>
> The host does not use the EH. The EH uses the host.
That's exactly what my statement above means:
F(scsi_host) = EH
>> You can define YOUR OWN EH! in usb storage, which you control!
>
>
> There are a few hotpluggable low-level providers besides usb-storage.
Ok.
Luben
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2005-09-09 17:15 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-07-26 14:12 [PATCH 1/5] SCSI scanning and removal fixes Alan Stern
2005-09-07 15:16 ` James Bottomley
2005-09-07 18:27 ` Alan Stern
2005-09-07 18:37 ` Luben Tuikov
2005-09-07 18:42 ` Luben Tuikov
2005-09-07 19:31 ` Alan Stern
2005-09-07 20:00 ` Mike Anderson
2005-09-07 20:43 ` Luben Tuikov
2005-09-07 21:34 ` Stefan Richter
2005-09-08 15:19 ` Alan Stern
2005-09-08 16:07 ` Luben Tuikov
2005-09-08 18:36 ` Alan Stern
2005-09-08 23:59 ` Luben Tuikov
2005-09-09 14:44 ` Alan Stern
2005-09-09 17:08 ` Stefan Richter
2005-09-09 17:15 ` Luben Tuikov
2005-09-07 19:58 ` James Bottomley
2005-09-07 22:05 ` James Bottomley
2005-09-08 15:59 ` Alan Stern
2005-09-08 16:15 ` James Bottomley
2005-09-08 18:58 ` Alan Stern
2005-09-08 20:15 ` James Bottomley
2005-09-09 0:18 ` Luben Tuikov
2005-09-09 14:16 ` Alan Stern
2005-09-09 14:44 ` James Bottomley
2005-09-09 15:16 ` Alan Stern
2005-09-09 15:37 ` James Bottomley
2005-09-09 16:17 ` Alan Stern
2005-09-09 16:47 ` Mike Anderson
2005-09-08 16:08 ` Alan Stern
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).