staging: hv: Gracefully handle SCSI resets - RESEND
Subsystems (2)
PATCH 5/5 staging: hv: Gracefully handle SCSI resets - RESEND
(Send from a linux machine, not routed through exchange)
If we get a SCSI host bus reset we now gracefully handle it, and we take the device offline. This before sometimes caused hangs.
--- drivers/staging/hv/storvsc.c | 36 +++++++++++++++++++++++++++++++++++- 1 files changed, 35 insertions(+), 1 deletions(-)
drivers/staging/hv/storvsc.c +35 -1
@@ -48,7 +48,9 @@ struct storvsc_device {/* 0 indicates the device is being destroyed */ atomic_t RefCount; - + +int reset; +spinlock_t lock;atomic_t NumOutstandingRequests;/*
@@ -93,6 +95,9 @@ static inline struct storvsc_device *AllocStorDevice(struct hv_device *Device)atomic_cmpxchg (&storDevice->RefCount,0 ,2 ); storDevice->Device = Device; + storDevice->reset =0 ; +spin_lock_init (&storDevice->lock); + Device->Extension = storDevice;return storDevice;
@@ -101,6 +106,7 @@ static inline struct storvsc_device *AllocStorDevice(struct hv_device *Device)static inline void FreeStorDevice (struct storvsc_device *Device) {/* ASSERT(atomic_read(&Device->RefCount) == 0); */ +/*kfree(Device->lock);*/ kfree (Device); }
@@ -108,13 +114,24 @@ static inline void FreeStorDevice(struct storvsc_device *Device)static inline struct storvsc_device *GetStorDevice (struct hv_device *Device) {struct storvsc_device *storDevice; +unsigned long flags; storDevice = (struct storvsc_device *)Device->Extension; + +spin_lock_irqsave (&storDevice->lock, flags); + +if (storDevice->reset ==1 ) { +spin_unlock_irqrestore (&storDevice->lock, flags); +return NULL ; + } +if (storDevice &&atomic_read (&storDevice->RefCount) >1 )atomic_inc (&storDevice->RefCount);else storDevice =NULL ; +spin_unlock_irqrestore (&storDevice->lock, flags); +return storDevice; }
@@ -122,13 +139,19 @@ static inline struct storvsc_device *GetStorDevice(struct hv_device *Device)static inline struct storvsc_device *MustGetStorDevice (struct hv_device *Device) {struct storvsc_device *storDevice; +unsigned long flags; storDevice = (struct storvsc_device *)Device->Extension; + +spin_lock_irqsave (&storDevice->lock, flags); +if (storDevice &&atomic_read (&storDevice->RefCount))atomic_inc (&storDevice->RefCount);else storDevice =NULL ; +spin_unlock_irqrestore (&storDevice->lock, flags); +return storDevice; }
@@ -614,6 +637,7 @@ int StorVscOnHostReset(struct hv_device *Device)struct storvsc_device *storDevice;struct storvsc_request_extension *request;struct vstor_packet *vstorPacket; +unsigned long flags;int ret;DPRINT_INFO (STORVSC ,"resetting host adapter..." );
@@ -625,6 +649,16 @@ int StorVscOnHostReset(struct hv_device *Device)return -1 ; } +spin_lock_irqsave (&storDevice->lock, flags); + storDevice->reset =1 ; +spin_unlock_irqrestore (&storDevice->lock, flags); + +/* +* Wait for traffic in transit to complete +*/ +while (atomic_read (&storDevice->NumOutstandingRequests)) +udelay (1000 ); + request = &storDevice->ResetRequest; vstorPacket = &request->VStorPacket;
Signature · 1 line
1.6.0.2
Quoted 4 lines · Hank Janssen
If we get a SCSI host bus reset we now gracefully handle it, and we take the device offline. This before sometimes caused hangs.
--- drivers/staging/hv/storvsc.c | 36 +++++++++++++++++++++++++++++++++++-
[]
drivers/staging/hv/storvsc.c int StorVscOnHostReset(struct hv_device *Device) · line 661
Quoted 6 lines
drivers/staging/hv/storvsc.c +6
-0+/* +* Wait for traffic in transit to complete +*/ +while (atomic_read (&storDevice->NumOutstandingRequests)) +udelay (1000 ); +
Is it useful to have a maximum check or timeout?
Maybe use usleep_range?
Quoted 6 lines · Joe Perches
Quoted 4 lines · Hank Janssen
If we get a SCSI host bus reset we now gracefully handle it, and we take the device offline. This before sometimes caused hangs.
--- drivers/staging/hv/storvsc.c | 36 +++++++++++++++++++++++++++++++++++-[]
Quoted 9 lines
drivers/staging/hv/storvsc.c int StorVscOnHostReset(struct hv_device *Device) · line 661
Quoted 6 lines
drivers/staging/hv/storvsc.c +6
-0+/* +* Wait for traffic in transit to complete +*/ +while (atomic_read (&storDevice->NumOutstandingRequests)) +udelay (1000 ); +Is it useful to have a maximum check or timeout?
Maybe useusleep_range?
Yeah, that's not good, you need to have some way to get out of here in case something bad happens and that number never goes down.
Why not just use a completion function instead of a busy loop?
thanks,
greg k-h