diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4acf5c284c2e..0e52ff035135 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -479,15 +479,26 @@ void scsi_requeue_run_queue(struct work_struct *work) | |||
479 | */ | 479 | */ |
480 | static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) | 480 | static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) |
481 | { | 481 | { |
482 | struct scsi_device *sdev = cmd->device; | ||
482 | struct request *req = cmd->request; | 483 | struct request *req = cmd->request; |
483 | unsigned long flags; | 484 | unsigned long flags; |
484 | 485 | ||
486 | /* | ||
487 | * We need to hold a reference on the device to avoid the queue being | ||
488 | * killed after the unlock and before scsi_run_queue is invoked which | ||
489 | * may happen because scsi_unprep_request() puts the command which | ||
490 | * releases its reference on the device. | ||
491 | */ | ||
492 | get_device(&sdev->sdev_gendev); | ||
493 | |||
485 | spin_lock_irqsave(q->queue_lock, flags); | 494 | spin_lock_irqsave(q->queue_lock, flags); |
486 | scsi_unprep_request(req); | 495 | scsi_unprep_request(req); |
487 | blk_requeue_request(q, req); | 496 | blk_requeue_request(q, req); |
488 | spin_unlock_irqrestore(q->queue_lock, flags); | 497 | spin_unlock_irqrestore(q->queue_lock, flags); |
489 | 498 | ||
490 | scsi_run_queue(q); | 499 | scsi_run_queue(q); |
500 | |||
501 | put_device(&sdev->sdev_gendev); | ||
491 | } | 502 | } |
492 | 503 | ||
493 | void scsi_next_command(struct scsi_cmnd *cmd) | 504 | void scsi_next_command(struct scsi_cmnd *cmd) |