]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Fix BLKPREP_KILL
authorAndrew Morton <akpm@osdl.org>
Tue, 30 Mar 2004 02:41:31 +0000 (18:41 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 30 Mar 2004 02:41:31 +0000 (18:41 -0800)
From: Jens Axboe <axboe@suse.de>

Samuel Rydh wrote:

If a MODE_SENSE(6) command is sent to an IDE cd using the CDROM_SEND_PACKET
ioctl, then the kernel freezes solidly. To reproduce this, one can take the
SCSI cmd [1a 08 31 00 10 00] and a 16 byte data buffer.

After some bug hunting, I found out that the following is what happens:

- ide-cd recognizes that MODE_SENSE(6) isn't supported and tries
  to abort the request from ide_cdrom_prep_pc by returning BLKPREP_KILL.

- in elv_next_request(), the kill request is handled by
  the following code:

while (end_that_request_first(rq, 0, rq->nr_sectors))
;
end_that_request_last(rq);

The while loop never exits. The end_that_request_first() doesn't do anything
since rq->nr_sectors is 0; it just returns "not-done" after handling those 0
bytes (rq->bio->bi_size is 16).

drivers/block/elevator.c

index 4b560bac8c1506714bc24afb226eaa5ea46525dc..40377d4a030acfdc40d16d30fe8e1fbdcde23811 100644 (file)
@@ -210,10 +210,14 @@ struct request *elv_next_request(request_queue_t *q)
                        rq = NULL;
                        break;
                } else if (ret == BLKPREP_KILL) {
+                       int nr_bytes = rq->hard_nr_sectors << 9;
+
+                       if (!nr_bytes)
+                               nr_bytes = rq->data_len;
+
                        blkdev_dequeue_request(rq);
                        rq->flags |= REQ_QUIET;
-                       while (end_that_request_first(rq, 0, rq->nr_sectors))
-                               ;
+                       end_that_request_chunk(rq, 0, nr_bytes);
                        end_that_request_last(rq);
                } else {
                        printk("%s: bad return=%d\n", __FUNCTION__, ret);