Commit 255ee932 authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen

scsi: Make __scsi_remove_device go straight from BLOCKED to DEL

If a device is blocked, make __scsi_remove_device() cause it to
transition to the DEL state. This means that all the commands issued in
.shutdown() will error in the mid-layer, thus making the removal proceed
without being stopped.

This patch is a slightly modified version of a patch from James
Bottomley. This patch avoids that the following lockup occurs:

Call Trace:
 schedule+0x35/0x80
 schedule_timeout+0x237/0x2d0
 io_schedule_timeout+0xa6/0x110
 wait_for_completion_io+0xa3/0x110
 blk_execute_rq+0xdf/0x120
 scsi_execute+0xce/0x150 [scsi_mod]
 scsi_execute_req_flags+0x8f/0xf0 [scsi_mod]
 sd_sync_cache+0xa9/0x190 [sd_mod]
 sd_shutdown+0x6a/0x100 [sd_mod]
 sd_remove+0x64/0xc0 [sd_mod]
 __device_release_driver+0x8d/0x120
 device_release_driver+0x1e/0x30
 bus_remove_device+0xf9/0x170
 device_del+0x127/0x240
 __scsi_remove_device+0xc1/0xd0 [scsi_mod]
 scsi_forget_host+0x57/0x60 [scsi_mod]
 scsi_remove_host+0x72/0x110 [scsi_mod]
 srp_remove_work+0x8b/0x200 [ib_srp]
Reported-by: default avatarIsrael Rukshin <israelr@mellanox.com>
Signed-off-by: default avatarBart Van Assche <bart.vanassche@sandisk.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Israel Rukshin <israelr@mellanox.com>
Cc: Max Gurtovoy <maxg@mellanox.com>
Cc: Benjamin Block <bblock@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 66483a4a
...@@ -2625,7 +2625,6 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) ...@@ -2625,7 +2625,6 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
case SDEV_QUIESCE: case SDEV_QUIESCE:
case SDEV_OFFLINE: case SDEV_OFFLINE:
case SDEV_TRANSPORT_OFFLINE: case SDEV_TRANSPORT_OFFLINE:
case SDEV_BLOCK:
break; break;
default: default:
goto illegal; goto illegal;
...@@ -2639,6 +2638,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) ...@@ -2639,6 +2638,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
case SDEV_OFFLINE: case SDEV_OFFLINE:
case SDEV_TRANSPORT_OFFLINE: case SDEV_TRANSPORT_OFFLINE:
case SDEV_CANCEL: case SDEV_CANCEL:
case SDEV_BLOCK:
case SDEV_CREATED_BLOCK: case SDEV_CREATED_BLOCK:
break; break;
default: default:
......
...@@ -1290,7 +1290,17 @@ void __scsi_remove_device(struct scsi_device *sdev) ...@@ -1290,7 +1290,17 @@ void __scsi_remove_device(struct scsi_device *sdev)
* wait until it has finished before changing the device state. * wait until it has finished before changing the device state.
*/ */
mutex_lock(&sdev->state_mutex); mutex_lock(&sdev->state_mutex);
/*
* If blocked, we go straight to DEL and restart the queue so
* any commands issued during driver shutdown (like sync
* cache) are errored immediately.
*/
res = scsi_device_set_state(sdev, SDEV_CANCEL); res = scsi_device_set_state(sdev, SDEV_CANCEL);
if (res != 0) {
res = scsi_device_set_state(sdev, SDEV_DEL);
if (res == 0)
scsi_start_queue(sdev);
}
mutex_unlock(&sdev->state_mutex); mutex_unlock(&sdev->state_mutex);
if (res != 0) if (res != 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment