From: Boaz Harrosh <bharrosh@panasas.com>
To: Christoph Hellwig <hch@lst.de>
Cc: Andrew Morton <akpm@osdl.org>,
Peter Osterlund <petero2@telia.com>,
linux-scsi@vger.kernel.org,
"bugme-daemon@kernel-bugs.osdl.org"
<bugme-daemon@bugzilla.kernel.org>,
laurent.riffard@free.fr, Adrian Bunk <bunk@stusta.de>
Subject: Re: [Bugme-new] [Bug 7667] New: BUG at drivers/scsi/scsi_lib.c:1118 caused by "pktsetup dvd /dev/sr0"
Date: Tue, 12 Dec 2006 16:21:23 +0200 [thread overview]
Message-ID: <457EBAE3.6090609@panasas.com> (raw)
In-Reply-To: <20061212132600.GA19912@lst.de>
Christoph Hellwig wrote:
> On Tue, Dec 12, 2006 at 11:38:42AM +0100, Christoph Hellwig wrote:
>> 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.
>> As part of the patch you mentioned I added strict assertations for that
>> case because the scsi layer doesn't handle those anymore.
>>
>> 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. I'll prepare a patch this weekend unless
>> someone beets me in doing that work.
>
> Please try the patch below to fix the bug for now. It's not the
> full way to a generic execute block pc infrastcuture but should fix
> the bug for the time beeing:
>
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
>
> Index: linux-2.6/drivers/block/pktcdvd.c
> ===================================================================
> --- linux-2.6.orig/drivers/block/pktcdvd.c 2006-12-12 11:30:45.000000000 +0100
> +++ linux-2.6/drivers/block/pktcdvd.c 2006-12-12 14:23:37.000000000 +0100
> @@ -765,47 +765,34 @@
> */
> 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;
> }
>
> /*
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
I'm afraid this might not be enough because of code in drivers/ide/ide-cd.c. It does IO off of request->data.
[background]
pkt_generic_packet and ton of other places mainly cd(s), floppy(s), and other ide code paths,
are using what I call BLACK requests. They put some data on request->buffer or request->data
stick it in the Q and than advance on them later down the ladder. Remove of "buffer" and "data" from
struct request will reveal all these places. At one time I had plans to do just that. But 1/2 way through I gave
up, it is too risky, too much Hardware that I don't have, that needs checking.
below patch combined with your patch might get a bit closer for this code path.
At struct request I have changed the name of "data" member to "user_data". than changed the code paths that used
"data" as IO to use request->buffer instead. This is just as bad but is a more common practice.
I suspect there is a problem with what I did in scsi_lib.c Christoph please check me out with the new BUG_ON.
Mainly what you need from below is only the code in ide-cd.c.
(And there are 3-4 places that do exactly like pkt_generic_packet, though I'm not sure they end up through SCSI.
At first I thought this code doesn't either)
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 9eaee66..f52a4f2 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -257,7 +257,7 @@ static void rq_init(request_queue_t *q,
rq->q = q;
rq->special = NULL;
rq->data_len = 0;
- rq->data = NULL;
+ rq->user_data = NULL;
rq->nr_phys_segments = 0;
rq->sense = NULL;
rq->end_io = NULL;
@@ -1199,7 +1199,7 @@ void blk_dump_rq_flags(struct request *r
printk("\nsector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector,
rq->nr_sectors,
rq->current_nr_sectors);
- printk("bio %p, biotail %p, buffer %p, data %p, len %u\n", rq->bio, rq->biotail, rq->buffer, rq->data, rq->data_len);
+ printk("bio %p, biotail %p, buffer %p, user_data %p, len %u\n", rq->bio, rq->biotail, rq->buffer, rq->user_data, rq->data_len);
if (blk_pc_request(rq)) {
printk("cdb: ");
@@ -2370,7 +2370,7 @@ int blk_rq_map_user(request_queue_t *q,
rq->bio = rq->biotail = bio;
blk_rq_bio_prep(q, rq, bio);
- rq->buffer = rq->data = NULL;
+ rq->buffer = NULL;
rq->data_len = len;
return 0;
}
@@ -2420,7 +2420,7 @@ int blk_rq_map_user_iov(request_queue_t
rq->bio = rq->biotail = bio;
blk_rq_bio_prep(q, rq, bio);
- rq->buffer = rq->data = NULL;
+ rq->buffer = NULL;
rq->data_len = bio->bi_size;
return 0;
}
@@ -2479,7 +2479,7 @@ int blk_rq_map_kern(request_queue_t *q,
rq->bio = rq->biotail = bio;
blk_rq_bio_prep(q, rq, bio);
- rq->buffer = rq->data = NULL;
+ rq->buffer = NULL;
rq->data_len = len;
return 0;
}
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index dcd9c71..d163a2c 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -502,7 +502,6 @@ static int __blk_send_generic(request_qu
rq = blk_get_request(q, WRITE, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_BLOCK_PC;
- rq->data = NULL;
rq->data_len = 0;
rq->timeout = BLK_DEFAULT_TIMEOUT;
memset(rq->cmd, 0, sizeof(rq->cmd));
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index f2904f6..b72758c 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -360,9 +360,8 @@ static int pkt_generic_packet(struct pkt
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->buffer = cgc->buffer;
rq->data_len = cgc->buflen;
rq->sense = sense;
memset(sense, 0, sizeof(sense));
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 8821494..00fce03 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -613,14 +613,14 @@ static void cdrom_queue_request_sense(id
/* stuff the sense request in front of our current request */
cdrom_prepare_request(drive, rq);
- rq->data = sense;
+ rq->buffer = sense;
rq->cmd[0] = GPCMD_REQUEST_SENSE;
rq->cmd[4] = rq->data_len = 18;
rq->cmd_type = REQ_TYPE_SENSE;
- /* NOTE! Save the failed command in "rq->buffer" */
- rq->buffer = (void *) failed_command;
+ /* NOTE! Save the failed command in "rq->user_data" */
+ rq->user_data = failed_command;
(void) ide_do_drive_cmd(drive, rq, ide_preempt);
}
@@ -632,10 +632,10 @@ static void cdrom_end_request (ide_drive
if (blk_sense_request(rq) && uptodate) {
/*
- * For REQ_TYPE_SENSE, "rq->buffer" points to the original
+ * For REQ_TYPE_SENSE, "rq->user_data" points to the original
* failed request
*/
- struct request *failed = (struct request *) rq->buffer;
+ struct request *failed = rq->user_data;
struct cdrom_info *info = drive->driver_data;
void *sense = &info->sense_data;
unsigned long flags;
@@ -1441,7 +1441,7 @@ static ide_startstop_t cdrom_pc_intr (id
rq->data_len > 0 &&
rq->data_len <= 5) {
while (rq->data_len > 0) {
- *(unsigned char *)rq->data++ = 0;
+ *(unsigned char *)rq->buffer++ = 0;
--rq->data_len;
}
}
@@ -1468,12 +1468,12 @@ static ide_startstop_t cdrom_pc_intr (id
/* The drive wants to be written to. */
if ((ireason & 3) == 0) {
- if (!rq->data) {
+ if (!rq->buffer) {
blk_dump_rq_flags(rq, "cdrom_pc_intr, write");
goto confused;
}
/* Transfer the data. */
- HWIF(drive)->atapi_output_bytes(drive, rq->data, thislen);
+ HWIF(drive)->atapi_output_bytes(drive, rq->buffer, thislen);
/* If we haven't moved enough data to satisfy the drive,
add some padding. */
@@ -1484,18 +1484,18 @@ static ide_startstop_t cdrom_pc_intr (id
}
/* Keep count of how much data we've moved. */
- rq->data += thislen;
+ rq->buffer += thislen;
rq->data_len -= thislen;
}
/* Same drill for reading. */
else if ((ireason & 3) == 2) {
- if (!rq->data) {
+ if (!rq->buffer) {
blk_dump_rq_flags(rq, "cdrom_pc_intr, write");
goto confused;
}
/* Transfer the data. */
- HWIF(drive)->atapi_input_bytes(drive, rq->data, thislen);
+ HWIF(drive)->atapi_input_bytes(drive, rq->buffer, thislen);
/* If we haven't moved enough data to satisfy the drive,
add some padding. */
@@ -1506,7 +1506,7 @@ static ide_startstop_t cdrom_pc_intr (id
}
/* Keep count of how much data we've moved. */
- rq->data += thislen;
+ rq->buffer += thislen;
rq->data_len -= thislen;
if (blk_sense_request(rq))
@@ -1644,7 +1644,7 @@ static void post_transform_command(struc
if (req->bio)
ibuf = bio_data(req->bio);
else
- ibuf = req->data;
+ ibuf = req->buffer;
if (!ibuf)
return;
@@ -1662,7 +1662,7 @@ typedef void (xfer_func_t)(ide_drive_t *
/*
* best way to deal with dma that is not sector aligned right now... note
- * that in this path we are not using ->data or ->buffer at all. this irs
+ * that in this path we are not using ->buffer at all. this irs
* can replace cdrom_pc_intr, cdrom_read_intr, and cdrom_write_intr in the
* future.
*/
@@ -1745,7 +1745,7 @@ static ide_startstop_t cdrom_newpc_intr(
*/
while (thislen > 0) {
int blen = blen = rq->data_len;
- char *ptr = rq->data;
+ char *ptr = rq->buffer;
/*
* bio backed?
@@ -1772,7 +1772,7 @@ static ide_startstop_t cdrom_newpc_intr(
if (rq->bio)
end_that_request_chunk(rq, 1, blen);
else
- rq->data += blen;
+ rq->buffer += blen;
}
/*
@@ -2206,7 +2206,7 @@ static int cdrom_read_capacity(ide_drive
req.sense = sense;
req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
- req.data = (char *)&capbuf;
+ req.buffer = (char *)&capbuf;
req.data_len = sizeof(capbuf);
req.cmd_flags |= REQ_QUIET;
@@ -2229,7 +2229,7 @@ static int cdrom_read_tocentry(ide_drive
cdrom_prepare_request(drive, &req);
req.sense = sense;
- req.data = buf;
+ req.buffer = buf;
req.data_len = buflen;
req.cmd_flags |= REQ_QUIET;
req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
@@ -2324,7 +2324,7 @@ #endif /* not STANDARD_ATAPI */
If we get an error for the regular case, we assume
a CDI without additional audio tracks. In this case
the readable TOC is empty (CDI tracks are not included)
- and only holds the Leadout entry. Heiko Ei�eldt */
+ and only holds the Leadout entry. Heiko Ei�eldt */
ntracks = 0;
stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
(char *)&toc->hdr,
@@ -2426,7 +2426,7 @@ static int cdrom_read_subchannel(ide_dri
cdrom_prepare_request(drive, &req);
req.sense = sense;
- req.data = buf;
+ req.buffer = buf;
req.data_len = buflen;
req.cmd[0] = GPCMD_READ_SUBCHANNEL;
req.cmd[1] = 2; /* MSF addressing */
@@ -2527,7 +2527,7 @@ static int ide_cdrom_packet(struct cdrom
memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
if (cgc->sense)
memset(cgc->sense, 0, sizeof(struct request_sense));
- req.data = cgc->buffer;
+ req.buffer = cgc->buffer;
req.data_len = cgc->buflen;
req.timeout = cgc->timeout;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 2614f41..dbf0295 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -141,7 +141,7 @@ enum {
static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
{
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->user_data;
if (drive->media != ide_disk)
return;
@@ -167,7 +167,7 @@ static void ide_complete_power_step(ide_
static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
{
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->user_data;
ide_task_t *args = rq->special;
memset(args, 0, sizeof(*args));
@@ -433,7 +433,7 @@ void ide_end_drive_cmd (ide_drive_t *dri
}
}
} else if (blk_pm_request(rq)) {
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->user_data;
#ifdef DEBUG_PM
printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n",
drive->name, rq->pm->pm_step, stat, err);
@@ -945,7 +945,7 @@ #endif
static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
{
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->user_data;
if (blk_pm_suspend_request(rq) &&
pm->pm_step == ide_pm_state_start_suspend)
@@ -1030,7 +1030,7 @@ #endif
rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
return execute_drive_cmd(drive, rq);
else if (blk_pm_request(rq)) {
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->user_data;
#ifdef DEBUG_PM
printk("%s: start_power_step(step: %d)\n",
drive->name, rq->pm->pm_step);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 287a662..47a6110 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1223,7 +1223,7 @@ static int generic_ide_suspend(struct de
memset(&args, 0, sizeof(args));
rq.cmd_type = REQ_TYPE_PM_SUSPEND;
rq.special = &args;
- rq.data = &rqpm;
+ rq.user_data = &rqpm;
rqpm.pm_step = ide_pm_state_start_suspend;
if (mesg.event == PM_EVENT_PRETHAW)
mesg.event = PM_EVENT_FREEZE;
@@ -1244,7 +1244,7 @@ static int generic_ide_resume(struct dev
memset(&args, 0, sizeof(args));
rq.cmd_type = REQ_TYPE_PM_RESUME;
rq.special = &args;
- rq.data = &rqpm;
+ rq.user_data = &rqpm;
rqpm.pm_step = ide_pm_state_start_resume;
rqpm.pm_state = PM_EVENT_ON;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index fb616c6..bea6e9e 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -351,7 +351,7 @@ static int scsi_req_map_sg(struct reques
}
}
- rq->buffer = rq->data = NULL;
+ rq->buffer = NULL;
rq->data_len = data_len;
return 0;
@@ -1116,12 +1116,11 @@ static int scsi_setup_blk_pc_cmnd(struct
return ret;
} else {
BUG_ON(req->data_len);
- BUG_ON(req->data);
+ BUG_ON(req->buffer);
cmd->request_bufflen = 0;
cmd->request_buffer = NULL;
cmd->use_sg = 0;
- req->buffer = NULL;
}
BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd));
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 7bfcde2..beb1f8d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -288,7 +288,8 @@ struct request {
unsigned short ioprio;
void *special;
- char *buffer;
+ char *buffer; /* FIXME: Deprecated */
+ void *user_data; /* FIXME: used to be *data. Deprecated this allready */
int tag;
int errors;
@@ -303,7 +304,6 @@ struct request {
unsigned int data_len;
unsigned int sense_len;
- void *data;
void *sense;
unsigned int timeout;
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2006-12-12 14:26 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <200612112159.kBBLxmep005850@fire-2.osdl.org>
2006-12-11 22:10 ` [Bugme-new] [Bug 7667] New: BUG at drivers/scsi/scsi_lib.c:1118 caused by "pktsetup dvd /dev/sr0" Andrew Morton
2006-12-11 22:36 ` James Bottomley
2006-12-12 10:38 ` Christoph Hellwig
2006-12-12 13:26 ` Christoph Hellwig
2006-12-12 14:21 ` Boaz Harrosh [this message]
2006-12-12 22:37 ` Laurent Riffard
2006-12-13 8:06 ` Boaz Harrosh
2006-12-28 22:28 ` Laurent Riffard
2007-01-02 12:05 ` struct request members, etc Christoph Hellwig
2007-01-02 12:34 ` Jens Axboe
2007-01-02 12:39 ` Christoph Hellwig
2007-01-02 12:44 ` Jens Axboe
2007-01-02 11:59 ` [Bugme-new] [Bug 7667] New: BUG at drivers/scsi/scsi_lib.c:1118 caused by "pktsetup dvd /dev/sr0" Christoph Hellwig
2007-01-02 14:00 ` Peter Osterlund
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=457EBAE3.6090609@panasas.com \
--to=bharrosh@panasas.com \
--cc=akpm@osdl.org \
--cc=bugme-daemon@bugzilla.kernel.org \
--cc=bunk@stusta.de \
--cc=hch@lst.de \
--cc=laurent.riffard@free.fr \
--cc=linux-scsi@vger.kernel.org \
--cc=petero2@telia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox