From: Jens Axboe <axboe@suse.de>

On Tue, Mar 23 2004, 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).




---

 25-akpm/drivers/block/elevator.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff -puN drivers/block/elevator.c~BLKPREP_KILL-fix drivers/block/elevator.c
--- 25/drivers/block/elevator.c~BLKPREP_KILL-fix	Tue Mar 23 14:45:00 2004
+++ 25-akpm/drivers/block/elevator.c	Tue Mar 23 14:45:00 2004
@@ -219,10 +219,14 @@ struct request *elv_next_request(request
 			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);

_