[kernel/f16] fix scsi_dispatch oops.

Dave Jones davej at fedoraproject.org
Sat Jul 30 02:50:14 UTC 2011


commit 12fe727f0d1c384202dbd24d4a5f7f948c555f06
Author: Dave Jones <davej at redhat.com>
Date:   Fri Jul 29 22:49:51 2011 -0400

    fix scsi_dispatch oops.

 fix-scsi_dispatch_cmd.patch |   68 +++++++++++++++++++++++++++++++++++++++++++
 kernel.spec                 |    7 ++++
 2 files changed, 75 insertions(+), 0 deletions(-)
---
diff --git a/fix-scsi_dispatch_cmd.patch b/fix-scsi_dispatch_cmd.patch
new file mode 100644
index 0000000..3976791
--- /dev/null
+++ b/fix-scsi_dispatch_cmd.patch
@@ -0,0 +1,68 @@
+commit bfe159a51203c15d23cb3158fffdc25ec4b4dda1
+Author: James Bottomley <James.Bottomley at HansenPartnership.com>
+Date:   Thu Jul 7 15:45:40 2011 -0500
+
+    [SCSI] fix crash in scsi_dispatch_cmd()
+    
+    USB surprise removal of sr is triggering an oops in
+    scsi_dispatch_command().  What seems to be happening is that USB is
+    hanging on to a queue reference until the last close of the upper
+    device, so the crash is caused by surprise remove of a mounted CD
+    followed by attempted unmount.
+    
+    The problem is that USB doesn't issue its final commands as part of
+    the SCSI teardown path, but on last close when the block queue is long
+    gone.  The long term fix is probably to make sr do the teardown in the
+    same way as sd (so remove all the lower bits on ejection, but keep the
+    upper disk alive until last close of user space).  However, the
+    current oops can be simply fixed by not allowing any commands to be
+    sent to a dead queue.
+    
+    Cc: stable at kernel.org
+    Signed-off-by: James Bottomley <JBottomley at Parallels.com>
+
+diff --git a/block/blk-core.c b/block/blk-core.c
+index d2f8f40..1d49e1c 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -839,6 +839,9 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask)
+ {
+ 	struct request *rq;
+ 
++	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
++		return NULL;
++
+ 	BUG_ON(rw != READ && rw != WRITE);
+ 
+ 	spin_lock_irq(q->queue_lock);
+diff --git a/block/blk-exec.c b/block/blk-exec.c
+index 8a0e7ec..a1ebceb 100644
+--- a/block/blk-exec.c
++++ b/block/blk-exec.c
+@@ -50,6 +50,13 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
+ {
+ 	int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+ 
++	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
++		rq->errors = -ENXIO;
++		if (rq->end_io)
++			rq->end_io(rq, rq->errors);
++		return;
++	}
++
+ 	rq->rq_disk = bd_disk;
+ 	rq->end_io = done;
+ 	WARN_ON(irqs_disabled());
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index ec1803a..28d9c9d 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -213,6 +213,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+ 	int ret = DRIVER_ERROR << 24;
+ 
+ 	req = blk_get_request(sdev->request_queue, write, __GFP_WAIT);
++	if (!req)
++		return ret;
+ 
+ 	if (bufflen &&	blk_rq_map_kern(sdev->request_queue, req,
+ 					buffer, bufflen, __GFP_WAIT))
diff --git a/kernel.spec b/kernel.spec
index 4c3c419..003a6a0 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -695,6 +695,8 @@ Patch12205: runtime_pm_fixups.patch
 
 Patch12303: dmar-disable-when-ricoh-multifunction.patch
 
+Patch13000: fix-scsi_dispatch_cmd.patch
+
 Patch20000: utrace.patch
 
 %endif
@@ -1277,6 +1279,8 @@ ApplyPatch udlfb-bind-framebuffer-to-interface.patch
 # rhbz#605888
 ApplyPatch dmar-disable-when-ricoh-multifunction.patch
 
+ApplyPatch fix-scsi_dispatch_cmd.patch
+
 # utrace.
 ApplyPatch utrace.patch
 
@@ -1889,6 +1893,9 @@ fi
 # and build.
 
 %changelog
+* Fri Jul 29 2011 Dave Jones <davej at redhat.com>
+- Fix scsi_dispatch_cmd oops (USB eject problems, etc).
+
 * Thu Jul 28 2011 Dave Jones <davej at redhat.com>
 - module-init-tools needs to be a prereq, not a conflict.
 


More information about the scm-commits mailing list