From 3acc7b100d8a7c504374cb81ddc4d042cdbb5bf1 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Jul 2011 16:47:47 -0400 Subject: [PATCH] Fix the USB eject problem for real. --- fix-scsi_dispatch_cmd.patch | 68 +++++++++++++++++++++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 75 insertions(+) create mode 100644 fix-scsi_dispatch_cmd.patch diff --git a/fix-scsi_dispatch_cmd.patch b/fix-scsi_dispatch_cmd.patch new file mode 100644 index 000000000..3976791ca --- /dev/null +++ b/fix-scsi_dispatch_cmd.patch @@ -0,0 +1,68 @@ +commit bfe159a51203c15d23cb3158fffdc25ec4b4dda1 +Author: James Bottomley +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@kernel.org + Signed-off-by: James Bottomley + +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 e6c429520..42e0f810d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -683,6 +683,8 @@ Patch12205: runtime_pm_fixups.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch +Patch13000: fix-scsi_dispatch_cmd.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1260,6 +1262,8 @@ ApplyPatch neuter_intel_microcode_load.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch +ApplyPatch fix-scsi_dispatch_cmd.patch + # END OF PATCH APPLICATIONS %endif @@ -1872,6 +1876,9 @@ fi # and build. %changelog +* Thu Jul 28 2011 Dave Jones +- fix crash in scsi_dispatch_cmd() + * Thu Jul 28 2011 Dave Jones 2.6.40-1 - Turn off debugging options. (make release)