Commit 5c10e63c943b4c67561ddc6bf61e01d4141f881f
Committed by
James Bottomley
1 parent
b0d428adeb
[SCSI] limit state transitions in scsi_internal_device_unblock
scsi timeout on two or more devices may cause extremely long execution time for user applications because SDEV_OFFLINE state is changed to SDEV_RUNNING state during scsi error recovery procedures triggered by a bus reset or a host reset of scsi LLD, and scsi timeout can happens on the same devices many times. This happens because scsi_internal_device_unblock() changes device's state to SDEV_RUNNING even if a device in other states than SDEV_BLOCK, while the following two transitions are required in this function. SDEV_BLOCK -> SDEV_RUNNING SDEV_CREATED_BLOCK -> SDEV_CREATED Otherwise, it returns -EINVAL. Signed-off-by: Takahiro Yasui <tyasui@redhat.com> [matthew@wil.cx: supplied rewritten base for patch] Signed-off-by: Matthew Wilcox <matthew@wil.cx> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Showing 1 changed file with 6 additions and 8 deletions Side-by-side Diff
drivers/scsi/scsi_lib.c
... | ... | @@ -2441,20 +2441,18 @@ |
2441 | 2441 | scsi_internal_device_unblock(struct scsi_device *sdev) |
2442 | 2442 | { |
2443 | 2443 | struct request_queue *q = sdev->request_queue; |
2444 | - int err; | |
2445 | 2444 | unsigned long flags; |
2446 | 2445 | |
2447 | 2446 | /* |
2448 | 2447 | * Try to transition the scsi device to SDEV_RUNNING |
2449 | 2448 | * and goose the device queue if successful. |
2450 | 2449 | */ |
2451 | - err = scsi_device_set_state(sdev, SDEV_RUNNING); | |
2452 | - if (err) { | |
2453 | - err = scsi_device_set_state(sdev, SDEV_CREATED); | |
2454 | - | |
2455 | - if (err) | |
2456 | - return err; | |
2457 | - } | |
2450 | + if (sdev->sdev_state == SDEV_BLOCK) | |
2451 | + sdev->sdev_state = SDEV_RUNNING; | |
2452 | + else if (sdev->sdev_state == SDEV_CREATED_BLOCK) | |
2453 | + sdev->sdev_state = SDEV_CREATED; | |
2454 | + else | |
2455 | + return -EINVAL; | |
2458 | 2456 | |
2459 | 2457 | spin_lock_irqsave(q->queue_lock, flags); |
2460 | 2458 | blk_start_queue(q); |