From: Christoph Hellwig Date: Sat, 6 Jan 2007 00:36:26 +0000 (-0800) Subject: [PATCH] Fix BUG at drivers/scsi/scsi_lib.c:1118 caused by "pktsetup dvd /dev/sr0" X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=406c9b605cbc45151c03ac9a3f95e9acf050808c;p=openwrt%2Fstaging%2Fblogic.git [PATCH] Fix BUG at drivers/scsi/scsi_lib.c:1118 caused by "pktsetup dvd /dev/sr0" Fix http://bugzilla.kernel.org/show_bug.cgi?id=7667 This is because the packet driver tries to send down read/write BLOCK_PC commands that don't use a bio and do not use sg lists. The right fix is to replace all the packet_command stuff in the packet driver by scsi_execute() which needs to be lifted from scsi code to the block code for that. Fix the bug for now. It's not the full way to a generic execute block pc infrastcuture but fixes the bug for the time being. Signed-off-by: Christoph Hellwig Acked-by: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 7c95c762950f..62462190e07e 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -765,47 +765,34 @@ static inline struct bio *pkt_get_list_first(struct bio **list_head, struct bio */ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *cgc) { - char sense[SCSI_SENSE_BUFFERSIZE]; - request_queue_t *q; + request_queue_t *q = bdev_get_queue(pd->bdev); struct request *rq; - DECLARE_COMPLETION_ONSTACK(wait); - int err = 0; + int ret = 0; - q = bdev_get_queue(pd->bdev); + rq = blk_get_request(q, (cgc->data_direction == CGC_DATA_WRITE) ? + WRITE : READ, __GFP_WAIT); + + if (cgc->buflen) { + if (blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen, __GFP_WAIT)) + goto out; + } + + rq->cmd_len = COMMAND_SIZE(rq->cmd[0]); + memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE); + if (sizeof(rq->cmd) > CDROM_PACKET_SIZE) + memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE); - rq = blk_get_request(q, (cgc->data_direction == CGC_DATA_WRITE) ? WRITE : READ, - __GFP_WAIT); - rq->errors = 0; - rq->rq_disk = pd->bdev->bd_disk; - rq->bio = NULL; - rq->buffer = NULL; rq->timeout = 60*HZ; - rq->data = cgc->buffer; - rq->data_len = cgc->buflen; - rq->sense = sense; - memset(sense, 0, sizeof(sense)); - rq->sense_len = 0; rq->cmd_type = REQ_TYPE_BLOCK_PC; rq->cmd_flags |= REQ_HARDBARRIER; if (cgc->quiet) rq->cmd_flags |= REQ_QUIET; - memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE); - if (sizeof(rq->cmd) > CDROM_PACKET_SIZE) - memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE); - rq->cmd_len = COMMAND_SIZE(rq->cmd[0]); - - rq->ref_count++; - rq->end_io_data = &wait; - rq->end_io = blk_end_sync_rq; - elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); - generic_unplug_device(q); - wait_for_completion(&wait); - - if (rq->errors) - err = -EIO; + blk_execute_rq(rq->q, pd->bdev->bd_disk, rq, 0); + ret = rq->errors; +out: blk_put_request(rq); - return err; + return ret; } /*