Skip to contentSkip to conversation

update bidirectional series to sit on top of sg_table

PATCH In review James Bottomley 3 participants 6 messages Jan 12, 2008 – Jan 23, 2008

Subsystems (3)
lore
Share & tools
lore

James Bottomley

author maintainer
#0 lore raw

cover update bidirectional series to sit on top of sg_table

OK, I suppose in the scheme of things, it's my turn to bear some of the pain. the SCSI bidirectional series rejects pretty badly with sg_table, and since sg_table has to go in, I rebased the series on top of it.

Additionally, I tidied up the patches to take advantages of some of the features of sg_table. I killed both use_sg and sg_count in favour of using sg_table.nseg for the count.

Just so you can test all of this to make sure I got it right, you can pull the patch series from

master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-bidi-2.6.git

James

author maintainer
#1 lore raw

PATCH 1/3 tgt: use scsi_init_io instead of scsi_alloc_sgtable

From: Boaz Harrosh <[email protected]>
Date: Thu, 13 Dec 2007 16:14:27 -0800
Subject: [SCSI] tgt: use scsi_init_io instead of scsi_alloc_sgtable

If we export scsi_init_io()/scsi_release_buffers() instead of scsi_{alloc,free}_sgtable() from scsi_lib than tgt code is much more insulated from scsi_lib changes. As a bonus it will also gain bidi capability when it comes.

[jejb: rebase on to sg_table and fix up rejections]

---
 drivers/scsi/scsi_lib.c     |   20 +++++++++-----------
 drivers/scsi/scsi_tgt_lib.c |   28 +++++-----------------------
 include/scsi/scsi_cmnd.h    |    4 ++--
 3 files changed, 16 insertions(+), 36 deletions(-)
drivers/scsi/scsi_lib.c +9 -11
index 0849c7c..5bc60f9 100644
@@ -755,7 +755,7 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask)
 	return mempool_alloc(sgp->pool, gfp_mask);
 }
 
-int scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
+static int scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 {
 	int ret;
 
@@ -769,15 +769,11 @@ int scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 	return ret;
 }
 
-EXPORT_SYMBOL(scsi_alloc_sgtable);
-
-void scsi_free_sgtable(struct scsi_cmnd *cmd)
+static void scsi_free_sgtable(struct scsi_cmnd *cmd)
 {
 	__sg_free_table(&cmd->sg_table, scsi_sg_free);
 }
 
-EXPORT_SYMBOL(scsi_free_sgtable);
-
 /*
  * Function:    scsi_release_buffers()
  *
@@ -795,7 +791,7 @@ EXPORT_SYMBOL(scsi_free_sgtable);
  *		the scatter-gather table, and potentially any bounce
  *		buffers.
  */
-static void scsi_release_buffers(struct scsi_cmnd *cmd)
+void scsi_release_buffers(struct scsi_cmnd *cmd)
 {
 	if (cmd->use_sg)
 		scsi_free_sgtable(cmd);
@@ -807,6 +803,7 @@ static void scsi_release_buffers(struct scsi_cmnd *cmd)
 	cmd->request_buffer = NULL;
 	cmd->request_bufflen = 0;
 }
+EXPORT_SYMBOL(scsi_release_buffers);
 
 /*
  * Function:    scsi_io_completion()
@@ -1008,7 +1005,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
  * Returns:     0 on success
  *		BLKPREP_DEFER if the failure is retryable
  */
-static int scsi_init_io(struct scsi_cmnd *cmd)
+int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 {
 	struct request     *req = cmd->request;
 	int		   count;
@@ -1023,7 +1020,7 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
 	/*
 	 * If sg table allocation fails, requeue request later.
 	 */
-	if (unlikely(scsi_alloc_sgtable(cmd, GFP_ATOMIC))) {
+	if (unlikely(scsi_alloc_sgtable(cmd, gfp_mask))) {
 		scsi_unprep_request(req);
 		return BLKPREP_DEFER;
 	}
@@ -1043,6 +1040,7 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
 	cmd->use_sg = count;
 	return BLKPREP_OK;
 }
+EXPORT_SYMBOL(scsi_init_io);
 
 static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
 		struct request *req)
@@ -1088,7 +1086,7 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 
 		BUG_ON(!req->nr_phys_segments);
 
-		ret = scsi_init_io(cmd);
+		ret = scsi_init_io(cmd, GFP_ATOMIC);
 		if (unlikely(ret))
 			return ret;
 	} else {
@@ -1139,7 +1137,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
 	if (unlikely(!cmd))
 		return BLKPREP_DEFER;
 
-	return scsi_init_io(cmd);
+	return scsi_init_io(cmd, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(scsi_setup_fs_cmnd);
 
drivers/scsi/scsi_tgt_lib.c +5 -23
index 01e03f3..91630ba 100644
@@ -331,8 +331,7 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
 
 	scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag);
 
-	if (scsi_sglist(cmd))
-		scsi_free_sgtable(cmd);
+	scsi_release_buffers(cmd);
 
 	queue_work(scsi_tgtd, &tcmd->work);
 }
@@ -353,25 +352,6 @@ static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
 	return 0;
 }
 
-static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask)
-{
-	struct request *rq = cmd->request;
-	int count;
-
-	cmd->use_sg = rq->nr_phys_segments;
-	if (scsi_alloc_sgtable(cmd, gfp_mask))
-		return -ENOMEM;
-
-	cmd->request_bufflen = rq->data_len;
-
-	dprintk("cmd %p cnt %d %lu\n", cmd, scsi_sg_count(cmd),
-		rq_data_dir(rq));
-	count = blk_rq_map_sg(rq->q, rq, scsi_sglist(cmd));
-	BUG_ON(count > cmd->use_sg);
-	cmd->use_sg = count;
-	return 0;
-}
-
 /* TODO: test this crap and replace bio_map_user with new interface maybe */
 static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
 			       unsigned long uaddr, unsigned int len, int rw)
@@ -397,9 +377,11 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
 	}
 
 	tcmd->bio = rq->bio;
-	err = scsi_tgt_init_cmd(cmd, GFP_KERNEL);
-	if (err)
+	err = scsi_init_io(cmd, GFP_KERNEL);
+	if (err) {
+		scsi_release_buffers(cmd);
 		goto unmap_rq;
+	}
 
 	return 0;
 
include/scsi/scsi_cmnd.h +2 -2
index 40f7c7c..764b929 100644
@@ -127,8 +127,8 @@ extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
 				 size_t *offset, size_t *len);
 extern void scsi_kunmap_atomic_sg(void *virt);
 
-extern int scsi_alloc_sgtable(struct scsi_cmnd *, gfp_t);
-extern void scsi_free_sgtable(struct scsi_cmnd *);
+extern int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask);
+extern void scsi_release_buffers(struct scsi_cmnd *cmd);
 
 extern int scsi_dma_map(struct scsi_cmnd *cmd);
 extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
Signature · 1 line
1.5.3.7
author maintainer
#2 lore raw

PATCH 2/3 implement scsi_data_buffer

In reply to James Bottomley

From: Boaz Harrosh <[email protected]>
Date: Thu, 13 Dec 2007 13:47:40 +0200
Subject: [SCSI] implement scsi_data_buffer

In preparation for bidi we abstract all IO members of scsi_cmnd, that will need to duplicate, into a substructure.

- Group all IO members of scsi_cmnd into a scsi_data_buffer structure.
- Adjust accessors to new members.
- scsi_{alloc,free}_sgtable receive a scsi_data_buffer instead of scsi_cmnd. And work on it.
- Adjust scsi_init_io() and scsi_release_buffers() for above change.
- Fix other parts of scsi_lib/scsi.c to members migration. Use accessors where appropriate.

- fix Documentation about scsi_cmnd in scsi_host.h

- scsi_error.c
* Changed needed members of struct scsi_eh_save.
* Careful considerations in scsi_eh_prep/restore_cmnd.

- sd.c and sr.c
* sd and sr would adjust IO size to align on device's block size so code needs to change once we move to scsi_data_buff implementation.
* Convert code to use scsi_for_each_sg
* Use data accessors where appropriate.

- tgt: convert libsrp to use scsi_data_buffer

- isd200: This driver still bangs on scsi_cmnd IO members, so need changing

[jejb: rebased on top of sg_table patches fixed up conflicts and used the synergy to eliminate use_sg and sg_count]

---
 drivers/scsi/libsrp.c        |    4 +-
 drivers/scsi/scsi.c          |    2 +-
 drivers/scsi/scsi_error.c    |   28 +++++++------------
 drivers/scsi/scsi_lib.c      |   61 ++++++++++++++++-------------------------
 drivers/scsi/sd.c            |    4 +-
 drivers/scsi/sr.c            |   25 +++++++++--------
 drivers/usb/storage/isd200.c |    8 +++---
 include/scsi/scsi_cmnd.h     |   36 +++++++++++++++---------
 include/scsi/scsi_eh.h       |    8 ++---
 include/scsi/scsi_host.h     |    4 +-
 10 files changed, 83 insertions(+), 97 deletions(-)
drivers/scsi/libsrp.c +2 -2
index 5cff020..6d6a76e 100644
@@ -426,8 +426,8 @@ int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info,
 
 	sc->SCp.ptr = info;
 	memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE);
-	sc->request_bufflen = len;
-	sc->request_buffer = (void *) (unsigned long) addr;
+	sc->sdb.length = len;
+	sc->sdb.table.sgl = (void *) (unsigned long) addr;
 	sc->tag = tag;
 	err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun,
 				     cmd->tag);
drivers/scsi/scsi.c +1 -1
index 54ff611..834d329 100644
@@ -711,7 +711,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
 				"Notifying upper driver of completion "
 				"(result %x)\n", cmd->result));
 
-	good_bytes = cmd->request_bufflen;
+	good_bytes = scsi_bufflen(cmd);
         if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
 		drv = scsi_cmd_to_driver(cmd);
 		if (drv->done)
drivers/scsi/scsi_error.c +10 -18
index 169bc59..8752a9f 100644
@@ -617,29 +617,25 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
 	ses->cmd_len = scmd->cmd_len;
 	memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
 	ses->data_direction = scmd->sc_data_direction;
-	ses->bufflen = scmd->request_bufflen;
-	ses->buffer = scmd->request_buffer;
-	ses->use_sg = scmd->use_sg;
-	ses->resid = scmd->resid;
+	ses->sdb = scmd->sdb;
 	ses->result = scmd->result;
 
+	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
+
 	if (sense_bytes) {
-		scmd->request_bufflen = min_t(unsigned,
+		scmd->sdb.length = min_t(unsigned,
 		                       sizeof(scmd->sense_buffer), sense_bytes);
 		sg_init_one(&ses->sense_sgl, scmd->sense_buffer,
-		                                       scmd->request_bufflen);
-		scmd->request_buffer = &ses->sense_sgl;
+			    scmd->sdb.length);
+		scmd->sdb.table.sgl = &ses->sense_sgl;
 		scmd->sc_data_direction = DMA_FROM_DEVICE;
-		scmd->use_sg = 1;
+		scmd->sdb.table.nents = 1;
 		memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
 		scmd->cmnd[0] = REQUEST_SENSE;
-		scmd->cmnd[4] = scmd->request_bufflen;
+		scmd->cmnd[4] = scmd->sdb.length;
 		scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 	} else {
-		scmd->request_buffer = NULL;
-		scmd->request_bufflen = 0;
 		scmd->sc_data_direction = DMA_NONE;
-		scmd->use_sg = 0;
 		if (cmnd) {
 			memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
 			memcpy(scmd->cmnd, cmnd, cmnd_size);
@@ -676,10 +672,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
 	scmd->cmd_len = ses->cmd_len;
 	memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
 	scmd->sc_data_direction = ses->data_direction;
-	scmd->request_bufflen = ses->bufflen;
-	scmd->request_buffer = ses->buffer;
-	scmd->use_sg = ses->use_sg;
-	scmd->resid = ses->resid;
+	scmd->sdb = ses->sdb;
 	scmd->result = ses->result;
 }
 EXPORT_SYMBOL(scsi_eh_restore_cmnd);
@@ -1700,8 +1693,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
 	memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
     
 	scmd->scsi_done		= scsi_reset_provider_done_command;
-	scmd->request_buffer		= NULL;
-	scmd->request_bufflen		= 0;
+	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
 
 	scmd->cmd_len			= 0;
 
drivers/scsi/scsi_lib.c +24 -37

144 lines not on this page · raw message

drivers/scsi/sd.c +2 -2
index 212f6bc..376db4d 100644
@@ -510,7 +510,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
 		SCpnt->cmnd[4] = (unsigned char) this_count;
 		SCpnt->cmnd[5] = 0;
 	}
-	SCpnt->request_bufflen = this_count * sdp->sector_size;
+	SCpnt->sdb.length = this_count * sdp->sector_size;
 
 	/*
 	 * We shouldn't disconnect in the middle of a sector, so with a dumb
@@ -917,7 +917,7 @@ static struct block_device_operations sd_fops = {
 static int sd_done(struct scsi_cmnd *SCpnt)
 {
 	int result = SCpnt->result;
- 	unsigned int xfer_size = SCpnt->request_bufflen;
+	unsigned int xfer_size = scsi_bufflen(SCpnt);
  	unsigned int good_bytes = result ? 0 : xfer_size;
  	u64 start_lba = SCpnt->request->sector;
  	u64 bad_lba;
drivers/scsi/sr.c +13 -12
index 1fcee16..50ba492 100644
@@ -231,7 +231,7 @@ out:
 static int sr_done(struct scsi_cmnd *SCpnt)
 {
 	int result = SCpnt->result;
-	int this_count = SCpnt->request_bufflen;
+	int this_count = scsi_bufflen(SCpnt);
 	int good_bytes = (result == 0 ? this_count : 0);
 	int block_sectors = 0;
 	long error_sector;
@@ -379,17 +379,18 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
 	}
 
 	{
-		struct scatterlist *sg = SCpnt->request_buffer;
-		int i, size = 0;
-		for (i = 0; i < SCpnt->use_sg; i++)
-			size += sg[i].length;
+		struct scatterlist *sg;
+		int i, size = 0, sg_count = scsi_sg_count(SCpnt);
 
-		if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
+		scsi_for_each_sg(SCpnt, sg, sg_count, i)
+			size += sg->length;
+
+		if (size != scsi_bufflen(SCpnt)) {
 			scmd_printk(KERN_ERR, SCpnt,
 				"mismatch count %d, bytes %d\n",
-				size, SCpnt->request_bufflen);
-			if (SCpnt->request_bufflen > size)
-				SCpnt->request_bufflen = size;
+				size, scsi_bufflen(SCpnt));
+			if (scsi_bufflen(SCpnt) > size)
+				SCpnt->sdb.length = size;
 		}
 	}
 
@@ -397,12 +398,12 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
 	 * request doesn't start on hw block boundary, add scatter pads
 	 */
 	if (((unsigned int)rq->sector % (s_size >> 9)) ||
-	    (SCpnt->request_bufflen % s_size)) {
+	    (scsi_bufflen(SCpnt) % s_size)) {
 		scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n");
 		goto out;
 	}
 
-	this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9);
+	this_count = (scsi_bufflen(SCpnt) >> 9) / (s_size >> 9);
 
 
 	SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
@@ -416,7 +417,7 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
 
 	if (this_count > 0xffff) {
 		this_count = 0xffff;
-		SCpnt->request_bufflen = this_count * s_size;
+		SCpnt->sdb.length = this_count * s_size;
 	}
 
 	SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
drivers/usb/storage/isd200.c +4 -4
index 178e8c2..0db4886 100644
@@ -415,14 +415,14 @@ static void isd200_set_srb(struct isd200_info *info,
 		sg_init_one(&info->sg, buff, bufflen);
 
 	srb->sc_data_direction = dir;
-	srb->request_buffer = buff ? &info->sg : NULL;
-	srb->request_bufflen = bufflen;
-	srb->use_sg = buff ? 1 : 0;
+	srb->sdb.table.sgl = buff ? &info->sg : NULL;
+	srb->sdb.length = bufflen;
+	srb->sdb.table.nents = buff ? 1 : 0;
 }
 
 static void isd200_srb_set_bufflen(struct scsi_cmnd *srb, unsigned bufflen)
 {
-	srb->request_bufflen = bufflen;
+	srb->sdb.length = bufflen;
 }
 
 
include/scsi/scsi_cmnd.h +22 -14
index 764b929..d95f0bf 100644
@@ -11,6 +11,11 @@ struct request;
 struct Scsi_Host;
 struct scsi_device;
 
+struct scsi_data_buffer {
+	struct sg_table table;
+	unsigned length;
+	int resid;
+};
 
 /* embedded in scsi_cmnd */
 struct scsi_pointer {
@@ -61,15 +66,11 @@ struct scsi_cmnd {
 	/* These elements define the operation we are about to perform */
 #define MAX_COMMAND_SIZE	16
 	unsigned char cmnd[MAX_COMMAND_SIZE];
-	unsigned request_bufflen;	/* Actual request size */
 
 	struct timer_list eh_timeout;	/* Used to time out the command. */
-	void *request_buffer;		/* Actual requested buffer */
 
 	/* These elements define the operation we ultimately want to perform */
-	struct sg_table sg_table;
-	unsigned short use_sg;	/* Number of pieces of scatter-gather */
-
+	struct scsi_data_buffer sdb;
 	unsigned underflow;	/* Return error if less than
 				   this amount is transferred */
 
@@ -79,10 +80,6 @@ struct scsi_cmnd {
 				   reconnects.   Probably == sector
 				   size */
 
-	int resid;		/* Number of bytes requested to be
-				   transferred less actual number
-				   transferred (0 if not supported) */
-
 	struct request *request;	/* The command we are
 				   	   working on */
 
@@ -133,18 +130,29 @@ extern void scsi_release_buffers(struct scsi_cmnd *cmd);
 extern int scsi_dma_map(struct scsi_cmnd *cmd);
 extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
 
-#define scsi_sg_count(cmd) ((cmd)->use_sg)
-#define scsi_sglist(cmd) ((cmd)->sg_table.sgl)
-#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
+static inline unsigned scsi_sg_count(struct scsi_cmnd *cmd)
+{
+	return cmd->sdb.table.nents;
+}
+
+static inline struct scatterlist *scsi_sglist(struct scsi_cmnd *cmd)
+{
+	return cmd->sdb.table.sgl;
+}
+
+static inline unsigned scsi_bufflen(struct scsi_cmnd *cmd)
+{
+	return cmd->sdb.length;
+}
 
 static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
 {
-	cmd->resid = resid;
+	cmd->sdb.resid = resid;
 }
 
 static inline int scsi_get_resid(struct scsi_cmnd *cmd)
 {
-	return cmd->resid;
+	return cmd->sdb.resid;
 }
 
 #define scsi_for_each_sg(cmd, sg, nseg, __i)			\
include/scsi/scsi_eh.h +3 -5
index d21b891..1e08be1 100644
@@ -68,16 +68,14 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
 extern int scsi_reset_provider(struct scsi_device *, int);
 
 struct scsi_eh_save {
+	/* saved state */
 	int result;
 	enum dma_data_direction data_direction;
 	unsigned char cmd_len;
 	unsigned char cmnd[MAX_COMMAND_SIZE];
+	struct scsi_data_buffer sdb;
 
-	void *buffer;
-	unsigned bufflen;
-	unsigned short use_sg;
-	int resid;
-
+	/* new command support */
 	struct scatterlist sense_sgl;
 };
 
include/scsi/scsi_host.h +2 -2
index 0fd4746..cb2bcab 100644
@@ -136,9 +136,9 @@ struct scsi_host_template {
 	 * the done callback is invoked.
 	 *
 	 * This is called to inform the LLD to transfer
-	 * cmd->request_bufflen bytes. The cmd->use_sg speciefies the
+	 * scsi_bufflen(cmd) bytes. scsi_sg_count(cmd) speciefies the
 	 * number of scatterlist entried in the command and
-	 * cmd->request_buffer contains the scatterlist.
+	 * scsi_sglist(cmd) returns the scatterlist.
 	 *
 	 * return values: see queuecommand
 	 *
Signature · 1 line
1.5.3.7
author maintainer
#3 lore raw

PATCH 3/3 bidirectional command support

In reply to James Bottomley

From: Boaz Harrosh <[email protected]>
Date: Thu, 13 Dec 2007 13:50:53 +0200
Subject: [SCSI] bidirectional command support

At the block level bidi request uses req->next_rq pointer for a second bidi_read request.
At Scsi-midlayer a second scsi_data_buffer structure is used for the bidi_read part. This bidi scsi_data_buffer is put on request->next_rq->special. Struct scsi_cmnd is not changed.

- Define scsi_bidi_cmnd() to return true if it is a bidi request and a second sgtable was allocated.

- Define scsi_in()/scsi_out() to return the in or out scsi_data_buffer from this command This API is to isolate users from the mechanics of bidi.

- Define scsi_end_bidi_request() to do what scsi_end_request() does but for a bidi request. This is necessary because bidi commands are a bit tricky here. (See comments in body)

- scsi_release_buffers() will also release the bidi_read scsi_data_buffer

- scsi_io_completion() on bidi commands will now call scsi_end_bidi_request() and return.

- The previous work done in scsi_init_io() is now done in a new scsi_init_sgtable() (which is 99% identical to old scsi_init_io()) The new scsi_init_io() will call the above twice if needed also for the bidi_read command. Only at this point is a command bidi.

- In scsi_error.c at scsi_eh_prep/restore_cmnd() make sure bidi-lld is not confused by a get-sense command that looks like bidi. This is done by puting NULL at request->next_rq, and restoring.

[jejb: update to sg_table and resolve conflicts]

---
 drivers/scsi/scsi_error.c |    3 +
 drivers/scsi/scsi_lib.c   |  144 ++++++++++++++++++++++++++++++++++++---------
 include/scsi/scsi_cmnd.h  |   23 +++++++-
 include/scsi/scsi_eh.h    |    1 +
 4 files changed, 141 insertions(+), 30 deletions(-)
drivers/scsi/scsi_error.c +3 -0
index 8752a9f..65d02e8 100644
@@ -618,9 +618,11 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
 	memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
 	ses->data_direction = scmd->sc_data_direction;
 	ses->sdb = scmd->sdb;
+	ses->next_rq = scmd->request->next_rq;
 	ses->result = scmd->result;
 
 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
+	scmd->request->next_rq = NULL;
 
 	if (sense_bytes) {
 		scmd->sdb.length = min_t(unsigned,
@@ -673,6 +675,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
 	memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
 	scmd->sc_data_direction = ses->data_direction;
 	scmd->sdb = ses->sdb;
+	scmd->request->next_rq = ses->next_rq;
 	scmd->result = ses->result;
 }
 EXPORT_SYMBOL(scsi_eh_restore_cmnd);
drivers/scsi/scsi_lib.c +115 -29

212 lines not on this page · raw message

include/scsi/scsi_cmnd.h +22 -1
index d95f0bf..90d8c5a 100644
@@ -2,12 +2,12 @@
 #define _SCSI_SCSI_CMND_H
 
 #include <linux/dma-mapping.h>
+#include <linux/blkdev.h>
 #include <linux/list.h>
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/scatterlist.h>
 
-struct request;
 struct Scsi_Host;
 struct scsi_device;
 
@@ -158,4 +158,25 @@ static inline int scsi_get_resid(struct scsi_cmnd *cmd)
 #define scsi_for_each_sg(cmd, sg, nseg, __i)			\
 	for_each_sg(scsi_sglist(cmd), sg, nseg, __i)
 
+static inline int scsi_bidi_cmnd(struct scsi_cmnd *cmd)
+{
+	return blk_bidi_rq(cmd->request) &&
+		(cmd->request->next_rq->special != NULL);
+}
+
+static inline struct scsi_data_buffer *scsi_in(struct scsi_cmnd *cmd)
+{
+	WARN_ON((cmd->sc_data_direction != DMA_FROM_DEVICE) &&
+		!scsi_bidi_cmnd(cmd));
+	return scsi_bidi_cmnd(cmd) ?
+		cmd->request->next_rq->special : &cmd->sdb;
+}
+
+static inline struct scsi_data_buffer *scsi_out(struct scsi_cmnd *cmd)
+{
+	WARN_ON((cmd->sc_data_direction != DMA_TO_DEVICE) &&
+		!scsi_bidi_cmnd(cmd));
+	return &cmd->sdb;
+}
+
 #endif /* _SCSI_SCSI_CMND_H */
include/scsi/scsi_eh.h +1 -0
index 1e08be1..25071d5 100644
@@ -74,6 +74,7 @@ struct scsi_eh_save {
 	unsigned char cmd_len;
 	unsigned char cmnd[MAX_COMMAND_SIZE];
 	struct scsi_data_buffer sdb;
+	struct request *next_rq;
 
 	/* new command support */
 	struct scatterlist sense_sgl;
Signature · 1 line
1.5.3.7
#4 lore raw
In reply to James Bottomley

From: James Bottomley <[email protected]>
Subject: [PATCH 0/3] update bidirectional series to sit on top of sg_table
Date: Fri, 11 Jan 2008 21:09:00 -0600

Quoted 4 lines

OK, I suppose in the scheme of things, it's my turn to bear some of the pain. the SCSI bidirectional series rejects pretty badly with sg_table, and since sg_table has to go in, I rebased the series on top of it.

Quoted 8 lines

Additionally, I tidied up the patches to take advantages of some of the features of sg_table. I killed both use_sg and sg_count in favour of using sg_table.nseg for the count.

Just so you can test all of this to make sure I got it right, you can pull the patch series from

master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-bidi-2.6.git

I've just started to look at the bidi tree.

I suppose that only panasas guys have tested the bidi tree with their OSD target devices. To test the bidi tree, I added XDWRITEREAD_10 support to scsi_debug and sgv4_xdwriteread tool to my makeshift bsg tool collections:

git://git.kernel.org/pub/scm/linux/kernel/git/tomo/sgv4-tools.git

It just sends XDWRITEREAD_10 commands like this:

tulip:~# sgv4_xdwriteread --length 16384 /sys/class/bsg/1:0:0:0
driver:0, transport:0, device:0, din_resid: 0, dout_resid: 0

No errors.

I'll send the patchset (over the bidi tree) to add XDWRITEREAD_10 support to scsi_debug though I'm not sure whether it's worth adding it to mainline.

#5 lore raw
Quoted 15 lines · FUJITA Tomonori

From: James Bottomley <[email protected]>
Subject: [PATCH 0/3] update bidirectional series to sit on top of sg_table
Date: Fri, 11 Jan 2008 21:09:00 -0600

Quoted 11 lines

OK, I suppose in the scheme of things, it's my turn to bear some of the pain. the SCSI bidirectional series rejects pretty badly with sg_table, and since sg_table has to go in, I rebased the series on top of it.

Additionally, I tidied up the patches to take advantages of some of the features of sg_table. I killed both use_sg and sg_count in favour of using sg_table.nseg for the count.

Just so you can test all of this to make sure I got it right, you can pull the patch series from

Quoted 6 lines
Quoted 1 line

master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-bidi-2.6.git

I've just started to look at the bidi tree.

I suppose that only panasas guys have tested the bidi tree with their OSD target devices. To test the bidi tree,

OSD Yes, but not only Panasas guys. Pete Wyckoff is doing bidi threw bsg to an OSD scsi_tgt target. And Seagate guys have an OSD device they use also threw bsg. In Panasas we used IBM's OSD-Initiator and now our own osd_lib, an in kernel only library that will be part of the Objects-layout drivers for pNFS.

Quoted 11 lines

I added XDWRITEREAD_10
support to scsi_debug and sgv4_xdwriteread tool to my makeshift bsg tool collections:

git://git.kernel.org/pub/scm/linux/kernel/git/tomo/sgv4-tools.git

It just sends XDWRITEREAD_10 commands like this:

tulip:~# sgv4_xdwriteread --length 16384 /sys/class/bsg/1:0:0:0
driver:0, transport:0, device:0, din_resid: 0, dout_resid: 0
Quoted 6 lines

No errors.

I'll send the patchset (over the bidi tree) to add XDWRITEREAD_10 support to scsi_debug though I'm not sure whether it's worth adding it to mainline.
-

Thanks TOMO, I think this is most valuable contribution, because now programmers have a most simple setup they can put up, to make sure they did not break, also the bidi path. And not need to setup the complete OSD stack for that. Also it is a very good reference implementation for drivers that want to support XDWRITEREAD_10. I bet the raid guys will love it.

So Thanks
Boaz