aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2012-06-29 11:34:26 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-07-20 03:58:40 -0400
commit940f5d47e2f2e1fa00443921a0abf4822335b54d (patch)
treee653ab9f2313c1fec3ab73433abecf5bda3003c3
parent67bd94130015c507011af37858989b199c52e1de (diff)
[SCSI] Avoid dangling pointer in scsi_requeue_command()
When we call scsi_unprep_request() the command associated with the request gets destroyed and therefore drops its reference on the device. If this was the only reference, the device may get released and we end up with a NULL pointer deref when we call blk_requeue_request. Reported-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Reviewed-by: Tejun Heo <tj@kernel.org> Cc: <stable@kernel.org> [jejb: enhance commend and add commit log for stable] Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/scsi_lib.c11
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 */
480static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) 480static 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
493void scsi_next_command(struct scsi_cmnd *cmd) 504void scsi_next_command(struct scsi_cmnd *cmd)