All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.