linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs
  2008-02-10 15:07         ` Boaz Harrosh
@ 2008-03-25 15:57           ` Boaz Harrosh
  0 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-03-25 15:57 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, Christoph Hellwig, Andrew Morton; +Cc: linux-scsi

Submitted is a patchset for adding support for variable-length, extended,
and vendor specific CDBs. It should now cover the entire range of the 
SCSI standard. (and/or any other use of command packets in block devices)

They are based on scsi-misc/scsi-rc-fixes/linux-block. They are aimed
for the 2.6.26 merge window. Andrew please also include them in -mm
for testing.

Difference from last time, is at struct request. I did a smallish
hack to save the extra pointer space. The pointer now shares it's
space with the request->cmd, as they are mutual exclusive. The
flag to switch between them is when cmd_len == 0 and varlen_cdb_len != 0
I've added 2 accessors to hide the mess. I think this approach
should be safe with legacy drivers.

This is on top of the size shrink to struct scsi_cmnd gained
in the first patch. We save upto 12 bytes on 32 bit ARCHs

So over all, this cleans things up, and add fixtures without
*any extra cost*.

[1/3] Let scsi_cmnd->cmnd use request->cmd buffer
  Here I let scsi_cmnd->cmnd point to the space allocated by
  request->cmd, instead of copying the data. The scsi_cmnd->cmd_len
  is guaranteed to contain the right length of the command.
  I have tried to go over every single place in the kernel that uses
  scsi_cmnd->cmnd and make sure it looks sane. Surprisingly to me,
  that was not at all bad. I hope I did not miss anything.

  I've tested on an x86_64 machine booting from a sata disk and
  ran the iscsi regression tests as well as my bidi and varlen tests
  on top of the complete patchset and all tests passed.

[2/3] block layer varlen-cd
   Here I added an option to use a user supplied buffer for an arbitrary
   large command. Buffer must be kept valid until execution of request
   ends. The pointer to the buffer shares it's space with the fixed
   length command, so the size of struct request does not change.

[3/3] scsi: varlen extended and vendor-specific cdbs
  Adds support for variable length, extended, and vendor-specific
  cdbs at the scsi mid-layer.

Boaz




^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs
@ 2008-03-25 16:21 Boaz Harrosh
  2008-03-25 16:22 ` [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
                   ` (4 more replies)
  0 siblings, 5 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-03-25 16:21 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, Christoph Hellwig, linux-scsi,
	Andrew

Submitted is a patchset for adding support for variable-length, extended,
and vendor specific CDBs. It should now cover the entire range of the 
SCSI standard. (and/or any other use of command packets in block devices)

They are based on scsi-misc/scsi-rc-fixes/linux-block. They are aimed
for the 2.6.26 merge window. Andrew please also include them in -mm
for testing.

Difference from last time, is at struct request. I did a smallish
hack to save the extra pointer space. The pointer now shares it's
space with the request->cmd, as they are mutual exclusive. The
flag to switch between them is when cmd_len == 0 and varlen_cdb_len != 0
I've added 2 accessors to hide the mess. I think this approach
should be safe with legacy drivers.

This is on top of the size shrink to struct scsi_cmnd gained
in the first patch. We save upto 12 bytes on 32 bit ARCHs

So over all, this cleans things up, and add fixtures without
*any extra cost*.

[1/3] Let scsi_cmnd->cmnd use request->cmd buffer
  Here I let scsi_cmnd->cmnd point to the space allocated by
  request->cmd, instead of copying the data. The scsi_cmnd->cmd_len
  is guaranteed to contain the right length of the command.
  I have tried to go over every single place in the kernel that uses
  scsi_cmnd->cmnd and make sure it looks sane. Surprisingly to me,
  that was not at all bad. I hope I did not miss anything.

  I've tested on an x86_64 machine booting from a sata disk and
  ran the iscsi regression tests as well as my bidi and varlen tests
  on top of the complete patchset and all tests passed.

[2/3] block layer varlen-cd
   Here I added an option to use a user supplied buffer for an arbitrary
   large command. Buffer must be kept valid until execution of request
   ends. The pointer to the buffer shares it's space with the fixed
   length command, so the size of struct request does not change.

[3/3] scsi: varlen extended and vendor-specific cdbs
  Adds support for variable length, extended, and vendor-specific
  cdbs at the scsi mid-layer.

Boaz


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer
  2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh
@ 2008-03-25 16:22 ` Boaz Harrosh
  2008-03-25 16:32 ` [PATCH 2/3] block layer varlen-cdb Boaz Harrosh
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-03-25 16:22 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, Christoph Hellwig, linux-scsi,
	Andrew


 - struct scsi_cmnd had a 16 bytes command buffer of its own.
   This is an unnecessary duplication and copy of request's
   cmd. It is probably left overs from the time that scsi_cmnd
   could function without a request attached. So clean that up.

 - Once above is done, few places, apart from scsi-ml, needed
   adjustments due to changing the data type of scsi_cmnd->cmnd.

 - Lots of drivers still use MAX_COMMAND_SIZE. So I have left
   that #define but equate it to BLK_MAX_CDB. The way I see it
   and is reflected in the patch below is.
   MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB
                      as per the SCSI standard and is not related
                      to the implementation.
   BLK_MAX_CDB.     - The allocated space at the request level

 - I have audit all ISA drivers and made sure none use ->cmnd in a DMA
   Operation. Same audit was done by Andi Kleen.

(*)fixed-length here means commands that their size can be determined
   by their opcode and the CDB does not carry a length specifier, (unlike
   the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
   true and the SCSI standard also defines extended commands and
   vendor specific commands that can be bigger than 16 bytes. The kernel
   will support these using the same infrastructure used for VARLEN CDB's.
   So in effect MAX_COMMAND_SIZE means the maximum size command
   scsi-ml supports without specifying a cmd_len by ULD's

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/firewire/fw-sbp2.c       |    2 +-
 drivers/s390/scsi/zfcp_dbf.c     |    2 +-
 drivers/s390/scsi/zfcp_fsf.c     |    2 +-
 drivers/scsi/53c700.c            |    6 +++---
 drivers/scsi/a100u2w.c           |    2 +-
 drivers/scsi/gdth.c              |    2 +-
 drivers/scsi/hptiop.c            |    6 +++---
 drivers/scsi/ibmvscsi/ibmvscsi.c |    2 +-
 drivers/scsi/initio.c            |    2 +-
 drivers/scsi/qla1280.c           |    4 ++--
 drivers/scsi/scsi_error.c        |   14 ++++++++------
 drivers/scsi/scsi_lib.c          |    5 +++--
 drivers/scsi/scsi_tgt_lib.c      |    2 ++
 drivers/usb/storage/isd200.c     |    2 ++
 include/scsi/scsi_cmnd.h         |   21 +++++++++++++++++++--
 include/scsi/scsi_eh.h           |    4 ++--
 16 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 62b4e47..2260e56 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -1492,7 +1492,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 
 	memset(orb->request.command_block,
 	       0, sizeof(orb->request.command_block));
-	memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+	memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
 
 	orb->base.callback = complete_command_orb;
 	orb->base.request_bus =
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 701046c..7a7f619 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -724,7 +724,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
 				rec->scsi_result = scsi_cmnd->result;
 				rec->scsi_cmnd = (unsigned long)scsi_cmnd;
 				rec->scsi_serial = scsi_cmnd->serial_number;
-				memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+				memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
 					min((int)scsi_cmnd->cmd_len,
 						ZFCP_DBF_SCSI_OPCODE));
 				rec->scsi_retries = scsi_cmnd->retries;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 2ed3c7b..df38e1d 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4227,7 +4227,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
 		ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n",
 			       scpnt->result);
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
-			      (void *) &scpnt->cmnd, scpnt->cmd_len);
+			      scpnt->cmnd, scpnt->cmd_len);
 
 		ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
 			       fcp_rsp_iu->fcp_sns_len);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index f4c4fe9..f5a9add 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
 			(struct NCR_700_command_slot *)SCp->host_scribble;
 		
 		dma_unmap_single(hostdata->dev, slot->pCmd,
-				 sizeof(SCp->cmnd), DMA_TO_DEVICE);
+				 MAX_COMMAND_SIZE, DMA_TO_DEVICE);
 		if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
 			char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
 #ifdef NCR_700_DEBUG
@@ -1004,7 +1004,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
 				 * here */
 				NCR_700_unmap(hostdata, SCp, slot);
 				dma_unmap_single(hostdata->dev, slot->pCmd,
-						 sizeof(SCp->cmnd),
+						 MAX_COMMAND_SIZE,
 						 DMA_TO_DEVICE);
 
 				cmnd[0] = REQUEST_SENSE;
@@ -1901,7 +1901,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	}
 	slot->resume_offset = 0;
 	slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
-				    sizeof(SCp->cmnd), DMA_TO_DEVICE);
+				    MAX_COMMAND_SIZE, DMA_TO_DEVICE);
 	NCR_700_start_command(SCp);
 	return 0;
 }
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 792b2e8..ced3eeb 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -895,7 +895,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru
 	} else {
 		scb->tag_msg = 0;	/* No tag support               */
 	}
-	memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len);
+	memcpy(scb->cdb, cmd->cmnd, scb->cdb_len);
 }
 
 /**
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index c6d6e7c..8e2e964 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -465,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
     scp->request = (struct request *)&wait;
     scp->timeout_per_command = timeout*HZ;
     scp->cmd_len = 12;
-    memcpy(scp->cmnd, cmnd, 12);
+    scp->cmnd = cmnd;
     cmndinfo.priority = IOCTL_PRI;
     cmndinfo.internal_cmd_str = gdtcmd;
     cmndinfo.internal_command = 1;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 44dccf2..5d9322c 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -761,9 +761,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 			scp,
 			host->host_no, scp->device->channel,
 			scp->device->id, scp->device->lun,
-			*((u32 *)&scp->cmnd),
-			*((u32 *)&scp->cmnd + 1),
-			*((u32 *)&scp->cmnd + 2),
+			((u32 *)scp->cmnd)[0],
+			((u32 *)scp->cmnd)[1],
+			((u32 *)scp->cmnd)[2],
 			_req->index, _req->req_virt);
 
 	scp->result = 0;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 78d46a9..df9b865 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -738,7 +738,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 	srp_cmd = &evt_struct->iu.srp.cmd;
 	memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
 	srp_cmd->opcode = SRP_CMD;
-	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb));
 	srp_cmd->lun = ((u64) lun) << 48;
 
 	if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 0cc8868..40e9875 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
 	cblk->hastat = 0;
 	cblk->tastat = 0;
 	/* Command the command */
-	memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
+	memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len);
 
 	/* Set up tags */
 	if (cmnd->device->tagged_supported) {	/* Tag Support                  */
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 68c0d09..b53420b 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -2863,7 +2863,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
 
 	/* Load SCSI command packet. */
 	pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
-	memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+	memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
 	/* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
 
 	/* Set transfer direction. */
@@ -3132,7 +3132,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
 
 	/* Load SCSI command packet. */
 	pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
-	memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+	memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
 
 	/*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
 	/* Set transfer direction. */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 1221d2c..0b42aa5 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -626,7 +626,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
  * @scmd:       SCSI command structure to hijack
  * @ses:        structure to save restore information
  * @cmnd:       CDB to send. Can be NULL if no new cmnd is needed
- * @cmnd_size:  size in bytes of @cmnd
+ * @cmnd_size:  size in bytes of @cmnd (must be <= BLK_MAX_CDB)
  * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
  *
  * This function is used to save a scsi command information before re-execution
@@ -648,12 +648,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
 	 * command.
 	 */
 	ses->cmd_len = scmd->cmd_len;
-	memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
+	ses->cmnd = scmd->cmnd;
 	ses->data_direction = scmd->sc_data_direction;
 	ses->sdb = scmd->sdb;
 	ses->next_rq = scmd->request->next_rq;
 	ses->result = scmd->result;
 
+	scmd->cmnd = ses->eh_cmnd;
+	memset(scmd->cmnd, 0, BLK_MAX_CDB);
 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
 	scmd->request->next_rq = NULL;
 
@@ -665,14 +667,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
 		scmd->sdb.table.sgl = &ses->sense_sgl;
 		scmd->sc_data_direction = DMA_FROM_DEVICE;
 		scmd->sdb.table.nents = 1;
-		memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
 		scmd->cmnd[0] = REQUEST_SENSE;
 		scmd->cmnd[4] = scmd->sdb.length;
 		scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 	} else {
 		scmd->sc_data_direction = DMA_NONE;
 		if (cmnd) {
-			memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+			BUG_ON(cmnd_size > BLK_MAX_CDB);
 			memcpy(scmd->cmnd, cmnd, cmnd_size);
 			scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 		}
@@ -705,7 +706,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
 	 * Restore original data
 	 */
 	scmd->cmd_len = ses->cmd_len;
-	memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
+	scmd->cmnd = ses->cmnd;
 	scmd->sc_data_direction = ses->data_direction;
 	scmd->sdb = ses->sdb;
 	scmd->request->next_rq = ses->next_rq;
@@ -1774,7 +1775,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
 	scmd->request = &req;
 	memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
 
-	memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
+	scmd->cmnd = req.cmd;
+	memset(scmd->cmnd, 0, BLK_MAX_CDB);
     
 	scmd->scsi_done		= scsi_reset_provider_done_command;
 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f40898d..75f3aab 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1092,6 +1092,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
 	cmd->tag = req->tag;
 	cmd->request = req;
 
+	cmd->cmnd = req->cmd;
+
 	return cmd;
 }
 
@@ -1129,8 +1131,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 		req->buffer = NULL;
 	}
 
-	BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd));
-	memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
 	cmd->cmd_len = req->cmd_len;
 	if (!req->data_len)
 		cmd->sc_data_direction = DMA_NONE;
@@ -1167,6 +1167,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
 	if (unlikely(!cmd))
 		return BLKPREP_DEFER;
 
+	memset(cmd->cmnd, 0, BLK_MAX_CDB);
 	return scsi_init_io(cmd, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(scsi_setup_fs_cmnd);
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index a0f308b..8c92ef3 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -107,6 +107,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
 	cmd->jiffies_at_alloc = jiffies;
 	cmd->request = rq;
 
+	cmd->cmnd = rq->cmd;
+
 	rq->special = cmd;
 	rq->cmd_type = REQ_TYPE_SPECIAL;
 	rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 971d13d..3addcd8 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -292,6 +292,7 @@ struct isd200_info {
 
 	/* maximum number of LUNs supported */
 	unsigned char MaxLUNs;
+	unsigned char cmnd[BLK_MAX_CDB];
 	struct scsi_cmnd srb;
 	struct scatterlist sg;
 };
@@ -450,6 +451,7 @@ static int isd200_action( struct us_data *us, int action,
 
 	memset(&ata, 0, sizeof(ata));
 	memset(&srb_dev, 0, sizeof(srb_dev));
+	srb->cmnd = info->cmnd;
 	srb->device = &srb_dev;
 	++srb->serial_number;
 
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 8d20e60..dea73e5 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -7,10 +7,28 @@
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/scatterlist.h>
+#include <linux/blkdev.h>
 
 struct Scsi_Host;
 struct scsi_device;
 
+/*
+ * MAX_COMMAND_SIZE is:
+ * The longest fixed-length SCSI CDB as per the SCSI standard.
+ * fixed-length means: commands that their size can be determined
+ * by their opcode and the CDB does not carry a length specifier, (unlike
+ * the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
+ * true and the SCSI standard also defines extended commands and
+ * vendor specific commands that can be bigger than 16 bytes. The kernel
+ * will support these using the same infrastructure used for VARLEN CDB's.
+ * So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml
+ * supports without specifying a cmd_len by ULD's
+ */
+#define MAX_COMMAND_SIZE 16
+#if (MAX_COMMAND_SIZE > BLK_MAX_CDB)
+# error MAX_COMMAND_SIZE can not be smaller than BLK_MAX_CDB
+#endif
+
 struct scsi_data_buffer {
 	struct sg_table table;
 	unsigned length;
@@ -64,8 +82,7 @@ struct scsi_cmnd {
 	enum dma_data_direction sc_data_direction;
 
 	/* These elements define the operation we are about to perform */
-#define MAX_COMMAND_SIZE	16
-	unsigned char cmnd[MAX_COMMAND_SIZE];
+	unsigned char *cmnd;
 
 	struct timer_list eh_timeout;	/* Used to time out the command. */
 
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 37a7614..93af44f 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -73,11 +73,11 @@ struct scsi_eh_save {
 	int result;
 	enum dma_data_direction data_direction;
 	unsigned char cmd_len;
-	unsigned char cmnd[MAX_COMMAND_SIZE];
+	unsigned char *cmnd;
 	struct scsi_data_buffer sdb;
 	struct request *next_rq;
-
 	/* new command support */
+	unsigned char eh_cmnd[BLK_MAX_CDB];
 	struct scatterlist sense_sgl;
 };
 
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 2/3] block layer varlen-cdb
  2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh
  2008-03-25 16:22 ` [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
@ 2008-03-25 16:32 ` Boaz Harrosh
  2008-04-03 16:43   ` James Bottomley
  2008-03-25 16:36 ` [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-03-25 16:32 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, Christoph Hellwig, linux-scsi,
	Andrew


- add varlen_cdb and varlen_cdb_len to hold a large user cdb
  if needed. They start as empty. Allocation of buffer must
  be done by user and held until request execution is done.
- Since there can be either a fix_length command up to 16 bytes
  or a variable_length, larger then 16 bytes, commands but never
  both, we hold the two types in a union to save space. The
  presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb
  mode.
- Please use added rq_{set,get}_varlen_cdb() to set every thing
  up in a way that will not confuse drivers that do not support
  varlen_cdb's.
- Note that this patch does not add any size to struct request
  since the unsigned cmd_len is split here to 2 ushorts, which
  is more then enough.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 block/blk-core.c       |    2 ++
 include/linux/blkdev.h |   27 +++++++++++++++++++++++++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 2a438a9..70d32f7 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq)
 	rq->end_io = NULL;
 	rq->end_io_data = NULL;
 	rq->next_rq = NULL;
+	rq->varlen_cdb_len = 0;
+	rq->varlen_cdb = NULL;
 }
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 6f79d40..f829571 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -213,8 +213,15 @@ struct request {
 	/*
 	 * when request is used as a packet command carrier
 	 */
-	unsigned int cmd_len;
-	unsigned char cmd[BLK_MAX_CDB];
+	unsigned short cmd_len;
+	unsigned short varlen_cdb_len;  /* length of varlen_cdb buffer */
+	union {
+		unsigned char cmd[BLK_MAX_CDB];
+		unsigned char *varlen_cdb;/* an optional variable-length cdb.
+	                                   * points to a user buffer that must
+	                                   * be valid until end of request
+	                                   */
+	};
 
 	unsigned int data_len;
 	unsigned int extra_len;	/* length of alignment and padding */
@@ -484,6 +491,22 @@ enum {
 #define rq_is_sync(rq)		(rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
 #define rq_is_meta(rq)		((rq)->cmd_flags & REQ_RW_META)
 
+static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short cdb_len)
+{
+	rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */
+	rq->varlen_cdb_len = cdb_len;
+	rq->varlen_cdb = cdb;
+}
+
+/* If ! a varlen_cdb than return NULL */
+static inline u8 *rq_get_varlen_cdb(struct request *rq)
+{
+	if (!rq->cmd_len && rq->varlen_cdb_len)
+		return rq->varlen_cdb;
+	else
+		return NULL;
+}
+
 static inline int blk_queue_full(struct request_queue *q, int rw)
 {
 	if (rw == READ)
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs
  2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh
  2008-03-25 16:22 ` [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
  2008-03-25 16:32 ` [PATCH 2/3] block layer varlen-cdb Boaz Harrosh
@ 2008-03-25 16:36 ` Boaz Harrosh
  2008-04-03 16:07 ` [PATCHSET 0/3] Is it time for " Boaz Harrosh
  2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh
  4 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-03-25 16:36 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, Christoph Hellwig, linux-scsi,
	Andrew


  Add support for variable-length, extended, and vendor specific
  CDBs to scsi-ml. It is now possible for initiators and ULD's
  to issue these types of commands. LLDs need not change much.
  All they need is to raise the .max_cmd_len to the longest command
  they support (see iscsi patches).

  - clean-up some code paths that did not expect commands to be
    larger than 16, and change cmd_len members' type to short as
    char is not enough.
  - Add support for varlen_cdb in scsi_execute.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
 block/scsi_ioctl.c       |    4 ++--
 drivers/scsi/constants.c |   10 +++-------
 drivers/scsi/scsi.c      |   22 +++++++++++-----------
 drivers/scsi/scsi_lib.c  |   27 ++++++++++++++++++++++-----
 include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
 include/scsi/scsi_cmnd.h |    2 +-
 include/scsi/scsi_host.h |    8 +++-----
 7 files changed, 75 insertions(+), 38 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index a2c3a93..0a83a99 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -33,13 +33,13 @@
 #include <scsi/scsi_cmnd.h>
 
 /* Command group 3 is reserved and should never be used.  */
-const unsigned char scsi_command_size[8] =
+const unsigned char scsi_command_size_tbl[8] =
 {
 	6, 10, 10, 12,
 	16, 12, 10, 10
 };
 
-EXPORT_SYMBOL(scsi_command_size);
+EXPORT_SYMBOL(scsi_command_size_tbl);
 
 #include <scsi/sg.h>
 
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 403a7f2..9785d73 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -28,7 +28,6 @@
 #define SERVICE_ACTION_OUT_12 0xa9
 #define SERVICE_ACTION_IN_16 0x9e
 #define SERVICE_ACTION_OUT_16 0x9f
-#define VARIABLE_LENGTH_CMD 0x7f
 
 
 
@@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short variable length command, "
 			       "len=%d ext_len=%d", len, cdb_len);
@@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short opcode=0x%x command, len=%d "
 			       "ext_len=%d", cdb0, len, cdb_len);
@@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
 	int k, len;
 
 	print_opcode_name(cdb, 0);
-	if (VARIABLE_LENGTH_CMD == cdb[0])
-		len = cdb[7] + 8;
-	else
-		len = COMMAND_SIZE(cdb[0]);
+	len = scsi_command_size(cdb);
 	/* print out all bytes in cdb */
 	for (k = 0; k < len; ++k) 
 		printk(" %02x", cdb[k]);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index f6980bd..3dabecb 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
 #define MIN_RESET_PERIOD (15*HZ)
 
 /*
- * Macro to determine the size of SCSI command. This macro takes vendor
- * unique commands into account. SCSI commands in groups 6 and 7 are
- * vendor unique and we will depend upon the command length being
- * supplied correctly in cmd_len.
- */
-#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
-				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 	unsigned long flags = 0;
 	unsigned long timeout;
 	int rtn = 0;
+	unsigned cmd_len;
 
 	/* check if the device is still usable */
 	if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
@@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 	 * Before we queue this command, check if the command
 	 * length exceeds what the host adapter can handle.
 	 */
-	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
+	cmd_len = cmd->cmd_len;
+	if (!cmd_len) {
+		BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD);
+		cmd_len = COMMAND_SIZE((cmd)->cmnd[0]);
+	}
+
+	if (cmd_len > cmd->device->host->max_cmd_len) {
 		SCSI_LOG_MLQUEUE(3,
-				printk("queuecommand : command too long.\n"));
+			printk("queuecommand : command too long. "
+			       "cdb_size=%d host->max_cmd_len=%d\n",
+			       cmd->cmd_len, cmd->device->host->max_cmd_len));
 		cmd->result = (DID_ABORT << 16);
 
 		scsi_done(cmd);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 75f3aab..6333126 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -193,8 +193,16 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
 					buffer, bufflen, __GFP_WAIT))
 		goto out;
 
-	req->cmd_len = COMMAND_SIZE(cmd[0]);
-	memcpy(req->cmd, cmd, req->cmd_len);
+	if (cmd[0] == VARIABLE_LENGTH_CMD)
+		rq_set_varlen_cdb(req, (u8 *)cmd, scsi_varlen_cdb_length(cmd));
+	else {
+		req->cmd_len = COMMAND_SIZE(cmd[0]);
+		memcpy(req->cmd, cmd, req->cmd_len);
+		if (req->cmd_len < MAX_COMMAND_SIZE)
+			memset(&req->cmd[req->cmd_len], 0,
+			       MAX_COMMAND_SIZE - req->cmd_len);
+	}
+
 	req->sense = sense;
 	req->sense_len = 0;
 	req->retries = retries;
@@ -445,7 +453,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 	scsi_set_resid(cmd, 0);
 	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 	if (cmd->cmd_len == 0)
-		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+		cmd->cmd_len = scsi_command_size(cmd->cmnd);
 }
 
 void scsi_device_unbusy(struct scsi_device *sdev)
@@ -1100,6 +1108,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
 int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 {
 	struct scsi_cmnd *cmd;
+	u8 *varlen_cdb;
 	int ret = scsi_prep_state_check(sdev, req);
 
 	if (ret != BLKPREP_OK)
@@ -1131,14 +1140,22 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 		req->buffer = NULL;
 	}
 
-	cmd->cmd_len = req->cmd_len;
+	varlen_cdb = rq_get_varlen_cdb(req);
+	if (varlen_cdb) {
+		cmd->cmnd = varlen_cdb;
+		cmd->cmd_len = req->varlen_cdb_len;
+	} else if (req->cmd_len)
+		cmd->cmd_len = req->cmd_len;
+	else
+		cmd->cmd_len = scsi_command_size(cmd->cmnd);
+
 	if (!req->data_len)
 		cmd->sc_data_direction = DMA_NONE;
 	else if (rq_data_dir(req) == WRITE)
 		cmd->sc_data_direction = DMA_TO_DEVICE;
 	else
 		cmd->sc_data_direction = DMA_FROM_DEVICE;
-	
+
 	cmd->transfersize = req->data_len;
 	cmd->allowed = req->retries;
 	cmd->timeout_per_command = req->timeout;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 1f74bcd..0ba902c 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -30,13 +30,6 @@
 #endif
 
 /*
- *	SCSI command lengths
- */
-
-extern const unsigned char scsi_command_size[8];
-#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
-
-/*
  * Special value for scanning to specify scanning or rescanning of all
  * possible channels, (target) ids, or luns on a given shost.
  */
@@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
 #define MODE_SENSE_10         0x5a
 #define PERSISTENT_RESERVE_IN 0x5e
 #define PERSISTENT_RESERVE_OUT 0x5f
+#define VARIABLE_LENGTH_CMD   0x7f
 #define REPORT_LUNS           0xa0
 #define MAINTENANCE_IN        0xa3
 #define MOVE_MEDIUM           0xa5
@@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8];
 #define	ATA_12		      0xa1	/* 12-byte pass-thru */
 
 /*
+ *	SCSI command lengths
+ */
+
+#define SCSI_MAX_VARLEN_CDB_SIZE 260
+
+/* defined in T10 SCSI Primary Commands-2 (SPC2) */
+struct scsi_varlen_cdb_hdr {
+	u8 opcode;        /* opcode always == VARIABLE_LENGTH_CMD */
+	u8 control;
+	u8 misc[5];
+	u8 additional_cdb_length;         /* total cdb length - 8 */
+	__be16 service_action;
+	/* service specific data follows */
+};
+
+static inline unsigned
+scsi_varlen_cdb_length(const void *hdr)
+{
+	return ((struct scsi_varlen_cdb_hdr*)hdr)->additional_cdb_length + 8;
+}
+
+extern const unsigned char scsi_command_size_tbl[8];
+#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
+
+static inline unsigned
+scsi_command_size(const unsigned char *cmnd)
+{
+	return (cmnd[0] == VARIABLE_LENGTH_CMD) ? scsi_varlen_cdb_length(cmnd) :
+	                                 COMMAND_SIZE(cmnd[0]);
+}
+
+/*
  *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
  *  T10/1561-D Revision 4 Draft dated 7th November 2002.
  */
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index dea73e5..f4dacb1 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -78,7 +78,7 @@ struct scsi_cmnd {
 	int allowed;
 	int timeout_per_command;
 
-	unsigned char cmd_len;
+	unsigned short cmd_len;
 	enum dma_data_direction sc_data_direction;
 
 	/* These elements define the operation we are about to perform */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 4913286..31f1bfd 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -573,13 +573,11 @@ struct Scsi_Host {
 	/*
 	 * The maximum length of SCSI commands that this host can accept.
 	 * Probably 12 for most host adapters, but could be 16 for others.
+	 * or 260 if the driver supports variable length cdbs.
 	 * For drivers that don't set this field, a value of 12 is
-	 * assumed.  I am leaving this as a number rather than a bit
-	 * because you never know what subsequent SCSI standards might do
-	 * (i.e. could there be a 20 byte or a 24-byte command a few years
-	 * down the road?).  
+	 * assumed.
 	 */
-	unsigned char max_cmd_len;
+	unsigned short max_cmd_len;
 
 	int this_id;
 	int can_queue;
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* Re: [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs
  2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh
                   ` (2 preceding siblings ...)
  2008-03-25 16:36 ` [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
@ 2008-04-03 16:07 ` Boaz Harrosh
  2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh
  4 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-03 16:07 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, Andrew Morton, FUJITA Tomonori
  Cc: Christoph Hellwig, linux-scsi

Boaz Harrosh wrote:
> Submitted is a patchset for adding support for variable-length, extended,
> and vendor specific CDBs. It should now cover the entire range of the 
> SCSI standard. (and/or any other use of command packets in block devices)
> 
> They are based on scsi-misc/scsi-rc-fixes/linux-block. They are aimed
> for the 2.6.26 merge window. Andrew please also include them in -mm
> for testing.
> 
ping James.

Are you giving me the other side of the boot on these patches?
Is that NO for Linux-next or NACK for never?

If it is a maybe. Could you please acknowledge a "maybe, need testing"
so they can be tested in -mm tree. A new -mm tree has passed after
I sent these patches and they are still not tested there.

ping Jens.
I need your ACK on the block bits of these patches. (patch 2/3).
There are already users that might use this facility if available.

Andrew Hi?
Could we test these patches anyway. It is a new fixture for
supporting more of the scsi standard. And a way for vendor specific
commands to any scsi/block device in a common way. Today every
driver/vendor cooks it's own char device and private ioctrls to issue
such commands. With these patches and a patch to the bsg driver that
are already used more then a year, these things could be done in one
standard way. Including very efficient way to pass large chunks of
data. The new fixture is not dangerous at all, only the first patch
is a cleanup and optimization which might be dangerous (theoretically),
hence the request for testing. I did it this way so the overall cost
of the enhancement is zero, or actually we gain a few bytes and a couple
of cycles.

These 3 patches are on a git here:
git://git.open-osd.org/open-osd.git varlen

And on the gitweb here:
http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=shortlog;h=varlen

They will be rebased from time to time ontop of latest scsi-misc/scsi-rc-fixes

Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3] block layer varlen-cdb
  2008-03-25 16:32 ` [PATCH 2/3] block layer varlen-cdb Boaz Harrosh
@ 2008-04-03 16:43   ` James Bottomley
  2008-04-03 17:26     ` Benny Halevy
  2008-04-03 18:32     ` [PATCH 2/3 ver2] block layer extended-cdb support Boaz Harrosh
  0 siblings, 2 replies; 77+ messages in thread
From: James Bottomley @ 2008-04-03 16:43 UTC (permalink / raw)
  To: Boaz Harrosh; +Cc: Jens Axboe, Christoph Hellwig, linux-scsi, Andrew Morton

On Tue, 2008-03-25 at 18:32 +0200, Boaz Harrosh wrote:
> - add varlen_cdb and varlen_cdb_len to hold a large user cdb
>   if needed. They start as empty. Allocation of buffer must
>   be done by user and held until request execution is done.
> - Since there can be either a fix_length command up to 16 bytes
>   or a variable_length, larger then 16 bytes, commands but never
>   both, we hold the two types in a union to save space. The
>   presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb
>   mode.
> - Please use added rq_{set,get}_varlen_cdb() to set every thing
>   up in a way that will not confuse drivers that do not support
>   varlen_cdb's.
> - Note that this patch does not add any size to struct request
>   since the unsigned cmd_len is split here to 2 ushorts, which
>   is more then enough.

My first observation is that the block stuff all looks a bit
misnamed ... it's not about variable length commands it's about getting
block to accept packet commands larger than BLK_MAX_CDB, be they SCSI
OSD commands or ATA taskfiles.

> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> ---
>  block/blk-core.c       |    2 ++
>  include/linux/blkdev.h |   27 +++++++++++++++++++++++++--
>  2 files changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/block/blk-core.c b/block/blk-core.c
> index 2a438a9..70d32f7 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq)
>  	rq->end_io = NULL;
>  	rq->end_io_data = NULL;
>  	rq->next_rq = NULL;
> +	rq->varlen_cdb_len = 0;
> +	rq->varlen_cdb = NULL;

possibly s/varlen/large/

>  }
>  
>  static void req_bio_endio(struct request *rq, struct bio *bio,
> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> index 6f79d40..f829571 100644
> --- a/include/linux/blkdev.h
> +++ b/include/linux/blkdev.h
> @@ -213,8 +213,15 @@ struct request {
>  	/*
>  	 * when request is used as a packet command carrier
>  	 */
> -	unsigned int cmd_len;
> -	unsigned char cmd[BLK_MAX_CDB];
> +	unsigned short cmd_len;
> +	unsigned short varlen_cdb_len;  /* length of varlen_cdb buffer */
> +	union {
> +		unsigned char cmd[BLK_MAX_CDB];
> +		unsigned char *varlen_cdb;/* an optional variable-length cdb.
> +	                                   * points to a user buffer that must
> +	                                   * be valid until end of request
> +	                                   */

again s/varlen/large/

> +	};
>  
>  	unsigned int data_len;
>  	unsigned int extra_len;	/* length of alignment and padding */
> @@ -484,6 +491,22 @@ enum {
>  #define rq_is_sync(rq)		(rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
>  #define rq_is_meta(rq)		((rq)->cmd_flags & REQ_RW_META)
>  
> +static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short cdb_len)
> +{
> +	rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */
> +	rq->varlen_cdb_len = cdb_len;
> +	rq->varlen_cdb = cdb;
> +}
> +
> +/* If ! a varlen_cdb than return NULL */
> +static inline u8 *rq_get_varlen_cdb(struct request *rq)
> +{
> +	if (!rq->cmd_len && rq->varlen_cdb_len)
> +		return rq->varlen_cdb;
> +	else
> +		return NULL;
> +}

These accessors look wrong ... I think what we want is rq_get_cdb and
rq_set_cdb that handles both <= BLK_MAX_CDB by simply a memcpy and >
BLK_MAX_CDB by setting up the large_cdb pointer.  That way we can
accessorize the whole lot and the drivers don't have to care about what
BLK_MAX_CDB is set to (it simply becomes an internal convenience of
block ... and possibly allows us to eliminate the request carries
command data entirely).

>  static inline int blk_queue_full(struct request_queue *q, int rw)
>  {
>  	if (rw == READ)

James



^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3] block layer varlen-cdb
  2008-04-03 16:43   ` James Bottomley
@ 2008-04-03 17:26     ` Benny Halevy
  2008-04-03 18:32     ` [PATCH 2/3 ver2] block layer extended-cdb support Boaz Harrosh
  1 sibling, 0 replies; 77+ messages in thread
From: Benny Halevy @ 2008-04-03 17:26 UTC (permalink / raw)
  To: James Bottomley
  Cc: Boaz Harrosh, Jens Axboe, Christoph Hellwig, linux-scsi,
	Andrew Morton

On Apr. 03, 2008, 19:43 +0300, James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> On Tue, 2008-03-25 at 18:32 +0200, Boaz Harrosh wrote:
>> - add varlen_cdb and varlen_cdb_len to hold a large user cdb
>>   if needed. They start as empty. Allocation of buffer must
>>   be done by user and held until request execution is done.
>> - Since there can be either a fix_length command up to 16 bytes
>>   or a variable_length, larger then 16 bytes, commands but never
>>   both, we hold the two types in a union to save space. The
>>   presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb
>>   mode.
>> - Please use added rq_{set,get}_varlen_cdb() to set every thing
>>   up in a way that will not confuse drivers that do not support
>>   varlen_cdb's.
>> - Note that this patch does not add any size to struct request
>>   since the unsigned cmd_len is split here to 2 ushorts, which
>>   is more then enough.
> 
> My first observation is that the block stuff all looks a bit
> misnamed ... it's not about variable length commands it's about getting
> block to accept packet commands larger than BLK_MAX_CDB, be they SCSI
> OSD commands or ATA taskfiles.
> 
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> ---
>>  block/blk-core.c       |    2 ++
>>  include/linux/blkdev.h |   27 +++++++++++++++++++++++++--
>>  2 files changed, 27 insertions(+), 2 deletions(-)
>>
>> diff --git a/block/blk-core.c b/block/blk-core.c
>> index 2a438a9..70d32f7 100644
>> --- a/block/blk-core.c
>> +++ b/block/blk-core.c
>> @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq)
>>  	rq->end_io = NULL;
>>  	rq->end_io_data = NULL;
>>  	rq->next_rq = NULL;
>> +	rq->varlen_cdb_len = 0;
>> +	rq->varlen_cdb = NULL;
> 
> possibly s/varlen/large/


If we change any names, just please do not use "large".
I'd prefer ext_cdb, where "ext" can stand for "extended" as well
as "external" (this chimes well with iSCSI naming BTW).

> 
>>  }
>>  
>>  static void req_bio_endio(struct request *rq, struct bio *bio,
>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
>> index 6f79d40..f829571 100644
>> --- a/include/linux/blkdev.h
>> +++ b/include/linux/blkdev.h
>> @@ -213,8 +213,15 @@ struct request {
>>  	/*
>>  	 * when request is used as a packet command carrier
>>  	 */
>> -	unsigned int cmd_len;
>> -	unsigned char cmd[BLK_MAX_CDB];
>> +	unsigned short cmd_len;
>> +	unsigned short varlen_cdb_len;  /* length of varlen_cdb buffer */
>> +	union {
>> +		unsigned char cmd[BLK_MAX_CDB];
>> +		unsigned char *varlen_cdb;/* an optional variable-length cdb.
>> +	                                   * points to a user buffer that must
>> +	                                   * be valid until end of request
>> +	                                   */
> 
> again s/varlen/large/
> 
>> +	};
>>  
>>  	unsigned int data_len;
>>  	unsigned int extra_len;	/* length of alignment and padding */
>> @@ -484,6 +491,22 @@ enum {
>>  #define rq_is_sync(rq)		(rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
>>  #define rq_is_meta(rq)		((rq)->cmd_flags & REQ_RW_META)
>>  
>> +static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short cdb_len)
>> +{
>> +	rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */
>> +	rq->varlen_cdb_len = cdb_len;
>> +	rq->varlen_cdb = cdb;
>> +}
>> +
>> +/* If ! a varlen_cdb than return NULL */
>> +static inline u8 *rq_get_varlen_cdb(struct request *rq)
>> +{
>> +	if (!rq->cmd_len && rq->varlen_cdb_len)
>> +		return rq->varlen_cdb;
>> +	else
>> +		return NULL;
>> +}
> 
> These accessors look wrong ... I think what we want is rq_get_cdb and
> rq_set_cdb that handles both <= BLK_MAX_CDB by simply a memcpy and >
> BLK_MAX_CDB by setting up the large_cdb pointer.  That way we can
> accessorize the whole lot and the drivers don't have to care about what
> BLK_MAX_CDB is set to (it simply becomes an internal convenience of
> block ... and possibly allows us to eliminate the request carries
> command data entirely).

That's seems like a terrific idea.

Benny

> 
>>  static inline int blk_queue_full(struct request_queue *q, int rw)
>>  {
>>  	if (rw == READ)
> 
> James
> 
> 
> --
> 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


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-03 16:43   ` James Bottomley
  2008-04-03 17:26     ` Benny Halevy
@ 2008-04-03 18:32     ` Boaz Harrosh
  2008-04-04 11:46       ` Jens Axboe
  1 sibling, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-03 18:32 UTC (permalink / raw)
  To: James Bottomley; +Cc: Jens Axboe, Christoph Hellwig, linux-scsi, Andrew Morton

James Bottomley wrote:
> On Tue, 2008-03-25 at 18:32 +0200, Boaz Harrosh wrote:
>> - add varlen_cdb and varlen_cdb_len to hold a large user cdb
>>   if needed. They start as empty. Allocation of buffer must
>>   be done by user and held until request execution is done.
>> - Since there can be either a fix_length command up to 16 bytes
>>   or a variable_length, larger then 16 bytes, commands but never
>>   both, we hold the two types in a union to save space. The
>>   presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb
>>   mode.
>> - Please use added rq_{set,get}_varlen_cdb() to set every thing
>>   up in a way that will not confuse drivers that do not support
>>   varlen_cdb's.
>> - Note that this patch does not add any size to struct request
>>   since the unsigned cmd_len is split here to 2 ushorts, which
>>   is more then enough.
> 
> My first observation is that the block stuff all looks a bit
> misnamed ... it's not about variable length commands it's about getting
> block to accept packet commands larger than BLK_MAX_CDB, be they SCSI
> OSD commands or ATA taskfiles.
> 
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> ---
>>  block/blk-core.c       |    2 ++
>>  include/linux/blkdev.h |   27 +++++++++++++++++++++++++--
>>  2 files changed, 27 insertions(+), 2 deletions(-)
>>
>> diff --git a/block/blk-core.c b/block/blk-core.c
>> index 2a438a9..70d32f7 100644
>> --- a/block/blk-core.c
>> +++ b/block/blk-core.c
>> @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq)
>>  	rq->end_io = NULL;
>>  	rq->end_io_data = NULL;
>>  	rq->next_rq = NULL;
>> +	rq->varlen_cdb_len = 0;
>> +	rq->varlen_cdb = NULL;
> 
> possibly s/varlen/large/
> 
>>  }
>>  
>>  static void req_bio_endio(struct request *rq, struct bio *bio,
>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
>> index 6f79d40..f829571 100644
>> --- a/include/linux/blkdev.h
>> +++ b/include/linux/blkdev.h
>> @@ -213,8 +213,15 @@ struct request {
>>  	/*
>>  	 * when request is used as a packet command carrier
>>  	 */
>> -	unsigned int cmd_len;
>> -	unsigned char cmd[BLK_MAX_CDB];
>> +	unsigned short cmd_len;
>> +	unsigned short varlen_cdb_len;  /* length of varlen_cdb buffer */
>> +	union {
>> +		unsigned char cmd[BLK_MAX_CDB];
>> +		unsigned char *varlen_cdb;/* an optional variable-length cdb.
>> +	                                   * points to a user buffer that must
>> +	                                   * be valid until end of request
>> +	                                   */
> 
> again s/varlen/large/
> 
>> +	};
>>  
>>  	unsigned int data_len;
>>  	unsigned int extra_len;	/* length of alignment and padding */
>> @@ -484,6 +491,22 @@ enum {
>>  #define rq_is_sync(rq)		(rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
>>  #define rq_is_meta(rq)		((rq)->cmd_flags & REQ_RW_META)
>>  
>> +static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short cdb_len)
>> +{
>> +	rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */
>> +	rq->varlen_cdb_len = cdb_len;
>> +	rq->varlen_cdb = cdb;
>> +}
>> +
>> +/* If ! a varlen_cdb than return NULL */
>> +static inline u8 *rq_get_varlen_cdb(struct request *rq)
>> +{
>> +	if (!rq->cmd_len && rq->varlen_cdb_len)
>> +		return rq->varlen_cdb;
>> +	else
>> +		return NULL;
>> +}
> 
> These accessors look wrong ... I think what we want is rq_get_cdb and
> rq_set_cdb that handles both <= BLK_MAX_CDB by simply a memcpy and >
> BLK_MAX_CDB by setting up the large_cdb pointer.  That way we can
> accessorize the whole lot and the drivers don't have to care about what
> BLK_MAX_CDB is set to (it simply becomes an internal convenience of
> block ... and possibly allows us to eliminate the request carries
> command data entirely).
> 
>>  static inline int blk_queue_full(struct request_queue *q, int rw)
>>  {
>>  	if (rw == READ)
> 
> James
> 
> 

Thanks James for your review.

With taking Benny's comments into account also, perhaps this is what you meant
(untested, for review, third patch is missing still)

Boaz
---
>From 1da591a5ef9697f37604721bfe437a2609bb8217 Mon Sep 17 00:00:00 2001
From: Boaz Harrosh <bharrosh@panasas.com>
Date: Wed, 31 Oct 2007 14:56:09 +0200
Subject: [PATCH] block layer extended-cdb support

  - add ext_cdb and ext_cdb_len to hold a large external cdb
    if needed. They start as empty. Allocation of buffer must
    be done by user and held until request execution is done.
  - Since there can be either a fix_length command up to 16 bytes
    or an external extended command but never both, we hold the two
    types in a union to save space. The presence of ext_cdb_len!=0
    and cmd_len==0 signals an ext_cdb mode.
  - Use new rq_set_cdb() to set everything up in a way that will
    not confuse drivers that do not support extended cdb's.
  - Use rq_get_cdb()/rq_get_cdb_len() to retrieve command and length
    in a generic way.
  - Once all drivers and users convert to the new accessors the cmd[]
    16 bytes buffer can be discarded.
  - Note that this patch does not add any size to struct request
    since the unsigned cmd_len is split here to 2 ushorts, which
    is more then enough.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 block/blk-core.c       |    2 ++
 include/linux/blkdev.h |   41 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 2a438a9..cc9a790 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq)
 	rq->end_io = NULL;
 	rq->end_io_data = NULL;
 	rq->next_rq = NULL;
+	rq->ext_cdb_len = 0;
+	rq->ext_cdb = NULL;
 }
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 6f79d40..2f87c9d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -213,8 +213,15 @@ struct request {
 	/*
 	 * when request is used as a packet command carrier
 	 */
-	unsigned int cmd_len;
-	unsigned char cmd[BLK_MAX_CDB];
+	unsigned short cmd_len;
+	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
+	union {
+		unsigned char cmd[BLK_MAX_CDB];
+		unsigned char *ext_cdb;/* an optional extended cdb.
+	                                   * points to a user buffer that must
+	                                   * be valid until end of request
+	                                   */
+	};
 
 	unsigned int data_len;
 	unsigned int extra_len;	/* length of alignment and padding */
@@ -484,6 +491,36 @@ enum {
 #define rq_is_sync(rq)		(rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
 #define rq_is_meta(rq)		((rq)->cmd_flags & REQ_RW_META)
 
+static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
+{
+	if (cdb_len <= BLK_MAX_CDB) {
+		memcpy(rq->cmd, cdb, cdb_len);
+		rq->cmd_len = cdb_len;
+		rq->ext_cdb_len = 0;
+	}
+	else {
+		rq->cmd_len = 0; /*Make sure legacy drivers don't get confused*/
+		rq->ext_cdb_len = cdb_len;
+		rq->ext_cdb = cdb;
+	}
+}
+
+static inline u8 *rq_get_cdb(struct request *rq)
+{
+	if (!rq->cmd_len && rq->ext_cdb_len)
+		return rq->ext_cdb;
+	else
+		return rq->cmd;
+}
+
+static inline unsigned short rq_get_cdb_len(struct request *rq)
+{
+	if (!rq->cmd_len && rq->ext_cdb_len)
+		return rq->ext_cdb_len;
+	else
+		return rq->cmd_len;
+}
+
 static inline int blk_queue_full(struct request_queue *q, int rw)
 {
 	if (rw == READ)
-- 
1.5.3.3


^ permalink raw reply related	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-03 18:32     ` [PATCH 2/3 ver2] block layer extended-cdb support Boaz Harrosh
@ 2008-04-04 11:46       ` Jens Axboe
  2008-04-06  9:35         ` Boaz Harrosh
  0 siblings, 1 reply; 77+ messages in thread
From: Jens Axboe @ 2008-04-04 11:46 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Christoph Hellwig, linux-scsi, Andrew Morton

On Thu, Apr 03 2008, Boaz Harrosh wrote:
>  static void req_bio_endio(struct request *rq, struct bio *bio,
> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> index 6f79d40..2f87c9d 100644
> --- a/include/linux/blkdev.h
> +++ b/include/linux/blkdev.h
> @@ -213,8 +213,15 @@ struct request {
>  	/*
>  	 * when request is used as a packet command carrier
>  	 */
> -	unsigned int cmd_len;
> -	unsigned char cmd[BLK_MAX_CDB];
> +	unsigned short cmd_len;
> +	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
> +	union {
> +		unsigned char cmd[BLK_MAX_CDB];
> +		unsigned char *ext_cdb;/* an optional extended cdb.
> +	                                   * points to a user buffer that must
> +	                                   * be valid until end of request
> +	                                   */
> +	};

Why not just something ala

        unsigned short cmd_len;
        unsigned char __cmd[BLK_MAX_CDB];
        unsigned char *cmd;

and then have rq_init() do

        rq->cmd = rq->__cmd;

and just have a function for setting up a larger ->cmd and adjusting
->cmd_len in the process?

Then rq_set_cdb() would be

static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
{
        rq->cmd = cdb;
        rq->cmd_len = cdb_len;
}

and rq_get_cdb() plus rq_get_cdb_len() could just go away.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-04 11:46       ` Jens Axboe
@ 2008-04-06  9:35         ` Boaz Harrosh
  2008-04-06 11:05           ` Boaz Harrosh
  2008-04-12  5:52           ` FUJITA Tomonori
  0 siblings, 2 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-06  9:35 UTC (permalink / raw)
  To: Jens Axboe; +Cc: James Bottomley, Christoph Hellwig, linux-scsi, Andrew Morton

On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> On Thu, Apr 03 2008, Boaz Harrosh wrote:
>>  static void req_bio_endio(struct request *rq, struct bio *bio,
>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
>> index 6f79d40..2f87c9d 100644
>> --- a/include/linux/blkdev.h
>> +++ b/include/linux/blkdev.h
>> @@ -213,8 +213,15 @@ struct request {
>>  	/*
>>  	 * when request is used as a packet command carrier
>>  	 */
>> -	unsigned int cmd_len;
>> -	unsigned char cmd[BLK_MAX_CDB];
>> +	unsigned short cmd_len;
>> +	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
>> +	union {
>> +		unsigned char cmd[BLK_MAX_CDB];
>> +		unsigned char *ext_cdb;/* an optional extended cdb.
>> +	                                   * points to a user buffer that must
>> +	                                   * be valid until end of request
>> +	                                   */
>> +	};
> 
> Why not just something ala
> 
>         unsigned short cmd_len;
>         unsigned char __cmd[BLK_MAX_CDB];
>         unsigned char *cmd;
> 
> and then have rq_init() do
> 
>         rq->cmd = rq->__cmd;
> 
> and just have a function for setting up a larger ->cmd and adjusting
> ->cmd_len in the process?
> 
> Then rq_set_cdb() would be
> 
> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
> {
>         rq->cmd = cdb;
>         rq->cmd_len = cdb_len;
> }
> 
> and rq_get_cdb() plus rq_get_cdb_len() could just go away.
> 

Because this way it is dangerous if large commands are issued to legacy
drivers. In scsi-land we have .cmd_len at host template that will govern if
we are allow to issue larger commands to the driver. In block devices we do
not have such a facility, and the danger is if such commands are issued through
bsg or other means, even by malicious code. What you say is the ideal and it
is what I've done for scsi, but for block devices we can not do that yet.
With the way I did it here, Legacy drivers will see zero length command and
will do the right thing, from what I've seen.

Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-06  9:35         ` Boaz Harrosh
@ 2008-04-06 11:05           ` Boaz Harrosh
  2008-04-07  8:31             ` Jens Axboe
  2008-04-12  5:52           ` FUJITA Tomonori
  1 sibling, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-06 11:05 UTC (permalink / raw)
  To: Jens Axboe; +Cc: James Bottomley, Christoph Hellwig, linux-scsi, Andrew Morton

On Sun, Apr 06 2008 at 12:35 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
>> On Thu, Apr 03 2008, Boaz Harrosh wrote:
>>>  static void req_bio_endio(struct request *rq, struct bio *bio,
>>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
>>> index 6f79d40..2f87c9d 100644
>>> --- a/include/linux/blkdev.h
>>> +++ b/include/linux/blkdev.h
>>> @@ -213,8 +213,15 @@ struct request {
>>>  	/*
>>>  	 * when request is used as a packet command carrier
>>>  	 */
>>> -	unsigned int cmd_len;
>>> -	unsigned char cmd[BLK_MAX_CDB];
>>> +	unsigned short cmd_len;
>>> +	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
>>> +	union {
>>> +		unsigned char cmd[BLK_MAX_CDB];
>>> +		unsigned char *ext_cdb;/* an optional extended cdb.
>>> +	                                   * points to a user buffer that must
>>> +	                                   * be valid until end of request
>>> +	                                   */
>>> +	};
>> Why not just something ala
>>
>>         unsigned short cmd_len;
>>         unsigned char __cmd[BLK_MAX_CDB];
>>         unsigned char *cmd;
>>
>> and then have rq_init() do
>>
>>         rq->cmd = rq->__cmd;
>>
>> and just have a function for setting up a larger ->cmd and adjusting
>> ->cmd_len in the process?
>>
>> Then rq_set_cdb() would be
>>
>> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
>> {
>>         rq->cmd = cdb;
>>         rq->cmd_len = cdb_len;
>> }
>>
>> and rq_get_cdb() plus rq_get_cdb_len() could just go away.
>>
> 
> Because this way it is dangerous if large commands are issued to legacy
> drivers. In scsi-land we have .cmd_len at host template that will govern if
> we are allow to issue larger commands to the driver. In block devices we do
> not have such a facility, and the danger is if such commands are issued through
> bsg or other means, even by malicious code. What you say is the ideal and it
> is what I've done for scsi, but for block devices we can not do that yet.
> With the way I did it here, Legacy drivers will see zero length command and
> will do the right thing, from what I've seen.
> 
> Boaz
>

I forgot to say.
With the proposed way, we are saving the space of the pointer. And the final outcome
of eventually eliminating the buffer, is the same.

Let me summarize.
- support extended, arbitrary large commands by introducing the notion that cdb space
  can be pointed to not carried.
- Eventually transition all block drivers and users to the new system, for all commands
  not just large ones.
- Do so without introducing any extra cost or instability, but also let the transition
  be done gradually, and not at once, (hence more stability).

I have thought about that long and hard, my first patch of the matter was 18 month ago.
I still think this is the smoothest way to go, and not that ugly, really.

Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-06 11:05           ` Boaz Harrosh
@ 2008-04-07  8:31             ` Jens Axboe
  0 siblings, 0 replies; 77+ messages in thread
From: Jens Axboe @ 2008-04-07  8:31 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Christoph Hellwig, linux-scsi, Andrew Morton

On Sun, Apr 06 2008, Boaz Harrosh wrote:
> On Sun, Apr 06 2008 at 12:35 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
> > On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> >> On Thu, Apr 03 2008, Boaz Harrosh wrote:
> >>>  static void req_bio_endio(struct request *rq, struct bio *bio,
> >>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> >>> index 6f79d40..2f87c9d 100644
> >>> --- a/include/linux/blkdev.h
> >>> +++ b/include/linux/blkdev.h
> >>> @@ -213,8 +213,15 @@ struct request {
> >>>  	/*
> >>>  	 * when request is used as a packet command carrier
> >>>  	 */
> >>> -	unsigned int cmd_len;
> >>> -	unsigned char cmd[BLK_MAX_CDB];
> >>> +	unsigned short cmd_len;
> >>> +	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
> >>> +	union {
> >>> +		unsigned char cmd[BLK_MAX_CDB];
> >>> +		unsigned char *ext_cdb;/* an optional extended cdb.
> >>> +	                                   * points to a user buffer that must
> >>> +	                                   * be valid until end of request
> >>> +	                                   */
> >>> +	};
> >> Why not just something ala
> >>
> >>         unsigned short cmd_len;
> >>         unsigned char __cmd[BLK_MAX_CDB];
> >>         unsigned char *cmd;
> >>
> >> and then have rq_init() do
> >>
> >>         rq->cmd = rq->__cmd;
> >>
> >> and just have a function for setting up a larger ->cmd and adjusting
> >> ->cmd_len in the process?
> >>
> >> Then rq_set_cdb() would be
> >>
> >> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
> >> {
> >>         rq->cmd = cdb;
> >>         rq->cmd_len = cdb_len;
> >> }
> >>
> >> and rq_get_cdb() plus rq_get_cdb_len() could just go away.
> >>
> > 
> > Because this way it is dangerous if large commands are issued to legacy
> > drivers. In scsi-land we have .cmd_len at host template that will govern if
> > we are allow to issue larger commands to the driver. In block devices we do
> > not have such a facility, and the danger is if such commands are issued through
> > bsg or other means, even by malicious code. What you say is the ideal and it
> > is what I've done for scsi, but for block devices we can not do that yet.
> > With the way I did it here, Legacy drivers will see zero length command and
> > will do the right thing, from what I've seen.
> > 
> > Boaz
> >
> 
> I forgot to say.
> With the proposed way, we are saving the space of the pointer. And the final outcome
> of eventually eliminating the buffer, is the same.
> 
> Let me summarize.
> - support extended, arbitrary large commands by introducing the notion that cdb space
>   can be pointed to not carried.
> - Eventually transition all block drivers and users to the new system, for all commands
>   not just large ones.
> - Do so without introducing any extra cost or instability, but also let the transition
>   be done gradually, and not at once, (hence more stability).
> 
> I have thought about that long and hard, my first patch of the matter was 18 month ago.
> I still think this is the smoothest way to go, and not that ugly, really.

OK, thanks for giving it some thought. I don't like the initial way of
doing this (I DO think it's ugly), but as long as there are plans to
make it smoother along the way, it's ok with me.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-06  9:35         ` Boaz Harrosh
  2008-04-06 11:05           ` Boaz Harrosh
@ 2008-04-12  5:52           ` FUJITA Tomonori
  2008-04-13  9:13             ` Boaz Harrosh
  2008-04-13 14:07             ` [PATCH 2/3 ver2] block layer extended-cdb support James Bottomley
  1 sibling, 2 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-12  5:52 UTC (permalink / raw)
  To: bharrosh; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm

On Sun, 06 Apr 2008 12:35:04 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> > On Thu, Apr 03 2008, Boaz Harrosh wrote:
> >>  static void req_bio_endio(struct request *rq, struct bio *bio,
> >> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> >> index 6f79d40..2f87c9d 100644
> >> --- a/include/linux/blkdev.h
> >> +++ b/include/linux/blkdev.h
> >> @@ -213,8 +213,15 @@ struct request {
> >>  	/*
> >>  	 * when request is used as a packet command carrier
> >>  	 */
> >> -	unsigned int cmd_len;
> >> -	unsigned char cmd[BLK_MAX_CDB];
> >> +	unsigned short cmd_len;
> >> +	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
> >> +	union {
> >> +		unsigned char cmd[BLK_MAX_CDB];
> >> +		unsigned char *ext_cdb;/* an optional extended cdb.
> >> +	                                   * points to a user buffer that must
> >> +	                                   * be valid until end of request
> >> +	                                   */
> >> +	};
> > 
> > Why not just something ala
> > 
> >         unsigned short cmd_len;
> >         unsigned char __cmd[BLK_MAX_CDB];
> >         unsigned char *cmd;
> > 
> > and then have rq_init() do
> > 
> >         rq->cmd = rq->__cmd;
> > 
> > and just have a function for setting up a larger ->cmd and adjusting
> > ->cmd_len in the process?
> > 
> > Then rq_set_cdb() would be
> > 
> > static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
> > {
> >         rq->cmd = cdb;
> >         rq->cmd_len = cdb_len;
> > }
> > 
> > and rq_get_cdb() plus rq_get_cdb_len() could just go away.
> > 
> 
> Because this way it is dangerous if large commands are issued to legacy
> drivers. In scsi-land we have .cmd_len at host template that will govern if
> we are allow to issue larger commands to the driver. In block devices we do
> not have such a facility, and the danger is if such commands are issued through
> bsg or other means, even by malicious code. What you say is the ideal and it
> is what I've done for scsi, but for block devices we can not do that yet.
> With the way I did it here, Legacy drivers will see zero length command and
> will do the right thing, from what I've seen.

What are exactly block devices? ub and ide?

bsg are created only for scsi devices (and scsi objects like sas host)
now. Are there other means to send commands except for ioctl?

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-12  5:52           ` FUJITA Tomonori
@ 2008-04-13  9:13             ` Boaz Harrosh
  2008-04-13 16:17               ` FUJITA Tomonori
  2008-04-13 14:07             ` [PATCH 2/3 ver2] block layer extended-cdb support James Bottomley
  1 sibling, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-13  9:13 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm

On Sat, Apr 12 2008 at 8:52 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> On Sun, 06 Apr 2008 12:35:04 +0300
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
>>> On Thu, Apr 03 2008, Boaz Harrosh wrote:
>>>>  static void req_bio_endio(struct request *rq, struct bio *bio,
>>>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
>>>> index 6f79d40..2f87c9d 100644
>>>> --- a/include/linux/blkdev.h
>>>> +++ b/include/linux/blkdev.h
>>>> @@ -213,8 +213,15 @@ struct request {
>>>>  	/*
>>>>  	 * when request is used as a packet command carrier
>>>>  	 */
>>>> -	unsigned int cmd_len;
>>>> -	unsigned char cmd[BLK_MAX_CDB];
>>>> +	unsigned short cmd_len;
>>>> +	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
>>>> +	union {
>>>> +		unsigned char cmd[BLK_MAX_CDB];
>>>> +		unsigned char *ext_cdb;/* an optional extended cdb.
>>>> +	                                   * points to a user buffer that must
>>>> +	                                   * be valid until end of request
>>>> +	                                   */
>>>> +	};
>>> Why not just something ala
>>>
>>>         unsigned short cmd_len;
>>>         unsigned char __cmd[BLK_MAX_CDB];
>>>         unsigned char *cmd;
>>>
>>> and then have rq_init() do
>>>
>>>         rq->cmd = rq->__cmd;
>>>
>>> and just have a function for setting up a larger ->cmd and adjusting
>>> ->cmd_len in the process?
>>>
>>> Then rq_set_cdb() would be
>>>
>>> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
>>> {
>>>         rq->cmd = cdb;
>>>         rq->cmd_len = cdb_len;
>>> }
>>>
>>> and rq_get_cdb() plus rq_get_cdb_len() could just go away.
>>>
>> Because this way it is dangerous if large commands are issued to legacy
>> drivers. In scsi-land we have .cmd_len at host template that will govern if
>> we are allow to issue larger commands to the driver. In block devices we do
>> not have such a facility, and the danger is if such commands are issued through
>> bsg or other means, even by malicious code. What you say is the ideal and it
>> is what I've done for scsi, but for block devices we can not do that yet.
>> With the way I did it here, Legacy drivers will see zero length command and
>> will do the right thing, from what I've seen.
> 
> What are exactly block devices? ub and ide?
> 
> bsg are created only for scsi devices (and scsi objects like sas host)
> now. Are there other means to send commands except for ioctl?

I'm not 100% sure either way, so I would like to be safe. Any way, there
is the size issue, this way we add *nothing* at all, so it looks preferable.
The final outcome will be the same both ways.

I would like if you reconsider the ugliness issue. I admit that at first I
personally disliked it, but now that I look at it, I think it is cleaner,
coding style, this way. Because the union points out the exclusiveness of
the two systems, the striate way give the notion of two separate systems.

Boaz


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-12  5:52           ` FUJITA Tomonori
  2008-04-13  9:13             ` Boaz Harrosh
@ 2008-04-13 14:07             ` James Bottomley
  2008-04-13 16:17               ` FUJITA Tomonori
  1 sibling, 1 reply; 77+ messages in thread
From: James Bottomley @ 2008-04-13 14:07 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: bharrosh, jens.axboe, hch, linux-scsi, akpm

On Sat, 2008-04-12 at 14:52 +0900, FUJITA Tomonori wrote:
> bsg are created only for scsi devices (and scsi objects like sas host)
> now. Are there other means to send commands except for ioctl?

Right now they are ... but the design was to allow for arbitrary packet
commands (like the frame in/frame out type that SMP needs), so the
anticipation is that it will be usable by arbitrary packet commands for
any block conforming device, examples of which would be ide taskfiles,
raid firmware commands and any other weirder native protocols.  On the
other hand, this is future work and won't depend on the legacy 16 byte
cmd size.

The only block device I know that implements SG_IO is cciss, so perhaps
there's no need to support a legacy mode at all for large packet
commands.

James



^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-13  9:13             ` Boaz Harrosh
@ 2008-04-13 16:17               ` FUJITA Tomonori
  2008-04-13 16:50                 ` Boaz Harrosh
  2008-04-14 10:50                 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
  0 siblings, 2 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-13 16:17 UTC (permalink / raw)
  To: bharrosh
  Cc: fujita.tomonori, jens.axboe, James.Bottomley, hch, linux-scsi,
	akpm

On Sun, 13 Apr 2008 12:13:18 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On Sat, Apr 12 2008 at 8:52 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> > On Sun, 06 Apr 2008 12:35:04 +0300
> > Boaz Harrosh <bharrosh@panasas.com> wrote:
> > 
> >> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> >>> On Thu, Apr 03 2008, Boaz Harrosh wrote:
> >>>>  static void req_bio_endio(struct request *rq, struct bio *bio,
> >>>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> >>>> index 6f79d40..2f87c9d 100644
> >>>> --- a/include/linux/blkdev.h
> >>>> +++ b/include/linux/blkdev.h
> >>>> @@ -213,8 +213,15 @@ struct request {
> >>>>  	/*
> >>>>  	 * when request is used as a packet command carrier
> >>>>  	 */
> >>>> -	unsigned int cmd_len;
> >>>> -	unsigned char cmd[BLK_MAX_CDB];
> >>>> +	unsigned short cmd_len;
> >>>> +	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
> >>>> +	union {
> >>>> +		unsigned char cmd[BLK_MAX_CDB];
> >>>> +		unsigned char *ext_cdb;/* an optional extended cdb.
> >>>> +	                                   * points to a user buffer that must
> >>>> +	                                   * be valid until end of request
> >>>> +	                                   */
> >>>> +	};
> >>> Why not just something ala
> >>>
> >>>         unsigned short cmd_len;
> >>>         unsigned char __cmd[BLK_MAX_CDB];
> >>>         unsigned char *cmd;
> >>>
> >>> and then have rq_init() do
> >>>
> >>>         rq->cmd = rq->__cmd;
> >>>
> >>> and just have a function for setting up a larger ->cmd and adjusting
> >>> ->cmd_len in the process?
> >>>
> >>> Then rq_set_cdb() would be
> >>>
> >>> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
> >>> {
> >>>         rq->cmd = cdb;
> >>>         rq->cmd_len = cdb_len;
> >>> }
> >>>
> >>> and rq_get_cdb() plus rq_get_cdb_len() could just go away.
> >>>
> >> Because this way it is dangerous if large commands are issued to legacy
> >> drivers. In scsi-land we have .cmd_len at host template that will govern if
> >> we are allow to issue larger commands to the driver. In block devices we do
> >> not have such a facility, and the danger is if such commands are issued through
> >> bsg or other means, even by malicious code. What you say is the ideal and it
> >> is what I've done for scsi, but for block devices we can not do that yet.
> >> With the way I did it here, Legacy drivers will see zero length command and
> >> will do the right thing, from what I've seen.
> > 
> > What are exactly block devices? ub and ide?
> > 
> > bsg are created only for scsi devices (and scsi objects like sas host)
> > now. Are there other means to send commands except for ioctl?
> 
> I'm not 100% sure either way, so I would like to be safe. Any way, there
> is the size issue, this way we add *nothing* at all, so it looks preferable.
> The final outcome will be the same both ways.

I think that a clean design is an important issue than the sizeof of
struct request.


> I would like if you reconsider the ugliness issue. I admit that at first I
> personally disliked it, but now that I look at it, I think it is cleaner,
> coding style, this way. Because the union points out the exclusiveness of
> the two systems, the striate way give the notion of two separate systems.

That's a ugly hack for me.

Why do we have two separate systems to represent the command length?
If the command length is smaller than 16 bytes, we use cmd_len. If the
length is larger than 16 bytes, we use varlen_cdb_len?

For me, as Jens proposed, having only cmd_len is the right way.

And 'cdb' name is not appropriate for the block layer, I think.

I agreed that changing the block layer and the scsi midlayer gradually
is a safe option. Shortly, I'll send patches to clean up the hack on
the top of your patchset.

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-13 14:07             ` [PATCH 2/3 ver2] block layer extended-cdb support James Bottomley
@ 2008-04-13 16:17               ` FUJITA Tomonori
  0 siblings, 0 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-13 16:17 UTC (permalink / raw)
  To: James.Bottomley
  Cc: fujita.tomonori, bharrosh, jens.axboe, hch, linux-scsi, akpm

On Sun, 13 Apr 2008 09:07:55 -0500
James Bottomley <James.Bottomley@HansenPartnership.com> wrote:

> On Sat, 2008-04-12 at 14:52 +0900, FUJITA Tomonori wrote:
> > bsg are created only for scsi devices (and scsi objects like sas host)
> > now. Are there other means to send commands except for ioctl?
> 
> Right now they are ... but the design was to allow for arbitrary packet
> commands (like the frame in/frame out type that SMP needs), so the
> anticipation is that it will be usable by arbitrary packet commands for
> any block conforming device, examples of which would be ide taskfiles,
> raid firmware commands and any other weirder native protocols.  On the
> other hand, this is future work and won't depend on the legacy 16 byte
> cmd size.

Yeah, we could add fc stuff to the list (James Smart said that he
could use bsg in LSF 2007).


> The only block device I know that implements SG_IO is cciss, so perhaps
> there's no need to support a legacy mode at all for large packet
> commands.

I thought that ub supports it too. I'll check the whole tree.

^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCHSET 0/4 ver2] Is it time for varlen extended and vendor-specific cdbs
  2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh
                   ` (3 preceding siblings ...)
  2008-04-03 16:07 ` [PATCHSET 0/3] Is it time for " Boaz Harrosh
@ 2008-04-13 16:30 ` Boaz Harrosh
  2008-04-13 16:37   ` [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
                     ` (3 more replies)
  4 siblings, 4 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-13 16:30 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike

Yet another iteration with James's suggestions and the 3rd patch
converted to the new block API. Also a small patch for iscsi_tcp.c

---
Submitted is a patchset for adding support for variable-length, extended,
and vendor specific CDBs. It should now cover the entire range of the 
SCSI standard, and/or any other use of command packets in block devices.

They are based on scsi-misc. They are aimed for the 2.6.26 merge window. 

Andrew !
Please include them in -mm for testing. Atleast the first patch
that no one had any comments and is the theoretically dangerous cleanup.

Difference from last time, is at struct request. I did a smallish
hack to save the extra pointer space. The pointer now shares it's
space with the request->cmd, as they are mutual exclusive. The
flag to switch between them is when cmd_len == 0 and varlen_cdb_len != 0
I've added 3 accessors to hide the mess. I think this approach
should be safe with legacy drivers.

This is on top of the size shrink to struct scsi_cmnd gained
in the first patch. We save upto 12 bytes on 32 bit ARCHs

So over all, this cleans things up, and add fixtures without
*any extra cost*.

[1/4] Let scsi_cmnd->cmnd use request->cmd buffer
  Here I let scsi_cmnd->cmnd point to the space allocated by
  request->cmd, instead of copying the data. The scsi_cmnd->cmd_len
  is guaranteed to contain the right length of the command.
  I have tried to go over every single place in the kernel that uses
  scsi_cmnd->cmnd and make sure it looks sane. Surprisingly to me,
  that was not at all bad. I hope I did not miss anything.

  I've tested on an x86_64 machine booting from a sata disk and
  ran the iscsi regression tests as well as my bidi and varlen tests
  on top of the complete patchset and all tests passed.

[2/4] block layer varlen-cd
   Here I added an option to use a user supplied buffer for an arbitrary
   large command. Buffer must be kept valid until execution of request
   ends. The pointer to the buffer shares it's space with the fixed
   length command, so the size of struct request does not change.

[3/4] scsi: varlen extended and vendor-specific cdbs
  Adds support for variable length, extended, and vendor-specific
  cdbs at the scsi mid-layer.

[4/4] iscsi_tcp: iscsi_tcp: Enable large commands
  just a one liner, Mike I need your Sign-off-by on this one.

Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer
  2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh
@ 2008-04-13 16:37   ` Boaz Harrosh
  2008-04-13 16:39   ` [PATCH 2/4] block layer extended-cdb support Boaz Harrosh
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-13 16:37 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike


 - struct scsi_cmnd had a 16 bytes command buffer of its own.
   This is an unnecessary duplication and copy of request's
   cmd. It is probably left overs from the time that scsi_cmnd
   could function without a request attached. So clean that up.

 - Once above is done, few places, apart from scsi-ml, needed
   adjustments due to changing the data type of scsi_cmnd->cmnd.

 - Lots of drivers still use MAX_COMMAND_SIZE. So I have left
   that #define but equate it to BLK_MAX_CDB. The way I see it
   and is reflected in the patch below is.
   MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB
                      as per the SCSI standard and is not related
                      to the implementation.
   BLK_MAX_CDB.     - The allocated space at the request level

 - I have audit all ISA drivers and made sure none use ->cmnd in a DMA
   Operation. Same audit was done by Andi Kleen.

(*)fixed-length here means commands that their size can be determined
   by their opcode and the CDB does not carry a length specifier, (unlike
   the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
   true and the SCSI standard also defines extended commands and
   vendor specific commands that can be bigger than 16 bytes. The kernel
   will support these using the same infrastructure used for VARLEN CDB's.
   So in effect MAX_COMMAND_SIZE means the maximum size command
   scsi-ml supports without specifying a cmd_len by ULD's

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/firewire/fw-sbp2.c       |    2 +-
 drivers/s390/scsi/zfcp_dbf.c     |    2 +-
 drivers/s390/scsi/zfcp_fsf.c     |    2 +-
 drivers/scsi/53c700.c            |    6 +++---
 drivers/scsi/a100u2w.c           |    2 +-
 drivers/scsi/gdth.c              |    2 +-
 drivers/scsi/hptiop.c            |    6 +++---
 drivers/scsi/ibmvscsi/ibmvscsi.c |    2 +-
 drivers/scsi/initio.c            |    2 +-
 drivers/scsi/qla1280.c           |    4 ++--
 drivers/scsi/scsi_error.c        |   14 ++++++++------
 drivers/scsi/scsi_lib.c          |    5 +++--
 drivers/scsi/scsi_tgt_lib.c      |    2 ++
 drivers/usb/storage/isd200.c     |    2 ++
 include/scsi/scsi_cmnd.h         |   21 +++++++++++++++++++--
 include/scsi/scsi_eh.h           |    4 ++--
 16 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 62b4e47..2260e56 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -1492,7 +1492,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 
 	memset(orb->request.command_block,
 	       0, sizeof(orb->request.command_block));
-	memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+	memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
 
 	orb->base.callback = complete_command_orb;
 	orb->base.request_bus =
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 85ba4cc..1bec0b2 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -1057,7 +1057,7 @@ static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
 				rec->scsi_result = scsi_cmnd->result;
 				rec->scsi_cmnd = (unsigned long)scsi_cmnd;
 				rec->scsi_serial = scsi_cmnd->serial_number;
-				memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+				memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
 					min((int)scsi_cmnd->cmd_len,
 						ZFCP_DBF_SCSI_OPCODE));
 				rec->scsi_retries = scsi_cmnd->retries;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index b7aa969..ea46881 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4024,7 +4024,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
 		ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n",
 			       scpnt->result);
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
-			      (void *) &scpnt->cmnd, scpnt->cmd_len);
+			      scpnt->cmnd, scpnt->cmd_len);
 
 		ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
 			       fcp_rsp_iu->fcp_sns_len);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index f4c4fe9..f5a9add 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
 			(struct NCR_700_command_slot *)SCp->host_scribble;
 		
 		dma_unmap_single(hostdata->dev, slot->pCmd,
-				 sizeof(SCp->cmnd), DMA_TO_DEVICE);
+				 MAX_COMMAND_SIZE, DMA_TO_DEVICE);
 		if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
 			char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
 #ifdef NCR_700_DEBUG
@@ -1004,7 +1004,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
 				 * here */
 				NCR_700_unmap(hostdata, SCp, slot);
 				dma_unmap_single(hostdata->dev, slot->pCmd,
-						 sizeof(SCp->cmnd),
+						 MAX_COMMAND_SIZE,
 						 DMA_TO_DEVICE);
 
 				cmnd[0] = REQUEST_SENSE;
@@ -1901,7 +1901,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	}
 	slot->resume_offset = 0;
 	slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
-				    sizeof(SCp->cmnd), DMA_TO_DEVICE);
+				    MAX_COMMAND_SIZE, DMA_TO_DEVICE);
 	NCR_700_start_command(SCp);
 	return 0;
 }
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 792b2e8..ced3eeb 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -895,7 +895,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru
 	} else {
 		scb->tag_msg = 0;	/* No tag support               */
 	}
-	memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len);
+	memcpy(scb->cdb, cmd->cmnd, scb->cdb_len);
 }
 
 /**
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index c6d6e7c..8e2e964 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -465,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
     scp->request = (struct request *)&wait;
     scp->timeout_per_command = timeout*HZ;
     scp->cmd_len = 12;
-    memcpy(scp->cmnd, cmnd, 12);
+    scp->cmnd = cmnd;
     cmndinfo.priority = IOCTL_PRI;
     cmndinfo.internal_cmd_str = gdtcmd;
     cmndinfo.internal_command = 1;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index beecda9..a24c5e3 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -763,9 +763,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 			scp,
 			host->host_no, scp->device->channel,
 			scp->device->id, scp->device->lun,
-			*((u32 *)&scp->cmnd),
-			*((u32 *)&scp->cmnd + 1),
-			*((u32 *)&scp->cmnd + 2),
+			((u32 *)scp->cmnd)[0],
+			((u32 *)scp->cmnd)[1],
+			((u32 *)scp->cmnd)[2],
 			_req->index, _req->req_virt);
 
 	scp->result = 0;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 78d46a9..df9b865 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -738,7 +738,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 	srp_cmd = &evt_struct->iu.srp.cmd;
 	memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
 	srp_cmd->opcode = SRP_CMD;
-	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb));
 	srp_cmd->lun = ((u64) lun) << 48;
 
 	if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index dbae3fd..e3f7397 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
 	cblk->hastat = 0;
 	cblk->tastat = 0;
 	/* Command the command */
-	memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
+	memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len);
 
 	/* Set up tags */
 	if (cmnd->device->tagged_supported) {	/* Tag Support                  */
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 68c0d09..b53420b 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -2863,7 +2863,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
 
 	/* Load SCSI command packet. */
 	pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
-	memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+	memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
 	/* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
 
 	/* Set transfer direction. */
@@ -3132,7 +3132,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
 
 	/* Load SCSI command packet. */
 	pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
-	memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+	memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
 
 	/*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
 	/* Set transfer direction. */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 221f31e..8b5748a 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -626,7 +626,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
  * @scmd:       SCSI command structure to hijack
  * @ses:        structure to save restore information
  * @cmnd:       CDB to send. Can be NULL if no new cmnd is needed
- * @cmnd_size:  size in bytes of @cmnd
+ * @cmnd_size:  size in bytes of @cmnd (must be <= BLK_MAX_CDB)
  * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
  *
  * This function is used to save a scsi command information before re-execution
@@ -648,12 +648,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
 	 * command.
 	 */
 	ses->cmd_len = scmd->cmd_len;
-	memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
+	ses->cmnd = scmd->cmnd;
 	ses->data_direction = scmd->sc_data_direction;
 	ses->sdb = scmd->sdb;
 	ses->next_rq = scmd->request->next_rq;
 	ses->result = scmd->result;
 
+	scmd->cmnd = ses->eh_cmnd;
+	memset(scmd->cmnd, 0, BLK_MAX_CDB);
 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
 	scmd->request->next_rq = NULL;
 
@@ -665,14 +667,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
 		scmd->sdb.table.sgl = &ses->sense_sgl;
 		scmd->sc_data_direction = DMA_FROM_DEVICE;
 		scmd->sdb.table.nents = 1;
-		memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
 		scmd->cmnd[0] = REQUEST_SENSE;
 		scmd->cmnd[4] = scmd->sdb.length;
 		scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 	} else {
 		scmd->sc_data_direction = DMA_NONE;
 		if (cmnd) {
-			memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+			BUG_ON(cmnd_size > BLK_MAX_CDB);
 			memcpy(scmd->cmnd, cmnd, cmnd_size);
 			scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 		}
@@ -705,7 +706,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
 	 * Restore original data
 	 */
 	scmd->cmd_len = ses->cmd_len;
-	memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
+	scmd->cmnd = ses->cmnd;
 	scmd->sc_data_direction = ses->data_direction;
 	scmd->sdb = ses->sdb;
 	scmd->request->next_rq = ses->next_rq;
@@ -1774,7 +1775,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
 	scmd->request = &req;
 	memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
 
-	memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
+	scmd->cmnd = req.cmd;
+	memset(scmd->cmnd, 0, BLK_MAX_CDB);
     
 	scmd->scsi_done		= scsi_reset_provider_done_command;
 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 67f412b..325270b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1090,6 +1090,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
 	cmd->tag = req->tag;
 	cmd->request = req;
 
+	cmd->cmnd = req->cmd;
+
 	return cmd;
 }
 
@@ -1127,8 +1129,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 		req->buffer = NULL;
 	}
 
-	BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd));
-	memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
 	cmd->cmd_len = req->cmd_len;
 	if (!req->data_len)
 		cmd->sc_data_direction = DMA_NONE;
@@ -1165,6 +1165,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
 	if (unlikely(!cmd))
 		return BLKPREP_DEFER;
 
+	memset(cmd->cmnd, 0, BLK_MAX_CDB);
 	return scsi_init_io(cmd, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(scsi_setup_fs_cmnd);
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index a0f308b..8c92ef3 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -107,6 +107,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
 	cmd->jiffies_at_alloc = jiffies;
 	cmd->request = rq;
 
+	cmd->cmnd = rq->cmd;
+
 	rq->special = cmd;
 	rq->cmd_type = REQ_TYPE_SPECIAL;
 	rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 971d13d..3addcd8 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -292,6 +292,7 @@ struct isd200_info {
 
 	/* maximum number of LUNs supported */
 	unsigned char MaxLUNs;
+	unsigned char cmnd[BLK_MAX_CDB];
 	struct scsi_cmnd srb;
 	struct scatterlist sg;
 };
@@ -450,6 +451,7 @@ static int isd200_action( struct us_data *us, int action,
 
 	memset(&ata, 0, sizeof(ata));
 	memset(&srb_dev, 0, sizeof(srb_dev));
+	srb->cmnd = info->cmnd;
 	srb->device = &srb_dev;
 	++srb->serial_number;
 
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 8d20e60..dea73e5 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -7,10 +7,28 @@
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/scatterlist.h>
+#include <linux/blkdev.h>
 
 struct Scsi_Host;
 struct scsi_device;
 
+/*
+ * MAX_COMMAND_SIZE is:
+ * The longest fixed-length SCSI CDB as per the SCSI standard.
+ * fixed-length means: commands that their size can be determined
+ * by their opcode and the CDB does not carry a length specifier, (unlike
+ * the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
+ * true and the SCSI standard also defines extended commands and
+ * vendor specific commands that can be bigger than 16 bytes. The kernel
+ * will support these using the same infrastructure used for VARLEN CDB's.
+ * So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml
+ * supports without specifying a cmd_len by ULD's
+ */
+#define MAX_COMMAND_SIZE 16
+#if (MAX_COMMAND_SIZE > BLK_MAX_CDB)
+# error MAX_COMMAND_SIZE can not be smaller than BLK_MAX_CDB
+#endif
+
 struct scsi_data_buffer {
 	struct sg_table table;
 	unsigned length;
@@ -64,8 +82,7 @@ struct scsi_cmnd {
 	enum dma_data_direction sc_data_direction;
 
 	/* These elements define the operation we are about to perform */
-#define MAX_COMMAND_SIZE	16
-	unsigned char cmnd[MAX_COMMAND_SIZE];
+	unsigned char *cmnd;
 
 	struct timer_list eh_timeout;	/* Used to time out the command. */
 
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index d3a133b..2a9add2 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -75,11 +75,11 @@ struct scsi_eh_save {
 	int result;
 	enum dma_data_direction data_direction;
 	unsigned char cmd_len;
-	unsigned char cmnd[MAX_COMMAND_SIZE];
+	unsigned char *cmnd;
 	struct scsi_data_buffer sdb;
 	struct request *next_rq;
-
 	/* new command support */
+	unsigned char eh_cmnd[BLK_MAX_CDB];
 	struct scatterlist sense_sgl;
 };
 
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 2/4] block layer extended-cdb support
  2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh
  2008-04-13 16:37   ` [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
@ 2008-04-13 16:39   ` Boaz Harrosh
  2008-04-13 16:39   ` [PATCH 3/4] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
  2008-04-13 16:41   ` [PATCH 4/4] iscsi_tcp: Enable large command Boaz Harrosh
  3 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-13 16:39 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike


  - add ext_cdb and ext_cdb_len to hold a large external cdb
    if needed. They start as empty. Allocation of buffer must
    be done by user and held until request execution is done.
  - Since there can be either a fix_length command up to 16 bytes
    or an external extended command but never both, we hold the two
    types in a union to save space. The presence of ext_cdb_len!=0
    and cmd_len==0 signals an ext_cdb mode.
  - Use new rq_set_cdb() to set everything up in a way that will
    not confuse drivers that do not support extended cdb's.
  - Use rq_get_cdb()/rq_get_cdb_len() to retrieve command and length
    in a generic way.
  - Once all drivers and users convert to the new accessors the cmd[]
    16 bytes buffer can be discarded.
  - Note that this patch does not add any size to struct request
    since the unsigned cmd_len is split here to 2 ushorts, which
    is more then enough.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 block/blk-core.c       |    2 ++
 include/linux/blkdev.h |   41 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 2a438a9..cc9a790 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq)
 	rq->end_io = NULL;
 	rq->end_io_data = NULL;
 	rq->next_rq = NULL;
+	rq->ext_cdb_len = 0;
+	rq->ext_cdb = NULL;
 }
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 6f79d40..2f87c9d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -213,8 +213,15 @@ struct request {
 	/*
 	 * when request is used as a packet command carrier
 	 */
-	unsigned int cmd_len;
-	unsigned char cmd[BLK_MAX_CDB];
+	unsigned short cmd_len;
+	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
+	union {
+		unsigned char cmd[BLK_MAX_CDB];
+		unsigned char *ext_cdb;/* an optional extended cdb.
+	                                   * points to a user buffer that must
+	                                   * be valid until end of request
+	                                   */
+	};
 
 	unsigned int data_len;
 	unsigned int extra_len;	/* length of alignment and padding */
@@ -484,6 +491,36 @@ enum {
 #define rq_is_sync(rq)		(rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
 #define rq_is_meta(rq)		((rq)->cmd_flags & REQ_RW_META)
 
+static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
+{
+	if (cdb_len <= BLK_MAX_CDB) {
+		memcpy(rq->cmd, cdb, cdb_len);
+		rq->cmd_len = cdb_len;
+		rq->ext_cdb_len = 0;
+	}
+	else {
+		rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */
+		rq->ext_cdb_len = cdb_len;
+		rq->ext_cdb = cdb;
+	}
+}
+
+static inline u8 *rq_get_cdb(struct request *rq)
+{
+	if (!rq->cmd_len && rq->ext_cdb_len)
+		return rq->ext_cdb;
+	else
+		return rq->cmd;
+}
+
+static inline unsigned short rq_get_cdb_len(struct request *rq)
+{
+	if (!rq->cmd_len && rq->ext_cdb_len)
+		return rq->ext_cdb_len;
+	else
+		return rq->cmd_len;
+}
+
 static inline int blk_queue_full(struct request_queue *q, int rw)
 {
 	if (rw == READ)
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 3/4] scsi: varlen extended and vendor-specific cdbs
  2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh
  2008-04-13 16:37   ` [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
  2008-04-13 16:39   ` [PATCH 2/4] block layer extended-cdb support Boaz Harrosh
@ 2008-04-13 16:39   ` Boaz Harrosh
  2008-04-13 16:41   ` [PATCH 4/4] iscsi_tcp: Enable large command Boaz Harrosh
  3 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-13 16:39 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike


  Add support for variable-length, extended, and vendor specific
  CDBs to scsi-ml. It is now possible for initiators and ULD's
  to issue these types of commands. LLDs need not change much.
  All they need is to raise the .max_cmd_len to the longest command
  they support (see iscsi patches).

  - clean-up some code paths that did not expect commands to be
    larger than 16, and change cmd_len members' type to short as
    char is not enough.
  - Add support for varlen_cdb in scsi_execute.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
 block/scsi_ioctl.c       |    4 ++--
 drivers/scsi/constants.c |   10 +++-------
 drivers/scsi/scsi.c      |   22 +++++++++++-----------
 drivers/scsi/scsi_lib.c  |   18 ++++++++++++------
 include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
 include/scsi/scsi_cmnd.h |    2 +-
 include/scsi/scsi_host.h |    8 +++-----
 7 files changed, 65 insertions(+), 39 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index a2c3a93..0a83a99 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -33,13 +33,13 @@
 #include <scsi/scsi_cmnd.h>
 
 /* Command group 3 is reserved and should never be used.  */
-const unsigned char scsi_command_size[8] =
+const unsigned char scsi_command_size_tbl[8] =
 {
 	6, 10, 10, 12,
 	16, 12, 10, 10
 };
 
-EXPORT_SYMBOL(scsi_command_size);
+EXPORT_SYMBOL(scsi_command_size_tbl);
 
 #include <scsi/sg.h>
 
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 403a7f2..9785d73 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -28,7 +28,6 @@
 #define SERVICE_ACTION_OUT_12 0xa9
 #define SERVICE_ACTION_IN_16 0x9e
 #define SERVICE_ACTION_OUT_16 0x9f
-#define VARIABLE_LENGTH_CMD 0x7f
 
 
 
@@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short variable length command, "
 			       "len=%d ext_len=%d", len, cdb_len);
@@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short opcode=0x%x command, len=%d "
 			       "ext_len=%d", cdb0, len, cdb_len);
@@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
 	int k, len;
 
 	print_opcode_name(cdb, 0);
-	if (VARIABLE_LENGTH_CMD == cdb[0])
-		len = cdb[7] + 8;
-	else
-		len = COMMAND_SIZE(cdb[0]);
+	len = scsi_command_size(cdb);
 	/* print out all bytes in cdb */
 	for (k = 0; k < len; ++k) 
 		printk(" %02x", cdb[k]);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index f6980bd..3dabecb 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
 #define MIN_RESET_PERIOD (15*HZ)
 
 /*
- * Macro to determine the size of SCSI command. This macro takes vendor
- * unique commands into account. SCSI commands in groups 6 and 7 are
- * vendor unique and we will depend upon the command length being
- * supplied correctly in cmd_len.
- */
-#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
-				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 	unsigned long flags = 0;
 	unsigned long timeout;
 	int rtn = 0;
+	unsigned cmd_len;
 
 	/* check if the device is still usable */
 	if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
@@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 	 * Before we queue this command, check if the command
 	 * length exceeds what the host adapter can handle.
 	 */
-	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
+	cmd_len = cmd->cmd_len;
+	if (!cmd_len) {
+		BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD);
+		cmd_len = COMMAND_SIZE((cmd)->cmnd[0]);
+	}
+
+	if (cmd_len > cmd->device->host->max_cmd_len) {
 		SCSI_LOG_MLQUEUE(3,
-				printk("queuecommand : command too long.\n"));
+			printk("queuecommand : command too long. "
+			       "cdb_size=%d host->max_cmd_len=%d\n",
+			       cmd->cmd_len, cmd->device->host->max_cmd_len));
 		cmd->result = (DID_ABORT << 16);
 
 		scsi_done(cmd);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 325270b..76cd886 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -193,8 +193,11 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
 					buffer, bufflen, __GFP_WAIT))
 		goto out;
 
-	req->cmd_len = COMMAND_SIZE(cmd[0]);
-	memcpy(req->cmd, cmd, req->cmd_len);
+	rq_set_cdb(req, (u8 *)cmd, scsi_command_size(cmd));
+	if (rq_get_cdb_len(req) < MAX_COMMAND_SIZE)
+		memset(&req->cmd[req->cmd_len], 0,
+					MAX_COMMAND_SIZE - req->cmd_len);
+
 	req->sense = sense;
 	req->sense_len = 0;
 	req->retries = retries;
@@ -445,7 +448,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 	scsi_set_resid(cmd, 0);
 	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 	if (cmd->cmd_len == 0)
-		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+		cmd->cmd_len = scsi_command_size(cmd->cmnd);
 }
 
 void scsi_device_unbusy(struct scsi_device *sdev)
@@ -1090,7 +1093,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
 	cmd->tag = req->tag;
 	cmd->request = req;
 
-	cmd->cmnd = req->cmd;
+	cmd->cmnd = rq_get_cdb(req);
 
 	return cmd;
 }
@@ -1129,14 +1132,17 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 		req->buffer = NULL;
 	}
 
-	cmd->cmd_len = req->cmd_len;
+	cmd->cmd_len = rq_get_cdb_len(req);
+	if (!cmd->cmd_len)
+		cmd->cmd_len = scsi_command_size(cmd->cmnd);
+
 	if (!req->data_len)
 		cmd->sc_data_direction = DMA_NONE;
 	else if (rq_data_dir(req) == WRITE)
 		cmd->sc_data_direction = DMA_TO_DEVICE;
 	else
 		cmd->sc_data_direction = DMA_FROM_DEVICE;
-	
+
 	cmd->transfersize = req->data_len;
 	cmd->allowed = req->retries;
 	cmd->timeout_per_command = req->timeout;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 1f74bcd..0ba902c 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -30,13 +30,6 @@
 #endif
 
 /*
- *	SCSI command lengths
- */
-
-extern const unsigned char scsi_command_size[8];
-#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
-
-/*
  * Special value for scanning to specify scanning or rescanning of all
  * possible channels, (target) ids, or luns on a given shost.
  */
@@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
 #define MODE_SENSE_10         0x5a
 #define PERSISTENT_RESERVE_IN 0x5e
 #define PERSISTENT_RESERVE_OUT 0x5f
+#define VARIABLE_LENGTH_CMD   0x7f
 #define REPORT_LUNS           0xa0
 #define MAINTENANCE_IN        0xa3
 #define MOVE_MEDIUM           0xa5
@@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8];
 #define	ATA_12		      0xa1	/* 12-byte pass-thru */
 
 /*
+ *	SCSI command lengths
+ */
+
+#define SCSI_MAX_VARLEN_CDB_SIZE 260
+
+/* defined in T10 SCSI Primary Commands-2 (SPC2) */
+struct scsi_varlen_cdb_hdr {
+	u8 opcode;        /* opcode always == VARIABLE_LENGTH_CMD */
+	u8 control;
+	u8 misc[5];
+	u8 additional_cdb_length;         /* total cdb length - 8 */
+	__be16 service_action;
+	/* service specific data follows */
+};
+
+static inline unsigned
+scsi_varlen_cdb_length(const void *hdr)
+{
+	return ((struct scsi_varlen_cdb_hdr*)hdr)->additional_cdb_length + 8;
+}
+
+extern const unsigned char scsi_command_size_tbl[8];
+#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
+
+static inline unsigned
+scsi_command_size(const unsigned char *cmnd)
+{
+	return (cmnd[0] == VARIABLE_LENGTH_CMD) ? scsi_varlen_cdb_length(cmnd) :
+	                                 COMMAND_SIZE(cmnd[0]);
+}
+
+/*
  *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
  *  T10/1561-D Revision 4 Draft dated 7th November 2002.
  */
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index dea73e5..f4dacb1 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -78,7 +78,7 @@ struct scsi_cmnd {
 	int allowed;
 	int timeout_per_command;
 
-	unsigned char cmd_len;
+	unsigned short cmd_len;
 	enum dma_data_direction sc_data_direction;
 
 	/* These elements define the operation we are about to perform */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 4913286..31f1bfd 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -573,13 +573,11 @@ struct Scsi_Host {
 	/*
 	 * The maximum length of SCSI commands that this host can accept.
 	 * Probably 12 for most host adapters, but could be 16 for others.
+	 * or 260 if the driver supports variable length cdbs.
 	 * For drivers that don't set this field, a value of 12 is
-	 * assumed.  I am leaving this as a number rather than a bit
-	 * because you never know what subsequent SCSI standards might do
-	 * (i.e. could there be a 20 byte or a 24-byte command a few years
-	 * down the road?).  
+	 * assumed.
 	 */
-	unsigned char max_cmd_len;
+	unsigned short max_cmd_len;
 
 	int this_id;
 	int can_queue;
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 4/4] iscsi_tcp: Enable large command
  2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh
                     ` (2 preceding siblings ...)
  2008-04-13 16:39   ` [PATCH 3/4] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
@ 2008-04-13 16:41   ` Boaz Harrosh
  2008-04-18 17:11     ` Mike Christie
  3 siblings, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-13 16:41 UTC (permalink / raw)
  To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike


Let through up to the largest command of 260 defined by the scsi standard.
iscsi core supports this already. Now that the scsi-ml supports it we can
start using large commands.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/iscsi_tcp.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 555f4e3..6500192 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1859,7 +1859,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
 	shost->max_lun = iscsi_max_lun;
 	shost->max_id = 0;
 	shost->max_channel = 0;
-	shost->max_cmd_len = 16;
+	shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
 	shost->can_queue = cmds_max;
 
 	if (iscsi_host_add(shost, NULL))
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-13 16:17               ` FUJITA Tomonori
@ 2008-04-13 16:50                 ` Boaz Harrosh
  2008-04-14  9:49                   ` [PATCH 2/3 ver3] " Boaz Harrosh
  2008-04-14 11:04                   ` [PATCH 2/3 ver2] " FUJITA Tomonori
  2008-04-14 10:50                 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
  1 sibling, 2 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-13 16:50 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm

On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> On Sun, 13 Apr 2008 12:13:18 +0300
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> On Sat, Apr 12 2008 at 8:52 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
>>> On Sun, 06 Apr 2008 12:35:04 +0300
>>> Boaz Harrosh <bharrosh@panasas.com> wrote:
>>>
>>>> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
>>>>> On Thu, Apr 03 2008, Boaz Harrosh wrote:
>>>>>>  static void req_bio_endio(struct request *rq, struct bio *bio,
>>>>>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
>>>>>> index 6f79d40..2f87c9d 100644
>>>>>> --- a/include/linux/blkdev.h
>>>>>> +++ b/include/linux/blkdev.h
>>>>>> @@ -213,8 +213,15 @@ struct request {
>>>>>>  	/*
>>>>>>  	 * when request is used as a packet command carrier
>>>>>>  	 */
>>>>>> -	unsigned int cmd_len;
>>>>>> -	unsigned char cmd[BLK_MAX_CDB];
>>>>>> +	unsigned short cmd_len;
>>>>>> +	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
>>>>>> +	union {
>>>>>> +		unsigned char cmd[BLK_MAX_CDB];
>>>>>> +		unsigned char *ext_cdb;/* an optional extended cdb.
>>>>>> +	                                   * points to a user buffer that must
>>>>>> +	                                   * be valid until end of request
>>>>>> +	                                   */
>>>>>> +	};
>>>>> Why not just something ala
>>>>>
>>>>>         unsigned short cmd_len;
>>>>>         unsigned char __cmd[BLK_MAX_CDB];
>>>>>         unsigned char *cmd;
>>>>>
>>>>> and then have rq_init() do
>>>>>
>>>>>         rq->cmd = rq->__cmd;
>>>>>
>>>>> and just have a function for setting up a larger ->cmd and adjusting
>>>>> ->cmd_len in the process?
>>>>>
>>>>> Then rq_set_cdb() would be
>>>>>
>>>>> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
>>>>> {
>>>>>         rq->cmd = cdb;
>>>>>         rq->cmd_len = cdb_len;
>>>>> }
>>>>>
>>>>> and rq_get_cdb() plus rq_get_cdb_len() could just go away.
>>>>>
>>>> Because this way it is dangerous if large commands are issued to legacy
>>>> drivers. In scsi-land we have .cmd_len at host template that will govern if
>>>> we are allow to issue larger commands to the driver. In block devices we do
>>>> not have such a facility, and the danger is if such commands are issued through
>>>> bsg or other means, even by malicious code. What you say is the ideal and it
>>>> is what I've done for scsi, but for block devices we can not do that yet.
>>>> With the way I did it here, Legacy drivers will see zero length command and
>>>> will do the right thing, from what I've seen.
>>> What are exactly block devices? ub and ide?
>>>
>>> bsg are created only for scsi devices (and scsi objects like sas host)
>>> now. Are there other means to send commands except for ioctl?
>> I'm not 100% sure either way, so I would like to be safe. Any way, there
>> is the size issue, this way we add *nothing* at all, so it looks preferable.
>> The final outcome will be the same both ways.
> 
> I think that a clean design is an important issue than the sizeof of
> struct request.
> 
> 
>> I would like if you reconsider the ugliness issue. I admit that at first I
>> personally disliked it, but now that I look at it, I think it is cleaner,
>> coding style, this way. Because the union points out the exclusiveness of
>> the two systems, the striate way give the notion of two separate systems.
> 
> That's a ugly hack for me.
> 
> Why do we have two separate systems to represent the command length?
> If the command length is smaller than 16 bytes, we use cmd_len. If the
> length is larger than 16 bytes, we use varlen_cdb_len?
> 
> For me, as Jens proposed, having only cmd_len is the right way.
> 
> And 'cdb' name is not appropriate for the block layer, I think.
> 
> I agreed that changing the block layer and the scsi midlayer gradually
> is a safe option. Shortly, I'll send patches to clean up the hack on
> the top of your patchset.
> --

Sorry TOMO, I was sending the ver2 patchset and only saw your mail in
the middle, so anyway you have the latest I have now.

If it's ok with you I will squash your patches onto mine and add your
sign-off-by. There is no use putting code in the tree that will be changed
immediately after.

Please note that I'm a bit afraid to put code that has both length as one
if you are more confident then me, I will take your word for it.

Thanks for helping out, as you can see I did it very safe, but with your
help maybe it can finally go in. Thanks++

Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCH 2/3 ver3] block layer extended-cdb support
  2008-04-13 16:50                 ` Boaz Harrosh
@ 2008-04-14  9:49                   ` Boaz Harrosh
  2008-04-14 11:04                     ` FUJITA Tomonori
  2008-04-14 11:04                   ` [PATCH 2/3 ver2] " FUJITA Tomonori
  1 sibling, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-14  9:49 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm

On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
>> On Sun, 13 Apr 2008 12:13:18 +0300
>> Boaz Harrosh <bharrosh@panasas.com> wrote:
>>
>> That's a ugly hack for me.
>>
>> Why do we have two separate systems to represent the command length?
>> If the command length is smaller than 16 bytes, we use cmd_len. If the
>> length is larger than 16 bytes, we use varlen_cdb_len?
>>
>> For me, as Jens proposed, having only cmd_len is the right way.
>>
>> And 'cdb' name is not appropriate for the block layer, I think.
>>
>> I agreed that changing the block layer and the scsi midlayer gradually
>> is a safe option. Shortly, I'll send patches to clean up the hack on
>> the top of your patchset.
>> --
> 
> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in
> the middle, so anyway you have the latest I have now.
> 
> If it's ok with you I will squash your patches onto mine and add your
> sign-off-by. There is no use putting code in the tree that will be changed
> immediately after.
> 
> Please note that I'm a bit afraid to put code that has both length as one
> if you are more confident then me, I will take your word for it.
> 
> Thanks for helping out, as you can see I did it very safe, but with your
> help maybe it can finally go in. Thanks++
> 
> Boaz
> --
Maybe you mean something like below. I changed cdb => cmd and I use one
cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB
right there next to it. But if you don't like it then I don't mind to
change the name, I think it was James idea.

But please note!!!
I think having one cmd_len is DANGEROUS. And it forces a full code audit
to be sure, has with my approach we are much more safe. There, I said it.

---
From: Boaz Harrosh <bharrosh@panasas.com>
Date: Wed, 31 Oct 2007 14:56:09 +0200
Subject: [PATCH] block layer extended-command support

  - add ext_cmd to hold a large external cdb if needed. Allocation
    of buffer must be done by user and held until request execution
    is done.
  - Since there can be either a fix_length command up to 16 bytes
    or an external extended command but never both, we hold the two
    types in a union to save space. cmd_len > BLK_MAX_CDB signals
    an ext_cmd mode.
  - Use new rq_set_cmd() to set everything properly.
  - Use rq_get_cmd() to retrieve the command in a generic way.
  - Once all drivers and users convert to the new accessors the cmd[]
    16 bytes buffer can be discarded.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 block/blk-core.c       |    2 ++
 include/linux/blkdev.h |   25 ++++++++++++++++++++++++-
 2 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 2a438a9..a2bf07f 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq)
 	rq->end_io = NULL;
 	rq->end_io_data = NULL;
 	rq->next_rq = NULL;
+	rq->cmd_len = 0;
+	rq->ext_cmd = NULL;
 }
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 6f79d40..0c4f5f5 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -214,7 +214,13 @@ struct request {
 	 * when request is used as a packet command carrier
 	 */
 	unsigned int cmd_len;
-	unsigned char cmd[BLK_MAX_CDB];
+	union {
+		unsigned char cmd[BLK_MAX_CDB];
+		unsigned char *ext_cmd;/* an optional extended cdb.
+	                                   * points to a user buffer that must
+	                                   * be valid until end of request
+	                                   */
+	};
 
 	unsigned int data_len;
 	unsigned int extra_len;	/* length of alignment and padding */
@@ -484,6 +490,23 @@ enum {
 #define rq_is_sync(rq)		(rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
 #define rq_is_meta(rq)		((rq)->cmd_flags & REQ_RW_META)
 
+static inline void rq_set_cmd(struct request *rq, u8 *cmd, short cmd_len)
+{
+	rq->cmd_len = cmd_len;
+	if (cmd_len <= BLK_MAX_CDB)
+		memcpy(rq->cmd, cmd, cmd_len);
+	else
+		rq->ext_cmd = cmd;
+}
+
+static inline u8 *rq_get_cmd(struct request *rq)
+{
+	if (rq->cmd_len <= BLK_MAX_CDB)
+		return rq->cmd;
+	else
+		return rq->ext_cmd;
+}
+
 static inline int blk_queue_full(struct request_queue *q, int rw)
 {
 	if (rw == READ)
-- 
1.5.3.3

 




^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 0/4] add large command support to the block layer
  2008-04-13 16:17               ` FUJITA Tomonori
  2008-04-13 16:50                 ` Boaz Harrosh
@ 2008-04-14 10:50                 ` FUJITA Tomonori
  2008-04-14 10:50                   ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori
                                     ` (3 more replies)
  1 sibling, 4 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw)
  To: linux-scsi
  Cc: bharrosh, Jens Axboe, Bartlomiej Zolnierkiewicz, James Bottomley,
	Alasdair G Kergon, Geert Uytterhoeven, FUJITA Tomonori

This patchset adds large command support to the block layer.

We rarely handle large commands. So for optimization, a struct request
still has a static array for a command. rq_init sets rq->cmd pointer
to the static array. In short, rq_init() does

rq->cmd = rq->__cmd;

So we can access to rq->cmd and rq->cmd_len as before.

Boaz argues that having single cmd_len is dangerous:

> Because this way it is dangerous if large commands are issued to legacy
> drivers. In scsi-land we have .cmd_len at host template that will govern if
> we are allow to issue larger commands to the driver. In block devices we do
> not have such a facility, and the danger is if such commands are issued through
> bsg or other means, even by malicious code. What you say is the ideal and it

I don't see how it is dangerous. We don't send large commands to block
devices via bsg. We can send large commands to block devices via only
SG_IO. SG_IO (block/scsi_ioctl.c) forbids us sending commands large
than 16 bytes, BLK_MAX_CDB. So how can we send large commands to block
devices?

The first, second, and third patches are safe cleanups (a preparation
for changing rq->cmd from the static array to a pointer). They don't
conflict with Boaz's patchset. Even if we choose Boaz's approach now,
we'll move to the approach to have one command length in struct
request in the long term. So they can be applied now.

The forth patch adds large command support. It's a substitute for
Boaz's second patch. It's pretty simple except for one hack for
ide-io. It's necessary since the ide subsystem allocates struct
request without using blk_get_request. In the long term, it would
better to convert it to use blk_get_request properly.



^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook
  2008-04-14 10:50                 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
@ 2008-04-14 10:50                   ` FUJITA Tomonori
  2008-04-14 10:50                     ` [PATCH 2/4] block: no need to initialize rq->cmd with blk_get_request FUJITA Tomonori
  2008-04-14 11:21                   ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
                                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw)
  To: linux-scsi
  Cc: bharrosh, FUJITA Tomonori, Geert Uytterhoeven, James Bottomley,
	Jens Axboe

The block layer initializes rq->cmd (queue_flush calls rq_init) so
prepare_flush_fn hooks don't need to do that.

This is a preparation for changing rq->cmd from the static array to a
pointer.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
---
 drivers/block/ps3disk.c |    1 -
 drivers/scsi/sd.c       |    1 -
 2 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index 7483f94..9c32b75 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -406,7 +406,6 @@ static void ps3disk_prepare_flush(struct request_queue *q, struct request *req)
 
 	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
 
-	memset(req->cmd, 0, sizeof(req->cmd));
 	req->cmd_type = REQ_TYPE_FLUSH;
 }
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 5fe7aae..338566a 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -850,7 +850,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
 
 static void sd_prepare_flush(struct request_queue *q, struct request *rq)
 {
-	memset(rq->cmd, 0, sizeof(rq->cmd));
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->timeout = SD_TIMEOUT;
 	rq->cmd[0] = SYNCHRONIZE_CACHE;
-- 
1.5.4.2


^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 2/4] block: no need to initialize rq->cmd with blk_get_request
  2008-04-14 10:50                   ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori
@ 2008-04-14 10:50                     ` FUJITA Tomonori
  2008-04-14 10:50                       ` [PATCH 3/4] block: replace sizeof(rq->cmd) with BLK_MAX_CDB FUJITA Tomonori
  0 siblings, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw)
  To: linux-scsi
  Cc: James Bottomley, bharrosh, FUJITA Tomonori, dm-devel, Jens Axboe,
	Alasdair G Kergon

blk_get_request initializes rq->cmd (rq_init does) so the users don't
need to do that.

This is a preparation for changing rq->cmd from the static array to a
pointer.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Alasdair G Kergon <agk@redhat.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
---
 block/scsi_ioctl.c          |    3 ---
 drivers/block/pktcdvd.c     |    2 --
 drivers/cdrom/cdrom.c       |    1 -
 drivers/md/dm-emc.c         |    2 --
 drivers/md/dm-mpath-hp-sw.c |    1 -
 drivers/md/dm-mpath-rdac.c  |    1 -
 6 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index a2c3a93..ffa3720 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -217,8 +217,6 @@ EXPORT_SYMBOL_GPL(blk_verify_command);
 static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
 			     struct sg_io_hdr *hdr, int has_write_perm)
 {
-	memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
-
 	if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
 		return -EFAULT;
 	if (blk_verify_command(rq->cmd, has_write_perm))
@@ -531,7 +529,6 @@ static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
 	rq->data_len = 0;
 	rq->extra_len = 0;
 	rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
-	memset(rq->cmd, 0, sizeof(rq->cmd));
 	rq->cmd[0] = cmd;
 	rq->cmd[4] = data;
 	rq->cmd_len = 6;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 18feb1c..3b806c9 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -776,8 +776,6 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
 
 	rq->cmd_len = COMMAND_SIZE(cgc->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->timeout = 60*HZ;
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index ac38290..69f26eb 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2194,7 +2194,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 		if (ret)
 			break;
 
-		memset(rq->cmd, 0, sizeof(rq->cmd));
 		rq->cmd[0] = GPCMD_READ_CD;
 		rq->cmd[1] = 1 << 2;
 		rq->cmd[2] = (lba >> 24) & 0xff;
diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c
index 6b91b9a..3ea5ad4 100644
--- a/drivers/md/dm-emc.c
+++ b/drivers/md/dm-emc.c
@@ -110,8 +110,6 @@ static struct request *get_failover_req(struct emc_handler *h,
 	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
 	rq->sense_len = 0;
 
-	memset(&rq->cmd, 0, BLK_MAX_CDB);
-
 	rq->timeout = EMC_FAILOVER_TIMEOUT;
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
diff --git a/drivers/md/dm-mpath-hp-sw.c b/drivers/md/dm-mpath-hp-sw.c
index 204bf42..b63a0ab 100644
--- a/drivers/md/dm-mpath-hp-sw.c
+++ b/drivers/md/dm-mpath-hp-sw.c
@@ -137,7 +137,6 @@ static struct request *hp_sw_get_request(struct dm_path *path)
 	req->sense = h->sense;
 	memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
 
-	memset(&req->cmd, 0, BLK_MAX_CDB);
 	req->cmd[0] = START_STOP;
 	req->cmd[4] = 1;
 	req->cmd_len = COMMAND_SIZE(req->cmd[0]);
diff --git a/drivers/md/dm-mpath-rdac.c b/drivers/md/dm-mpath-rdac.c
index e04eb5c..95e7773 100644
--- a/drivers/md/dm-mpath-rdac.c
+++ b/drivers/md/dm-mpath-rdac.c
@@ -284,7 +284,6 @@ static struct request *get_rdac_req(struct rdac_handler *h,
 		return NULL;
 	}
 
- 	memset(&rq->cmd, 0, BLK_MAX_CDB);
 	rq->sense = h->sense;
 	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
 	rq->sense_len = 0;
-- 
1.5.4.2

^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 3/4] block: replace sizeof(rq->cmd) with BLK_MAX_CDB
  2008-04-14 10:50                     ` [PATCH 2/4] block: no need to initialize rq->cmd with blk_get_request FUJITA Tomonori
@ 2008-04-14 10:50                       ` FUJITA Tomonori
  2008-04-14 10:50                         ` [PATCH 4/4] block: add large command support FUJITA Tomonori
  0 siblings, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw)
  To: linux-scsi
  Cc: bharrosh, FUJITA Tomonori, Bartlomiej Zolnierkiewicz, Jens Axboe,
	linux-ide

This is a preparation for changing rq->cmd from the static array to a
pointer.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
---
 block/blk-core.c             |    4 ++--
 drivers/ide/ide-cd.c         |    4 ++--
 drivers/ide/ide-cd_verbose.c |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 2a438a9..6669238 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -132,7 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
 	rq->errors = 0;
 	rq->ref_count = 1;
 	rq->cmd_len = 0;
-	memset(rq->cmd, 0, sizeof(rq->cmd));
+	memset(rq->cmd, 0, BLK_MAX_CDB);
 	rq->data_len = 0;
 	rq->extra_len = 0;
 	rq->sense_len = 0;
@@ -194,7 +194,7 @@ void blk_dump_rq_flags(struct request *rq, char *msg)
 
 	if (blk_pc_request(rq)) {
 		printk(KERN_INFO "  cdb: ");
-		for (bit = 0; bit < sizeof(rq->cmd); bit++)
+		for (bit = 0; bit < BLK_MAX_CDB; bit++)
 			printk("%02x ", rq->cmd[bit]);
 		printk("\n");
 	}
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index f8cea94..db29bde 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -879,7 +879,7 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
 
 	sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
 
-	memset(rq->cmd, 0, sizeof(rq->cmd));
+	memset(rq->cmd, 0, BLK_MAX_CDB);
 	rq->cmd[0] = GPCMD_SEEK;
 	put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
 
@@ -1812,7 +1812,7 @@ static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
 	long block = (long)rq->hard_sector / (hard_sect >> 9);
 	unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
 
-	memset(rq->cmd, 0, sizeof(rq->cmd));
+	memset(rq->cmd, 0, BLK_MAX_CDB);
 
 	if (rq_data_dir(rq) == READ)
 		rq->cmd[0] = GPCMD_READ_10;
diff --git a/drivers/ide/ide-cd_verbose.c b/drivers/ide/ide-cd_verbose.c
index 6ed7ca0..6490a2d 100644
--- a/drivers/ide/ide-cd_verbose.c
+++ b/drivers/ide/ide-cd_verbose.c
@@ -326,7 +326,7 @@ void ide_cd_log_error(const char *name, struct request *failed_command,
 
 		printk(KERN_ERR "  The failed \"%s\" packet command "
 				"was: \n  \"", s);
-		for (i = 0; i < sizeof(failed_command->cmd); i++)
+		for (i = 0; i < BLK_MAX_CDB; i++)
 			printk(KERN_CONT "%02x ", failed_command->cmd[i]);
 		printk(KERN_CONT "\"\n");
 	}
-- 
1.5.4.2


^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 4/4] block: add large command support
  2008-04-14 10:50                       ` [PATCH 3/4] block: replace sizeof(rq->cmd) with BLK_MAX_CDB FUJITA Tomonori
@ 2008-04-14 10:50                         ` FUJITA Tomonori
  2008-04-14 11:29                           ` Jens Axboe
                                             ` (2 more replies)
  0 siblings, 3 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw)
  To: linux-scsi; +Cc: bharrosh, FUJITA Tomonori, Jens Axboe, linux-ide

This patch changes rq->cmd from the static array to a pointer to
support large commands.

We rarely handle large commands. So for optimization, a struct request
still has a static array for a command. rq_init sets rq->cmd pointer
to the static array.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Jens Axboe <jens.axboe@oracle.com>
---
 block/blk-core.c       |    1 +
 drivers/ide/ide-io.c   |    1 +
 include/linux/blkdev.h |   12 ++++++++++--
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 6669238..6f0968f 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
 	rq->errors = 0;
 	rq->ref_count = 1;
 	rq->cmd_len = 0;
+	rq->cmd = rq->__cmd;
 	memset(rq->cmd, 0, BLK_MAX_CDB);
 	rq->data_len = 0;
 	rq->extra_len = 0;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 7153796..bac5ea1 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
 {
 	memset(rq, 0, sizeof(*rq));
 	rq->ref_count = 1;
+	rq->cmd = rq->__cmd;
 }
 
 EXPORT_SYMBOL(ide_init_drive_cmd);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index b3a58ad..5710ae4 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -215,8 +215,9 @@ struct request {
 	/*
 	 * when request is used as a packet command carrier
 	 */
-	unsigned int cmd_len;
-	unsigned char cmd[BLK_MAX_CDB];
+	unsigned short cmd_len;
+	unsigned char __cmd[BLK_MAX_CDB];
+	unsigned char *cmd;
 
 	unsigned int data_len;
 	unsigned int extra_len;	/* length of alignment and padding */
@@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p)
 	page_cache_release(p.v);
 }
 
+static inline void rq_set_cmd(struct request *rq, unsigned char *cmd,
+			      unsigned short cmd_len)
+{
+	rq->cmd = cmd;
+	rq->cmd_len = cmd_len;
+}
+
 struct work_struct;
 int kblockd_schedule_work(struct work_struct *work);
 void kblockd_flush_work(struct work_struct *work);
-- 
1.5.4.2


^ permalink raw reply related	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver2] block layer extended-cdb support
  2008-04-13 16:50                 ` Boaz Harrosh
  2008-04-14  9:49                   ` [PATCH 2/3 ver3] " Boaz Harrosh
@ 2008-04-14 11:04                   ` FUJITA Tomonori
  1 sibling, 0 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 11:04 UTC (permalink / raw)
  To: bharrosh
  Cc: fujita.tomonori, jens.axboe, James.Bottomley, hch, linux-scsi,
	akpm

On Sun, 13 Apr 2008 19:50:26 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> > On Sun, 13 Apr 2008 12:13:18 +0300
> > Boaz Harrosh <bharrosh@panasas.com> wrote:
> > 
> >> On Sat, Apr 12 2008 at 8:52 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> >>> On Sun, 06 Apr 2008 12:35:04 +0300
> >>> Boaz Harrosh <bharrosh@panasas.com> wrote:
> >>>
> >>>> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> >>>>> On Thu, Apr 03 2008, Boaz Harrosh wrote:
> >>>>>>  static void req_bio_endio(struct request *rq, struct bio *bio,
> >>>>>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> >>>>>> index 6f79d40..2f87c9d 100644
> >>>>>> --- a/include/linux/blkdev.h
> >>>>>> +++ b/include/linux/blkdev.h
> >>>>>> @@ -213,8 +213,15 @@ struct request {
> >>>>>>  	/*
> >>>>>>  	 * when request is used as a packet command carrier
> >>>>>>  	 */
> >>>>>> -	unsigned int cmd_len;
> >>>>>> -	unsigned char cmd[BLK_MAX_CDB];
> >>>>>> +	unsigned short cmd_len;
> >>>>>> +	unsigned short ext_cdb_len;  /* length of ext_cdb buffer */
> >>>>>> +	union {
> >>>>>> +		unsigned char cmd[BLK_MAX_CDB];
> >>>>>> +		unsigned char *ext_cdb;/* an optional extended cdb.
> >>>>>> +	                                   * points to a user buffer that must
> >>>>>> +	                                   * be valid until end of request
> >>>>>> +	                                   */
> >>>>>> +	};
> >>>>> Why not just something ala
> >>>>>
> >>>>>         unsigned short cmd_len;
> >>>>>         unsigned char __cmd[BLK_MAX_CDB];
> >>>>>         unsigned char *cmd;
> >>>>>
> >>>>> and then have rq_init() do
> >>>>>
> >>>>>         rq->cmd = rq->__cmd;
> >>>>>
> >>>>> and just have a function for setting up a larger ->cmd and adjusting
> >>>>> ->cmd_len in the process?
> >>>>>
> >>>>> Then rq_set_cdb() would be
> >>>>>
> >>>>> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len)
> >>>>> {
> >>>>>         rq->cmd = cdb;
> >>>>>         rq->cmd_len = cdb_len;
> >>>>> }
> >>>>>
> >>>>> and rq_get_cdb() plus rq_get_cdb_len() could just go away.
> >>>>>
> >>>> Because this way it is dangerous if large commands are issued to legacy
> >>>> drivers. In scsi-land we have .cmd_len at host template that will govern if
> >>>> we are allow to issue larger commands to the driver. In block devices we do
> >>>> not have such a facility, and the danger is if such commands are issued through
> >>>> bsg or other means, even by malicious code. What you say is the ideal and it
> >>>> is what I've done for scsi, but for block devices we can not do that yet.
> >>>> With the way I did it here, Legacy drivers will see zero length command and
> >>>> will do the right thing, from what I've seen.
> >>> What are exactly block devices? ub and ide?
> >>>
> >>> bsg are created only for scsi devices (and scsi objects like sas host)
> >>> now. Are there other means to send commands except for ioctl?
> >> I'm not 100% sure either way, so I would like to be safe. Any way, there
> >> is the size issue, this way we add *nothing* at all, so it looks preferable.
> >> The final outcome will be the same both ways.
> > 
> > I think that a clean design is an important issue than the sizeof of
> > struct request.
> > 
> > 
> >> I would like if you reconsider the ugliness issue. I admit that at first I
> >> personally disliked it, but now that I look at it, I think it is cleaner,
> >> coding style, this way. Because the union points out the exclusiveness of
> >> the two systems, the striate way give the notion of two separate systems.
> > 
> > That's a ugly hack for me.
> > 
> > Why do we have two separate systems to represent the command length?
> > If the command length is smaller than 16 bytes, we use cmd_len. If the
> > length is larger than 16 bytes, we use varlen_cdb_len?
> > 
> > For me, as Jens proposed, having only cmd_len is the right way.
> > 
> > And 'cdb' name is not appropriate for the block layer, I think.
> > 
> > I agreed that changing the block layer and the scsi midlayer gradually
> > is a safe option. Shortly, I'll send patches to clean up the hack on
> > the top of your patchset.
> > --
> 
> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in
> the middle, so anyway you have the latest I have now.
> 
> If it's ok with you I will squash your patches onto mine and add your
> sign-off-by. There is no use putting code in the tree that will be changed
> immediately after.

There is no mergeable stuff between yours and my patchset. I've just
sent four patches. The first three patches are not related your
patchset (they are cleanups for changing rq->cmd from the static array
to a pointer). The fourth patch is a substitute for your second
patch. Nothing are common between them.


> Please note that I'm a bit afraid to put code that has both length as one
> if you are more confident then me, I will take your word for it.
> 
> Thanks for helping out, as you can see I did it very safe, but with your
> help maybe it can finally go in. Thanks++
> 
> Boaz
> --
> 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

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver3] block layer extended-cdb support
  2008-04-14  9:49                   ` [PATCH 2/3 ver3] " Boaz Harrosh
@ 2008-04-14 11:04                     ` FUJITA Tomonori
  2008-04-14 11:28                       ` Boaz Harrosh
  0 siblings, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 11:04 UTC (permalink / raw)
  To: bharrosh
  Cc: fujita.tomonori, jens.axboe, James.Bottomley, hch, linux-scsi,
	akpm

On Mon, 14 Apr 2008 12:49:49 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
> > On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> >> On Sun, 13 Apr 2008 12:13:18 +0300
> >> Boaz Harrosh <bharrosh@panasas.com> wrote:
> >>
> >> That's a ugly hack for me.
> >>
> >> Why do we have two separate systems to represent the command length?
> >> If the command length is smaller than 16 bytes, we use cmd_len. If the
> >> length is larger than 16 bytes, we use varlen_cdb_len?
> >>
> >> For me, as Jens proposed, having only cmd_len is the right way.
> >>
> >> And 'cdb' name is not appropriate for the block layer, I think.
> >>
> >> I agreed that changing the block layer and the scsi midlayer gradually
> >> is a safe option. Shortly, I'll send patches to clean up the hack on
> >> the top of your patchset.
> >> --
> > 
> > Sorry TOMO, I was sending the ver2 patchset and only saw your mail in
> > the middle, so anyway you have the latest I have now.
> > 
> > If it's ok with you I will squash your patches onto mine and add your
> > sign-off-by. There is no use putting code in the tree that will be changed
> > immediately after.
> > 
> > Please note that I'm a bit afraid to put code that has both length as one
> > if you are more confident then me, I will take your word for it.
> > 
> > Thanks for helping out, as you can see I did it very safe, but with your
> > help maybe it can finally go in. Thanks++
> > 
> > Boaz
> > --
> Maybe you mean something like below. I changed cdb => cmd and I use one
> cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB
> right there next to it. But if you don't like it then I don't mind to
> change the name, I think it was James idea.

I don't. I've been talking mainly about how to represent the length of
command.

About 'cdb' name, I thought that there is a better name than
BLK_MAX_CDB. But it's up to Jens.


> But please note!!!
> I think having one cmd_len is DANGEROUS. And it forces a full code audit
> to be sure, has with my approach we are much more safe. There, I said it.

Could you be more specific? So far, you have not explained how it can
be dangerous.

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 0/4] add large command support to the block layer
  2008-04-14 10:50                 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
  2008-04-14 10:50                   ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori
@ 2008-04-14 11:21                   ` FUJITA Tomonori
  2008-04-14 11:38                   ` Boaz Harrosh
  2008-04-15 12:24                   ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh
  3 siblings, 0 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 11:21 UTC (permalink / raw)
  To: jens.axboe
  Cc: linux-scsi, bharrosh, bzolnier, James.Bottomley, agk,
	Geert.Uytterhoeven, fujita.tomonori

On Mon, 14 Apr 2008 19:50:33 +0900
FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:

> This patchset adds large command support to the block layer.

Forgot to add: the patchset are against for for-2.6.26 branch in Jens'
block tree.

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver3] block layer extended-cdb support
  2008-04-14 11:04                     ` FUJITA Tomonori
@ 2008-04-14 11:28                       ` Boaz Harrosh
  2008-04-14 12:08                         ` FUJITA Tomonori
  0 siblings, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-14 11:28 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm, Pete Wyckoff

On Mon, Apr 14 2008 at 14:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> On Mon, 14 Apr 2008 12:49:49 +0300
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
>>> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
>>>> On Sun, 13 Apr 2008 12:13:18 +0300
>>>> Boaz Harrosh <bharrosh@panasas.com> wrote:
>>>>
>>>> That's a ugly hack for me.
>>>>
>>>> Why do we have two separate systems to represent the command length?
>>>> If the command length is smaller than 16 bytes, we use cmd_len. If the
>>>> length is larger than 16 bytes, we use varlen_cdb_len?
>>>>
>>>> For me, as Jens proposed, having only cmd_len is the right way.
>>>>
>>>> And 'cdb' name is not appropriate for the block layer, I think.
>>>>
>>>> I agreed that changing the block layer and the scsi midlayer gradually
>>>> is a safe option. Shortly, I'll send patches to clean up the hack on
>>>> the top of your patchset.
>>>> --
>>> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in
>>> the middle, so anyway you have the latest I have now.
>>>
>>> If it's ok with you I will squash your patches onto mine and add your
>>> sign-off-by. There is no use putting code in the tree that will be changed
>>> immediately after.
>>>
>>> Please note that I'm a bit afraid to put code that has both length as one
>>> if you are more confident then me, I will take your word for it.
>>>
>>> Thanks for helping out, as you can see I did it very safe, but with your
>>> help maybe it can finally go in. Thanks++
>>>
>>> Boaz
>>> --
>> Maybe you mean something like below. I changed cdb => cmd and I use one
>> cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB
>> right there next to it. But if you don't like it then I don't mind to
>> change the name, I think it was James idea.
> 
> I don't. I've been talking mainly about how to represent the length of
> command.
> 
> About 'cdb' name, I thought that there is a better name than
> BLK_MAX_CDB. But it's up to Jens.
> 
> 
>> But please note!!!
>> I think having one cmd_len is DANGEROUS. And it forces a full code audit
>> to be sure, has with my approach we are much more safe. There, I said it.
> 
> Could you be more specific? So far, you have not explained how it can
> be dangerous.

There is a pending patch by Pete, and our main goal, is to push OSD commands 
through bsg. All over the kernel there are cooked up char-devices, like in 
gdth, that do vendor specific management commands. All these, and future, 
special-command can go from user-mode through bsg in a common way. Via support 
of vendor specific and extended commands. All the new scsi defined commands 
that are bigger then 16 are not going to be sent through sg, but through 
bsg right? So we do want to use this facility from kernel and from user-land
but we need some protection. In scsi LLDs we have .max_cmnd but block devices
don't have that. So either you need to restrict what can be done, or play it safe
like I did.

Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-14 10:50                         ` [PATCH 4/4] block: add large command support FUJITA Tomonori
@ 2008-04-14 11:29                           ` Jens Axboe
  2008-04-14 12:08                             ` FUJITA Tomonori
  2008-04-15 22:50                             ` Bartlomiej Zolnierkiewicz
  2008-04-14 14:41                           ` Pete Wyckoff
  2008-04-15  7:29                           ` Jens Axboe
  2 siblings, 2 replies; 77+ messages in thread
From: Jens Axboe @ 2008-04-14 11:29 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: linux-scsi, bharrosh, linux-ide

On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> This patch changes rq->cmd from the static array to a pointer to
> support large commands.
> 
> We rarely handle large commands. So for optimization, a struct request
> still has a static array for a command. rq_init sets rq->cmd pointer
> to the static array.
> 
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> Cc: Jens Axboe <jens.axboe@oracle.com>
> ---
>  block/blk-core.c       |    1 +
>  drivers/ide/ide-io.c   |    1 +
>  include/linux/blkdev.h |   12 ++++++++++--
>  3 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/block/blk-core.c b/block/blk-core.c
> index 6669238..6f0968f 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
>  	rq->errors = 0;
>  	rq->ref_count = 1;
>  	rq->cmd_len = 0;
> +	rq->cmd = rq->__cmd;
>  	memset(rq->cmd, 0, BLK_MAX_CDB);
>  	rq->data_len = 0;
>  	rq->extra_len = 0;
> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> index 7153796..bac5ea1 100644
> --- a/drivers/ide/ide-io.c
> +++ b/drivers/ide/ide-io.c
> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
>  {
>  	memset(rq, 0, sizeof(*rq));
>  	rq->ref_count = 1;
> +	rq->cmd = rq->__cmd;
>  }
>  
>  EXPORT_SYMBOL(ide_init_drive_cmd);
> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> index b3a58ad..5710ae4 100644
> --- a/include/linux/blkdev.h
> +++ b/include/linux/blkdev.h
> @@ -215,8 +215,9 @@ struct request {
>  	/*
>  	 * when request is used as a packet command carrier
>  	 */
> -	unsigned int cmd_len;
> -	unsigned char cmd[BLK_MAX_CDB];
> +	unsigned short cmd_len;
> +	unsigned char __cmd[BLK_MAX_CDB];
> +	unsigned char *cmd;
>  
>  	unsigned int data_len;
>  	unsigned int extra_len;	/* length of alignment and padding */
> @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p)
>  	page_cache_release(p.v);
>  }
>  
> +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd,
> +			      unsigned short cmd_len)
> +{
> +	rq->cmd = cmd;
> +	rq->cmd_len = cmd_len;
> +}
> +

This is 100% identical to what I suggested be done instead, so of course
I agree with this.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 0/4] add large command support to the block layer
  2008-04-14 10:50                 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
  2008-04-14 10:50                   ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori
  2008-04-14 11:21                   ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
@ 2008-04-14 11:38                   ` Boaz Harrosh
  2008-04-14 12:36                     ` Boaz Harrosh
  2008-04-15 12:24                   ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh
  3 siblings, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-14 11:38 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz,
	James Bottomley, Alasdair G Kergon, Geert Uytterhoeven

On Mon, Apr 14 2008 at 13:50 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> This patchset adds large command support to the block layer.
> 
> We rarely handle large commands. So for optimization, a struct request
> still has a static array for a command. rq_init sets rq->cmd pointer
> to the static array. In short, rq_init() does
> 
> rq->cmd = rq->__cmd;
> 
> So we can access to rq->cmd and rq->cmd_len as before.
> 
> Boaz argues that having single cmd_len is dangerous:
> 
>> Because this way it is dangerous if large commands are issued to legacy
>> drivers. In scsi-land we have .cmd_len at host template that will govern if
>> we are allow to issue larger commands to the driver. In block devices we do
>> not have such a facility, and the danger is if such commands are issued through
>> bsg or other means, even by malicious code. What you say is the ideal and it
> 
> I don't see how it is dangerous. We don't send large commands to block
> devices via bsg. We can send large commands to block devices via only
> SG_IO. SG_IO (block/scsi_ioctl.c) forbids us sending commands large
> than 16 bytes, BLK_MAX_CDB. So how can we send large commands to block
> devices?
> 
> The first, second, and third patches are safe cleanups (a preparation
> for changing rq->cmd from the static array to a pointer). They don't
> conflict with Boaz's patchset. Even if we choose Boaz's approach now,
> we'll move to the approach to have one command length in struct
> request in the long term. So they can be applied now.
> 
> The forth patch adds large command support. It's a substitute for
> Boaz's second patch. It's pretty simple except for one hack for
> ide-io. It's necessary since the ide subsystem allocates struct
> request without using blk_get_request. In the long term, it would
> better to convert it to use blk_get_request properly.
> 
>

I still think that my last patch with one cmd_len and the Union is
nicer and more simple. And does not waist the extra pointer that is 
never ever used but by me. (And does not need 3 preparation patches)

Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver3] block layer extended-cdb support
  2008-04-14 11:28                       ` Boaz Harrosh
@ 2008-04-14 12:08                         ` FUJITA Tomonori
  2008-04-14 12:22                           ` Boaz Harrosh
  0 siblings, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 12:08 UTC (permalink / raw)
  To: bharrosh
  Cc: fujita.tomonori, jens.axboe, James.Bottomley, hch, linux-scsi,
	akpm, pw

On Mon, 14 Apr 2008 14:28:45 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On Mon, Apr 14 2008 at 14:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> > On Mon, 14 Apr 2008 12:49:49 +0300
> > Boaz Harrosh <bharrosh@panasas.com> wrote:
> > 
> >> On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
> >>> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> >>>> On Sun, 13 Apr 2008 12:13:18 +0300
> >>>> Boaz Harrosh <bharrosh@panasas.com> wrote:
> >>>>
> >>>> That's a ugly hack for me.
> >>>>
> >>>> Why do we have two separate systems to represent the command length?
> >>>> If the command length is smaller than 16 bytes, we use cmd_len. If the
> >>>> length is larger than 16 bytes, we use varlen_cdb_len?
> >>>>
> >>>> For me, as Jens proposed, having only cmd_len is the right way.
> >>>>
> >>>> And 'cdb' name is not appropriate for the block layer, I think.
> >>>>
> >>>> I agreed that changing the block layer and the scsi midlayer gradually
> >>>> is a safe option. Shortly, I'll send patches to clean up the hack on
> >>>> the top of your patchset.
> >>>> --
> >>> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in
> >>> the middle, so anyway you have the latest I have now.
> >>>
> >>> If it's ok with you I will squash your patches onto mine and add your
> >>> sign-off-by. There is no use putting code in the tree that will be changed
> >>> immediately after.
> >>>
> >>> Please note that I'm a bit afraid to put code that has both length as one
> >>> if you are more confident then me, I will take your word for it.
> >>>
> >>> Thanks for helping out, as you can see I did it very safe, but with your
> >>> help maybe it can finally go in. Thanks++
> >>>
> >>> Boaz
> >>> --
> >> Maybe you mean something like below. I changed cdb => cmd and I use one
> >> cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB
> >> right there next to it. But if you don't like it then I don't mind to
> >> change the name, I think it was James idea.
> > 
> > I don't. I've been talking mainly about how to represent the length of
> > command.
> > 
> > About 'cdb' name, I thought that there is a better name than
> > BLK_MAX_CDB. But it's up to Jens.
> > 
> > 
> >> But please note!!!
> >> I think having one cmd_len is DANGEROUS. And it forces a full code audit
> >> to be sure, has with my approach we are much more safe. There, I said it.
> > 
> > Could you be more specific? So far, you have not explained how it can
> > be dangerous.
> 
> There is a pending patch by Pete, and our main goal, is to push OSD commands 
> through bsg. All over the kernel there are cooked up char-devices, like in 
> gdth, that do vendor specific management commands. All these, and future, 
> special-command can go from user-mode through bsg in a common way. Via support 
> of vendor specific and extended commands. All the new scsi defined commands 
> that are bigger then 16 are not going to be sent through sg, but through 
> bsg right? So we do want to use this facility from kernel and from user-land
> but we need some protection. In scsi LLDs we have .max_cmnd but block devices
> don't have that. So either you need to restrict what can be done, or play it safe
> like I did.

If we creates bsg devices for block devices, of course, we need to a
mechanism to govern the length of commands.

But why do you want to create bsg devices for block devices? If block
devices want large commands for some reasons, their bsg hook functions
need to handle the length of commands anyway. There is no reason that
the block layer has two values to represent one item, the length of
command.

If we want to govern the command length in a common place, then I
think that it would be better to add the limit to request queue.

And again, what are your block devices? What do they want bsg for?

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-14 11:29                           ` Jens Axboe
@ 2008-04-14 12:08                             ` FUJITA Tomonori
  2008-04-15 22:50                             ` Bartlomiej Zolnierkiewicz
  1 sibling, 0 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 12:08 UTC (permalink / raw)
  To: jens.axboe; +Cc: fujita.tomonori, linux-scsi, bharrosh, linux-ide

On Mon, 14 Apr 2008 13:29:20 +0200
Jens Axboe <jens.axboe@oracle.com> wrote:

> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> > This patch changes rq->cmd from the static array to a pointer to
> > support large commands.
> > 
> > We rarely handle large commands. So for optimization, a struct request
> > still has a static array for a command. rq_init sets rq->cmd pointer
> > to the static array.
> > 
> > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > Cc: Jens Axboe <jens.axboe@oracle.com>
> > ---
> >  block/blk-core.c       |    1 +
> >  drivers/ide/ide-io.c   |    1 +
> >  include/linux/blkdev.h |   12 ++++++++++--
> >  3 files changed, 12 insertions(+), 2 deletions(-)
> > 
> > diff --git a/block/blk-core.c b/block/blk-core.c
> > index 6669238..6f0968f 100644
> > --- a/block/blk-core.c
> > +++ b/block/blk-core.c
> > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> >  	rq->errors = 0;
> >  	rq->ref_count = 1;
> >  	rq->cmd_len = 0;
> > +	rq->cmd = rq->__cmd;
> >  	memset(rq->cmd, 0, BLK_MAX_CDB);
> >  	rq->data_len = 0;
> >  	rq->extra_len = 0;
> > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> > index 7153796..bac5ea1 100644
> > --- a/drivers/ide/ide-io.c
> > +++ b/drivers/ide/ide-io.c
> > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> >  {
> >  	memset(rq, 0, sizeof(*rq));
> >  	rq->ref_count = 1;
> > +	rq->cmd = rq->__cmd;
> >  }
> >  
> >  EXPORT_SYMBOL(ide_init_drive_cmd);
> > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> > index b3a58ad..5710ae4 100644
> > --- a/include/linux/blkdev.h
> > +++ b/include/linux/blkdev.h
> > @@ -215,8 +215,9 @@ struct request {
> >  	/*
> >  	 * when request is used as a packet command carrier
> >  	 */
> > -	unsigned int cmd_len;
> > -	unsigned char cmd[BLK_MAX_CDB];
> > +	unsigned short cmd_len;
> > +	unsigned char __cmd[BLK_MAX_CDB];
> > +	unsigned char *cmd;
> >  
> >  	unsigned int data_len;
> >  	unsigned int extra_len;	/* length of alignment and padding */
> > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p)
> >  	page_cache_release(p.v);
> >  }
> >  
> > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd,
> > +			      unsigned short cmd_len)
> > +{
> > +	rq->cmd = cmd;
> > +	rq->cmd_len = cmd_len;
> > +}
> > +
> 
> This is 100% identical to what I suggested be done instead, so of course
> I agree with this.

Yeah, I think that it's the most straightforward. We have one value to
represent one item, the length of command. We can access to rq->cmd
and rq->cmd_len as before.

I don't see how it's is dangerous to have a single value to represent
the length of command though changing rq->cmd from the static array to
a pointer to support large commands is tricky. It's possible that I
overlooked something that uses the block layer in an uncommon way as
ide does.

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver3] block layer extended-cdb support
  2008-04-14 12:08                         ` FUJITA Tomonori
@ 2008-04-14 12:22                           ` Boaz Harrosh
  0 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-14 12:22 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm, pw

On Mon, Apr 14 2008 at 15:08 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> On Mon, 14 Apr 2008 14:28:45 +0300
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> On Mon, Apr 14 2008 at 14:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
>>> On Mon, 14 Apr 2008 12:49:49 +0300
>>> Boaz Harrosh <bharrosh@panasas.com> wrote:
>>>
>>>> On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
>>>>> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
>>>>>> On Sun, 13 Apr 2008 12:13:18 +0300
>>>>>> Boaz Harrosh <bharrosh@panasas.com> wrote:
>>>>>>
>>>>>> That's a ugly hack for me.
>>>>>>
>>>>>> Why do we have two separate systems to represent the command length?
>>>>>> If the command length is smaller than 16 bytes, we use cmd_len. If the
>>>>>> length is larger than 16 bytes, we use varlen_cdb_len?
>>>>>>
>>>>>> For me, as Jens proposed, having only cmd_len is the right way.
>>>>>>
>>>>>> And 'cdb' name is not appropriate for the block layer, I think.
>>>>>>
>>>>>> I agreed that changing the block layer and the scsi midlayer gradually
>>>>>> is a safe option. Shortly, I'll send patches to clean up the hack on
>>>>>> the top of your patchset.
>>>>>> --
>>>>> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in
>>>>> the middle, so anyway you have the latest I have now.
>>>>>
>>>>> If it's ok with you I will squash your patches onto mine and add your
>>>>> sign-off-by. There is no use putting code in the tree that will be changed
>>>>> immediately after.
>>>>>
>>>>> Please note that I'm a bit afraid to put code that has both length as one
>>>>> if you are more confident then me, I will take your word for it.
>>>>>
>>>>> Thanks for helping out, as you can see I did it very safe, but with your
>>>>> help maybe it can finally go in. Thanks++
>>>>>
>>>>> Boaz
>>>>> --
>>>> Maybe you mean something like below. I changed cdb => cmd and I use one
>>>> cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB
>>>> right there next to it. But if you don't like it then I don't mind to
>>>> change the name, I think it was James idea.
>>> I don't. I've been talking mainly about how to represent the length of
>>> command.
>>>
>>> About 'cdb' name, I thought that there is a better name than
>>> BLK_MAX_CDB. But it's up to Jens.
>>>
>>>
>>>> But please note!!!
>>>> I think having one cmd_len is DANGEROUS. And it forces a full code audit
>>>> to be sure, has with my approach we are much more safe. There, I said it.
>>> Could you be more specific? So far, you have not explained how it can
>>> be dangerous.
>> There is a pending patch by Pete, and our main goal, is to push OSD commands 
>> through bsg. All over the kernel there are cooked up char-devices, like in 
>> gdth, that do vendor specific management commands. All these, and future, 
>> special-command can go from user-mode through bsg in a common way. Via support 
>> of vendor specific and extended commands. All the new scsi defined commands 
>> that are bigger then 16 are not going to be sent through sg, but through 
>> bsg right? So we do want to use this facility from kernel and from user-land
>> but we need some protection. In scsi LLDs we have .max_cmnd but block devices
>> don't have that. So either you need to restrict what can be done, or play it safe
>> like I did.
> 
> If we creates bsg devices for block devices, of course, we need to a
> mechanism to govern the length of commands.
> 
> But why do you want to create bsg devices for block devices? If block
> devices want large commands for some reasons, their bsg hook functions
> need to handle the length of commands anyway. There is no reason that
> the block layer has two values to represent one item, the length of
> command.
> 
> If we want to govern the command length in a common place, then I
> think that it would be better to add the limit to request queue.
> 
> And again, what are your block devices? What do they want bsg for?
> --

I don't have any block devices personally. I just thought that the diff
between sg a bsg is that bsg will support any block device, so I guess
I was wrong, bsg is a user-to-scsi bridge just like sg is. I thought
bsg registers on every request_queue, how does bsg filter which devices
to export and which not?

What about the union, don't we care about the space saved?

Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 0/4] add large command support to the block layer
  2008-04-14 11:38                   ` Boaz Harrosh
@ 2008-04-14 12:36                     ` Boaz Harrosh
  2008-04-14 13:06                       ` FUJITA Tomonori
  0 siblings, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-14 12:36 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz,
	James Bottomley, Alasdair G Kergon, Geert Uytterhoeven

On Mon, Apr 14 2008 at 14:38 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
> On Mon, Apr 14 2008 at 13:50 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
>> This patchset adds large command support to the block layer.
>>
>> We rarely handle large commands. So for optimization, a struct request
>> still has a static array for a command. rq_init sets rq->cmd pointer
>> to the static array. In short, rq_init() does
>>
>> rq->cmd = rq->__cmd;
>>
>> So we can access to rq->cmd and rq->cmd_len as before.
>>
>> Boaz argues that having single cmd_len is dangerous:
>>
>>> Because this way it is dangerous if large commands are issued to legacy
>>> drivers. In scsi-land we have .cmd_len at host template that will govern if
>>> we are allow to issue larger commands to the driver. In block devices we do
>>> not have such a facility, and the danger is if such commands are issued through
>>> bsg or other means, even by malicious code. What you say is the ideal and it
>> I don't see how it is dangerous. We don't send large commands to block
>> devices via bsg. We can send large commands to block devices via only
>> SG_IO. SG_IO (block/scsi_ioctl.c) forbids us sending commands large
>> than 16 bytes, BLK_MAX_CDB. So how can we send large commands to block
>> devices?
>>
>> The first, second, and third patches are safe cleanups (a preparation
>> for changing rq->cmd from the static array to a pointer). They don't
>> conflict with Boaz's patchset. Even if we choose Boaz's approach now,
>> we'll move to the approach to have one command length in struct
>> request in the long term. So they can be applied now.
>>
>> The forth patch adds large command support. It's a substitute for
>> Boaz's second patch. It's pretty simple except for one hack for
>> ide-io. It's necessary since the ide subsystem allocates struct
>> request without using blk_get_request. In the long term, it would
>> better to convert it to use blk_get_request properly.
>>
>>
> 
> I still think that my last patch with one cmd_len and the Union is
> nicer and more simple. And does not waist the extra pointer that is 
> never ever used but by me. (And does not need 3 preparation patches)
> 
> Boaz
> 
Tomo hi.

Please don't miss understand me.
ACK-by: Boaz Harrosh <bharrosh@panasas.com>

I really don't mind, it is fine by me and it does what I want.
So thanks yes please push this through, and I'll rebase my
two patches to yours.

Thanks
Boaz



^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 0/4] add large command support to the block layer
  2008-04-14 12:36                     ` Boaz Harrosh
@ 2008-04-14 13:06                       ` FUJITA Tomonori
  0 siblings, 0 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 13:06 UTC (permalink / raw)
  To: bharrosh
  Cc: fujita.tomonori, linux-scsi, jens.axboe, bzolnier,
	James.Bottomley, agk, Geert.Uytterhoeven

On Mon, 14 Apr 2008 15:22:21 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On Mon, Apr 14 2008 at 15:08 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> > On Mon, 14 Apr 2008 14:28:45 +0300
> > Boaz Harrosh <bharrosh@panasas.com> wrote:
> > 
> >> On Mon, Apr 14 2008 at 14:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> >>> On Mon, 14 Apr 2008 12:49:49 +0300
> >>> Boaz Harrosh <bharrosh@panasas.com> wrote:
> >>>
> >>>> On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
> >>>>> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> >>>>>> On Sun, 13 Apr 2008 12:13:18 +0300
> >>>>>> Boaz Harrosh <bharrosh@panasas.com> wrote:
> >>>>>>
> >>>>>> That's a ugly hack for me.
> >>>>>>
> >>>>>> Why do we have two separate systems to represent the command length?
> >>>>>> If the command length is smaller than 16 bytes, we use cmd_len. If the
> >>>>>> length is larger than 16 bytes, we use varlen_cdb_len?
> >>>>>>
> >>>>>> For me, as Jens proposed, having only cmd_len is the right way.
> >>>>>>
> >>>>>> And 'cdb' name is not appropriate for the block layer, I think.
> >>>>>>
> >>>>>> I agreed that changing the block layer and the scsi midlayer gradually
> >>>>>> is a safe option. Shortly, I'll send patches to clean up the hack on
> >>>>>> the top of your patchset.
> >>>>>> --
> >>>>> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in
> >>>>> the middle, so anyway you have the latest I have now.
> >>>>>
> >>>>> If it's ok with you I will squash your patches onto mine and add your
> >>>>> sign-off-by. There is no use putting code in the tree that will be changed
> >>>>> immediately after.
> >>>>>
> >>>>> Please note that I'm a bit afraid to put code that has both length as one
> >>>>> if you are more confident then me, I will take your word for it.
> >>>>>
> >>>>> Thanks for helping out, as you can see I did it very safe, but with your
> >>>>> help maybe it can finally go in. Thanks++
> >>>>>
> >>>>> Boaz
> >>>>> --
> >>>> Maybe you mean something like below. I changed cdb => cmd and I use one
> >>>> cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB
> >>>> right there next to it. But if you don't like it then I don't mind to
> >>>> change the name, I think it was James idea.
> >>> I don't. I've been talking mainly about how to represent the length of
> >>> command.
> >>>
> >>> About 'cdb' name, I thought that there is a better name than
> >>> BLK_MAX_CDB. But it's up to Jens.
> >>>
> >>>
> >>>> But please note!!!
> >>>> I think having one cmd_len is DANGEROUS. And it forces a full code audit
> >>>> to be sure, has with my approach we are much more safe. There, I said it.
> >>> Could you be more specific? So far, you have not explained how it can
> >>> be dangerous.
> >> There is a pending patch by Pete, and our main goal, is to push OSD commands 
> >> through bsg. All over the kernel there are cooked up char-devices, like in 
> >> gdth, that do vendor specific management commands. All these, and future, 
> >> special-command can go from user-mode through bsg in a common way. Via support 
> >> of vendor specific and extended commands. All the new scsi defined commands 
> >> that are bigger then 16 are not going to be sent through sg, but through 
> >> bsg right? So we do want to use this facility from kernel and from user-land
> >> but we need some protection. In scsi LLDs we have .max_cmnd but block devices
> >> don't have that. So either you need to restrict what can be done, or play it safe
> >> like I did.
> > 
> > If we creates bsg devices for block devices, of course, we need to a
> > mechanism to govern the length of commands.
> > 
> > But why do you want to create bsg devices for block devices? If block
> > devices want large commands for some reasons, their bsg hook functions
> > need to handle the length of commands anyway. There is no reason that
> > the block layer has two values to represent one item, the length of
> > command.
> > 
> > If we want to govern the command length in a common place, then I
> > think that it would be better to add the limit to request queue.
> > 
> > And again, what are your block devices? What do they want bsg for?
> > --
> 
> I don't have any block devices personally. I just thought that the diff
> between sg a bsg is that bsg will support any block device, so I guess
> I was wrong, bsg is a user-to-scsi bridge just like sg is. I thought
> bsg registers on every request_queue, how does bsg filter which devices
> to export and which not?

bsg is not a user-to-scsi bridge just like sg is. You can create bsg
devices for any request queue but we don't create bsg devices for
every request queue in kernel.

When you create a bsg device, you need your hook funciton to perform a
request via the bsg device. The hook function needs to handle large
commands if necessary.

If you are interested in how bsg works for non scsi devices, see
scsi_transport_sas.c. It creates bsg devices for sas objects to handle
SMP requests.


> What about the union, don't we care about the space saved?

I think that the approach to use a cmd pointer is clearer. But it's up
to Jens.

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-14 10:50                         ` [PATCH 4/4] block: add large command support FUJITA Tomonori
  2008-04-14 11:29                           ` Jens Axboe
@ 2008-04-14 14:41                           ` Pete Wyckoff
  2008-04-14 22:33                             ` FUJITA Tomonori
  2008-04-15  7:45                             ` Boaz Harrosh
  2008-04-15  7:29                           ` Jens Axboe
  2 siblings, 2 replies; 77+ messages in thread
From: Pete Wyckoff @ 2008-04-14 14:41 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: linux-scsi, bharrosh, Jens Axboe, linux-ide

fujita.tomonori@lab.ntt.co.jp wrote on Mon, 14 Apr 2008 19:50 +0900:
> This patch changes rq->cmd from the static array to a pointer to
> support large commands.
> 
> We rarely handle large commands. So for optimization, a struct request
> still has a static array for a command. rq_init sets rq->cmd pointer
> to the static array.
> 
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> Cc: Jens Axboe <jens.axboe@oracle.com>
[..]
> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> index b3a58ad..5710ae4 100644
> --- a/include/linux/blkdev.h
> +++ b/include/linux/blkdev.h
> @@ -215,8 +215,9 @@ struct request {
>  	/*
>  	 * when request is used as a packet command carrier
>  	 */
> -	unsigned int cmd_len;
> -	unsigned char cmd[BLK_MAX_CDB];
> +	unsigned short cmd_len;
> +	unsigned char __cmd[BLK_MAX_CDB];
> +	unsigned char *cmd;
>  
>  	unsigned int data_len;
>  	unsigned int extra_len;	/* length of alignment and padding */
> @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p)
>  	page_cache_release(p.v);
>  }
>  
> +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd,
> +			      unsigned short cmd_len)
> +{
> +	rq->cmd = cmd;
> +	rq->cmd_len = cmd_len;
> +}

Here's one way this will be used, in a patched bsg that understands
large commands.  Complication is the need to copy and hold onto the
big command across the duration of the request.

Submit time is fairly clean:

	/* buf, len from user request */
	rq = blk_get_request(..);
	rq->cmd_len = len;
	if (len > BLK_MAX_CDB) {
		rq->cmd = kmalloc(len);
		if (rq->cmd == NULL)
			goto out;
	}
	copy_from_user(rq->cmd, buf, len);

Completion time needs to know when to free rq->cmd:

	if (rq->cmd_len > BLK_MAX_CDB)
		kfree(rq->cmd);
	blk_put_request(rq);

Could use (rq->cmd != rq->__cmd) instead, but nothing had better
ever touch rq->cmd_len.

I don't think the helper rq_set_cmd() will be very useful, as the
caller (bsg) must think about allocation of the command buffer if it
is big.

One option would be to handle allocation/freeing of the big command
in rq_set_... functions, but I don't think you want to constrain the
interface like that.

Boaz's concern about big rq->cmd_len still worries me, although I
think this approach is better and worth solving bugs in drivers as
they arise.  It only matters in the case that someone adds, say, a
bsg interface to all block devices though.  The queuecommand of ub
shows a good example of how this will break.

In sum, this is a cleaner approach, and a bit easier for callers
with long commands to deal with.  And you could get rid of the
trivial helper.

		-- Pete

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-14 14:41                           ` Pete Wyckoff
@ 2008-04-14 22:33                             ` FUJITA Tomonori
  2008-04-15 13:44                               ` Pete Wyckoff
  2008-04-15  7:45                             ` Boaz Harrosh
  1 sibling, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-14 22:33 UTC (permalink / raw)
  To: pw; +Cc: fujita.tomonori, linux-scsi, bharrosh, jens.axboe, linux-ide

On Mon, 14 Apr 2008 10:41:54 -0400
Pete Wyckoff <pw@osc.edu> wrote:

> fujita.tomonori@lab.ntt.co.jp wrote on Mon, 14 Apr 2008 19:50 +0900:
> > This patch changes rq->cmd from the static array to a pointer to
> > support large commands.
> > 
> > We rarely handle large commands. So for optimization, a struct request
> > still has a static array for a command. rq_init sets rq->cmd pointer
> > to the static array.
> > 
> > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > Cc: Jens Axboe <jens.axboe@oracle.com>
> [..]
> > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> > index b3a58ad..5710ae4 100644
> > --- a/include/linux/blkdev.h
> > +++ b/include/linux/blkdev.h
> > @@ -215,8 +215,9 @@ struct request {
> >  	/*
> >  	 * when request is used as a packet command carrier
> >  	 */
> > -	unsigned int cmd_len;
> > -	unsigned char cmd[BLK_MAX_CDB];
> > +	unsigned short cmd_len;
> > +	unsigned char __cmd[BLK_MAX_CDB];
> > +	unsigned char *cmd;
> >  
> >  	unsigned int data_len;
> >  	unsigned int extra_len;	/* length of alignment and padding */
> > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p)
> >  	page_cache_release(p.v);
> >  }
> >  
> > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd,
> > +			      unsigned short cmd_len)
> > +{
> > +	rq->cmd = cmd;
> > +	rq->cmd_len = cmd_len;
> > +}
> 
> Here's one way this will be used, in a patched bsg that understands
> large commands.  Complication is the need to copy and hold onto the
> big command across the duration of the request.
> 
> Submit time is fairly clean:
> 
> 	/* buf, len from user request */
> 	rq = blk_get_request(..);
> 	rq->cmd_len = len;
> 	if (len > BLK_MAX_CDB) {
> 		rq->cmd = kmalloc(len);
> 		if (rq->cmd == NULL)
> 			goto out;
> 	}
> 	copy_from_user(rq->cmd, buf, len);
> 
> Completion time needs to know when to free rq->cmd:
> 
> 	if (rq->cmd_len > BLK_MAX_CDB)
> 		kfree(rq->cmd);
> 	blk_put_request(rq);
> 
> Could use (rq->cmd != rq->__cmd) instead, but nothing had better
> ever touch rq->cmd_len.
> 
> I don't think the helper rq_set_cmd() will be very useful, as the
> caller (bsg) must think about allocation of the command buffer if it
> is big.

Yeah, I think so. If you need large command support, you need to know
how to handle it for now. Now only bsg supports large commands. So I
guess that nobody complains about the current interface.


> One option would be to handle allocation/freeing of the big command
> in rq_set_... functions, but I don't think you want to constrain the
> interface like that.

Or, you can change blk_get_request to take the command length
argument. But I don't think that such is the right approach.


> Boaz's concern about big rq->cmd_len still worries me, although I
> think this approach is better and worth solving bugs in drivers as
> they arise.  It only matters in the case that someone adds, say, a
> bsg interface to all block devices though.  The queuecommand of ub
> shows a good example of how this will break.

Yes, a bsg hook will need to handle large commands. I don't see any
problem about it. All a hook needs to do is just looking at the legnth
and dropping or executing the command. And of course, we are unlikely
to add a bsg device to all the block devices.

As I said, if we want to govern the command length in a common place,
we can have the limit of the command length in request queues. It's
clear than an implicit checking with two lengths, cmd_len and
ext_cdb_len.

I thought about adding the code to check the command length in UB. But
I thought that we were unlikely to create bsg devices for ub. Common
people use USB_STORAGE rather than UB, I guess.


> In sum, this is a cleaner approach, and a bit easier for callers
> with long commands to deal with.  And you could get rid of the
> trivial helper.

Yeah, it's a cleaner design, that's main point, I think.


BTW, have you had a chance to try the bsg patches to fix the problems
that you reported? I think that Mike and I analyzed the problem
correctly and the patches works for me, but it would be nice if you
can confirm that they also work for you.

Thanks,

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-14 10:50                         ` [PATCH 4/4] block: add large command support FUJITA Tomonori
  2008-04-14 11:29                           ` Jens Axboe
  2008-04-14 14:41                           ` Pete Wyckoff
@ 2008-04-15  7:29                           ` Jens Axboe
  2 siblings, 0 replies; 77+ messages in thread
From: Jens Axboe @ 2008-04-15  7:29 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: linux-scsi, bharrosh, linux-ide

On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> This patch changes rq->cmd from the static array to a pointer to
> support large commands.
> 
> We rarely handle large commands. So for optimization, a struct request
> still has a static array for a command. rq_init sets rq->cmd pointer
> to the static array.

I applied 1-4, thanks.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-14 14:41                           ` Pete Wyckoff
  2008-04-14 22:33                             ` FUJITA Tomonori
@ 2008-04-15  7:45                             ` Boaz Harrosh
  2008-04-15 10:05                               ` FUJITA Tomonori
  1 sibling, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-15  7:45 UTC (permalink / raw)
  To: Pete Wyckoff; +Cc: FUJITA Tomonori, linux-scsi, Jens Axboe, linux-ide

On Mon, Apr 14 2008 at 17:41 +0300, Pete Wyckoff <pw@osc.edu> wrote:
> fujita.tomonori@lab.ntt.co.jp wrote on Mon, 14 Apr 2008 19:50 +0900:
>> This patch changes rq->cmd from the static array to a pointer to
>> support large commands.
>>
>> We rarely handle large commands. So for optimization, a struct request
>> still has a static array for a command. rq_init sets rq->cmd pointer
>> to the static array.
>>
>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
>> Cc: Jens Axboe <jens.axboe@oracle.com>
> [..]
>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
>> index b3a58ad..5710ae4 100644
>> --- a/include/linux/blkdev.h
>> +++ b/include/linux/blkdev.h
>> @@ -215,8 +215,9 @@ struct request {
>>  	/*
>>  	 * when request is used as a packet command carrier
>>  	 */
>> -	unsigned int cmd_len;
>> -	unsigned char cmd[BLK_MAX_CDB];
>> +	unsigned short cmd_len;
>> +	unsigned char __cmd[BLK_MAX_CDB];
>> +	unsigned char *cmd;
>>  
>>  	unsigned int data_len;
>>  	unsigned int extra_len;	/* length of alignment and padding */
>> @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p)
>>  	page_cache_release(p.v);
>>  }
>>  
>> +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd,
>> +			      unsigned short cmd_len)
>> +{
>> +	rq->cmd = cmd;
>> +	rq->cmd_len = cmd_len;
>> +}
> 
> Here's one way this will be used, in a patched bsg that understands
> large commands.  Complication is the need to copy and hold onto the
> big command across the duration of the request.
> 
> Submit time is fairly clean:
> 
> 	/* buf, len from user request */
> 	rq = blk_get_request(..);
> 	rq->cmd_len = len;
> 	if (len > BLK_MAX_CDB) {
> 		rq->cmd = kmalloc(len);
> 		if (rq->cmd == NULL)
> 			goto out;
> 	}
> 	copy_from_user(rq->cmd, buf, len);
> 
> Completion time needs to know when to free rq->cmd:
> 
> 	if (rq->cmd_len > BLK_MAX_CDB)
> 		kfree(rq->cmd);
> 	blk_put_request(rq);
> 
> Could use (rq->cmd != rq->__cmd) instead, but nothing had better
> ever touch rq->cmd_len.
> 

Don't do any of that please. The 16 bytes buffer at request is eventually
going away. Just always allocate and call rq_set_cmd(). This way we are
free to change in the future, and users code need not change.

And better then kmalloc the space for the command, is if you have
a structure that governs your request, just allocate a 
SCSI_MAX_VARLEN_CDB_SIZE (260) bytes array at your structure and always
use that.

> I don't think the helper rq_set_cmd() will be very useful, as the
> caller (bsg) must think about allocation of the command buffer if it
> is big.
> 
> One option would be to handle allocation/freeing of the big command
> in rq_set_... functions, but I don't think you want to constrain the
> interface like that.
> 
> Boaz's concern about big rq->cmd_len still worries me, although I
> think this approach is better and worth solving bugs in drivers as
> they arise.  It only matters in the case that someone adds, say, a
> bsg interface to all block devices though.  The queuecommand of ub
> shows a good example of how this will break.
> 
> In sum, this is a cleaner approach, and a bit easier for callers
> with long commands to deal with.  And you could get rid of the
> trivial helper.
> 

Don't. Please use the set helper it will give us future compatibility.

> 		-- Pete
> --

Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-15  7:45                             ` Boaz Harrosh
@ 2008-04-15 10:05                               ` FUJITA Tomonori
  0 siblings, 0 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-15 10:05 UTC (permalink / raw)
  To: bharrosh; +Cc: pw, fujita.tomonori, linux-scsi, jens.axboe, linux-ide

On Tue, 15 Apr 2008 10:45:52 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On Mon, Apr 14 2008 at 17:41 +0300, Pete Wyckoff <pw@osc.edu> wrote:
> > fujita.tomonori@lab.ntt.co.jp wrote on Mon, 14 Apr 2008 19:50 +0900:
> >> This patch changes rq->cmd from the static array to a pointer to
> >> support large commands.
> >>
> >> We rarely handle large commands. So for optimization, a struct request
> >> still has a static array for a command. rq_init sets rq->cmd pointer
> >> to the static array.
> >>
> >> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> >> Cc: Jens Axboe <jens.axboe@oracle.com>
> > [..]
> >> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> >> index b3a58ad..5710ae4 100644
> >> --- a/include/linux/blkdev.h
> >> +++ b/include/linux/blkdev.h
> >> @@ -215,8 +215,9 @@ struct request {
> >>  	/*
> >>  	 * when request is used as a packet command carrier
> >>  	 */
> >> -	unsigned int cmd_len;
> >> -	unsigned char cmd[BLK_MAX_CDB];
> >> +	unsigned short cmd_len;
> >> +	unsigned char __cmd[BLK_MAX_CDB];
> >> +	unsigned char *cmd;
> >>  
> >>  	unsigned int data_len;
> >>  	unsigned int extra_len;	/* length of alignment and padding */
> >> @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p)
> >>  	page_cache_release(p.v);
> >>  }
> >>  
> >> +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd,
> >> +			      unsigned short cmd_len)
> >> +{
> >> +	rq->cmd = cmd;
> >> +	rq->cmd_len = cmd_len;
> >> +}
> > 
> > Here's one way this will be used, in a patched bsg that understands
> > large commands.  Complication is the need to copy and hold onto the
> > big command across the duration of the request.
> > 
> > Submit time is fairly clean:
> > 
> > 	/* buf, len from user request */
> > 	rq = blk_get_request(..);
> > 	rq->cmd_len = len;
> > 	if (len > BLK_MAX_CDB) {
> > 		rq->cmd = kmalloc(len);
> > 		if (rq->cmd == NULL)
> > 			goto out;
> > 	}
> > 	copy_from_user(rq->cmd, buf, len);
> > 
> > Completion time needs to know when to free rq->cmd:
> > 
> > 	if (rq->cmd_len > BLK_MAX_CDB)
> > 		kfree(rq->cmd);
> > 	blk_put_request(rq);
> > 
> > Could use (rq->cmd != rq->__cmd) instead, but nothing had better
> > ever touch rq->cmd_len.
> > 
> 
> Don't do any of that please. The 16 bytes buffer at request is eventually
> going away. Just always allocate and call rq_set_cmd(). This way we are
> free to change in the future, and users code need not change.

Hmm, it's clean for bsg, but we nearly always allocates 16 bytes
dynamically. That's wasteful. Probably, we would loose some
performance as we did for sense buffer.


> And better then kmalloc the space for the command, is if you have
> a structure that governs your request, just allocate a 
> SCSI_MAX_VARLEN_CDB_SIZE (260) bytes array at your structure and always
> use that.

I don't put 260 bytes into bsg_command structure. I don't see why bsg
needs to be tuned up for OSD or for SCSI commands.

^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCH 0/3] scsi: variable-length CDBs support
  2008-04-14 10:50                 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
                                     ` (2 preceding siblings ...)
  2008-04-14 11:38                   ` Boaz Harrosh
@ 2008-04-15 12:24                   ` Boaz Harrosh
  2008-04-15 12:30                     ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
                                       ` (2 more replies)
  3 siblings, 3 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-15 12:24 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz,
	James Bottomley, Alasdair G Kergon, Geert Uytterhoeven

Based on TOMO's block patches for supporting large commands
These patches will enable support for variable-length, extended,
and vendor specific CDBs. It should now cover the entire range of the 
SCSI standard.

These patches are independent of TOMO's patches to the block layer, 
because the block layer API for drivers did not change. So all I did
was make sure nothing will break when large commands start coming.
They are based on scsi-misc and could go in as is. 

I have tested my OSD setup with scsi-misc + for-2.6.26 branch from
Jens + these patches and it all works fine. So I'm happy.

[1/3] Let scsi_cmnd->cmnd use request->cmd buffer
  Here I let scsi_cmnd->cmnd point to the space allocated by
  request->cmd, instead of copying the data. The scsi_cmnd->cmd_len
  is guaranteed to contain the right length of the command.
  I have tried to go over every single place in the kernel that uses
  scsi_cmnd->cmnd and make sure it looks sane. Surprisingly to me,
  that was not at all bad. I hope I did not miss anything.

  I've tested on an x86_64 machine booting from a sata disk and
  ran the iscsi regression tests as well as my bidi and varlen tests
  on top of the complete patchset and all tests passed.

[2/3] scsi: varlen extended and vendor-specific cdbs
  Adds support for variable length, extended, and vendor-specific
  cdbs at the scsi mid-layer.

[3/3] iscsi_tcp: Enable large commands
  One liner for iscsi_tcp. Mike please ACK this patch

Boaz


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer
  2008-04-15 12:24                   ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh
@ 2008-04-15 12:30                     ` Boaz Harrosh
  2008-04-15 12:34                     ` [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
  2008-04-15 12:37                     ` [PATCH 3/3] iscsi_tcp: Enable large commands Boaz Harrosh
  2 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-15 12:30 UTC (permalink / raw)
  To: FUJITA Tomonori, James Bottomley
  Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz,
	Alasdair G Kergon, Geert Uytterhoeven


 - struct scsi_cmnd had a 16 bytes command buffer of its own.
   This is an unnecessary duplication and copy of request's
   cmd. It is probably left overs from the time that scsi_cmnd
   could function without a request attached. So clean that up.

 - Once above is done, few places, apart from scsi-ml, needed
   adjustments due to changing the data type of scsi_cmnd->cmnd.

 - Lots of drivers still use MAX_COMMAND_SIZE. So I have left
   that #define but equate it to BLK_MAX_CDB. The way I see it
   and is reflected in the patch below is.
   MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB
                      as per the SCSI standard and is not related
                      to the implementation.
   BLK_MAX_CDB.     - The allocated space at the request level

 - I have audit all ISA drivers and made sure none use ->cmnd in a DMA
   Operation. Same audit was done by Andi Kleen.

(*)fixed-length here means commands that their size can be determined
   by their opcode and the CDB does not carry a length specifier, (unlike
   the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
   true and the SCSI standard also defines extended commands and
   vendor specific commands that can be bigger than 16 bytes. The kernel
   will support these using the same infrastructure used for VARLEN CDB's.
   So in effect MAX_COMMAND_SIZE means the maximum size command
   scsi-ml supports without specifying a cmd_len by ULD's

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/firewire/fw-sbp2.c       |    2 +-
 drivers/s390/scsi/zfcp_dbf.c     |    2 +-
 drivers/s390/scsi/zfcp_fsf.c     |    2 +-
 drivers/scsi/53c700.c            |    6 +++---
 drivers/scsi/a100u2w.c           |    2 +-
 drivers/scsi/gdth.c              |    2 +-
 drivers/scsi/hptiop.c            |    6 +++---
 drivers/scsi/ibmvscsi/ibmvscsi.c |    2 +-
 drivers/scsi/initio.c            |    2 +-
 drivers/scsi/qla1280.c           |    4 ++--
 drivers/scsi/scsi_error.c        |   14 ++++++++------
 drivers/scsi/scsi_lib.c          |    5 +++--
 drivers/scsi/scsi_tgt_lib.c      |    2 ++
 drivers/usb/storage/isd200.c     |    2 ++
 include/scsi/scsi_cmnd.h         |   21 +++++++++++++++++++--
 include/scsi/scsi_eh.h           |    4 ++--
 16 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 62b4e47..2260e56 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -1492,7 +1492,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 
 	memset(orb->request.command_block,
 	       0, sizeof(orb->request.command_block));
-	memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+	memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
 
 	orb->base.callback = complete_command_orb;
 	orb->base.request_bus =
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 85ba4cc..1bec0b2 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -1057,7 +1057,7 @@ static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
 				rec->scsi_result = scsi_cmnd->result;
 				rec->scsi_cmnd = (unsigned long)scsi_cmnd;
 				rec->scsi_serial = scsi_cmnd->serial_number;
-				memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+				memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
 					min((int)scsi_cmnd->cmd_len,
 						ZFCP_DBF_SCSI_OPCODE));
 				rec->scsi_retries = scsi_cmnd->retries;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index b7aa969..ea46881 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4024,7 +4024,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
 		ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n",
 			       scpnt->result);
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
-			      (void *) &scpnt->cmnd, scpnt->cmd_len);
+			      scpnt->cmnd, scpnt->cmd_len);
 
 		ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
 			       fcp_rsp_iu->fcp_sns_len);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index f4c4fe9..f5a9add 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
 			(struct NCR_700_command_slot *)SCp->host_scribble;
 		
 		dma_unmap_single(hostdata->dev, slot->pCmd,
-				 sizeof(SCp->cmnd), DMA_TO_DEVICE);
+				 MAX_COMMAND_SIZE, DMA_TO_DEVICE);
 		if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
 			char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
 #ifdef NCR_700_DEBUG
@@ -1004,7 +1004,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
 				 * here */
 				NCR_700_unmap(hostdata, SCp, slot);
 				dma_unmap_single(hostdata->dev, slot->pCmd,
-						 sizeof(SCp->cmnd),
+						 MAX_COMMAND_SIZE,
 						 DMA_TO_DEVICE);
 
 				cmnd[0] = REQUEST_SENSE;
@@ -1901,7 +1901,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *))
 	}
 	slot->resume_offset = 0;
 	slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd,
-				    sizeof(SCp->cmnd), DMA_TO_DEVICE);
+				    MAX_COMMAND_SIZE, DMA_TO_DEVICE);
 	NCR_700_start_command(SCp);
 	return 0;
 }
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 792b2e8..ced3eeb 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -895,7 +895,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru
 	} else {
 		scb->tag_msg = 0;	/* No tag support               */
 	}
-	memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len);
+	memcpy(scb->cdb, cmd->cmnd, scb->cdb_len);
 }
 
 /**
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index c6d6e7c..8e2e964 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -465,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
     scp->request = (struct request *)&wait;
     scp->timeout_per_command = timeout*HZ;
     scp->cmd_len = 12;
-    memcpy(scp->cmnd, cmnd, 12);
+    scp->cmnd = cmnd;
     cmndinfo.priority = IOCTL_PRI;
     cmndinfo.internal_cmd_str = gdtcmd;
     cmndinfo.internal_command = 1;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index beecda9..a24c5e3 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -763,9 +763,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp,
 			scp,
 			host->host_no, scp->device->channel,
 			scp->device->id, scp->device->lun,
-			*((u32 *)&scp->cmnd),
-			*((u32 *)&scp->cmnd + 1),
-			*((u32 *)&scp->cmnd + 2),
+			((u32 *)scp->cmnd)[0],
+			((u32 *)scp->cmnd)[1],
+			((u32 *)scp->cmnd)[2],
 			_req->index, _req->req_virt);
 
 	scp->result = 0;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 78d46a9..df9b865 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -738,7 +738,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
 	srp_cmd = &evt_struct->iu.srp.cmd;
 	memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
 	srp_cmd->opcode = SRP_CMD;
-	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb));
 	srp_cmd->lun = ((u64) lun) << 48;
 
 	if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index dbae3fd..e3f7397 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
 	cblk->hastat = 0;
 	cblk->tastat = 0;
 	/* Command the command */
-	memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
+	memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len);
 
 	/* Set up tags */
 	if (cmnd->device->tagged_supported) {	/* Tag Support                  */
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 68c0d09..b53420b 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -2863,7 +2863,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
 
 	/* Load SCSI command packet. */
 	pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
-	memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+	memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
 	/* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
 
 	/* Set transfer direction. */
@@ -3132,7 +3132,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
 
 	/* Load SCSI command packet. */
 	pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd));
-	memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd));
+	memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd));
 
 	/*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
 	/* Set transfer direction. */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 221f31e..8b5748a 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -626,7 +626,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
  * @scmd:       SCSI command structure to hijack
  * @ses:        structure to save restore information
  * @cmnd:       CDB to send. Can be NULL if no new cmnd is needed
- * @cmnd_size:  size in bytes of @cmnd
+ * @cmnd_size:  size in bytes of @cmnd (must be <= BLK_MAX_CDB)
  * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
  *
  * This function is used to save a scsi command information before re-execution
@@ -648,12 +648,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
 	 * command.
 	 */
 	ses->cmd_len = scmd->cmd_len;
-	memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
+	ses->cmnd = scmd->cmnd;
 	ses->data_direction = scmd->sc_data_direction;
 	ses->sdb = scmd->sdb;
 	ses->next_rq = scmd->request->next_rq;
 	ses->result = scmd->result;
 
+	scmd->cmnd = ses->eh_cmnd;
+	memset(scmd->cmnd, 0, BLK_MAX_CDB);
 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
 	scmd->request->next_rq = NULL;
 
@@ -665,14 +667,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
 		scmd->sdb.table.sgl = &ses->sense_sgl;
 		scmd->sc_data_direction = DMA_FROM_DEVICE;
 		scmd->sdb.table.nents = 1;
-		memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
 		scmd->cmnd[0] = REQUEST_SENSE;
 		scmd->cmnd[4] = scmd->sdb.length;
 		scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 	} else {
 		scmd->sc_data_direction = DMA_NONE;
 		if (cmnd) {
-			memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+			BUG_ON(cmnd_size > BLK_MAX_CDB);
 			memcpy(scmd->cmnd, cmnd, cmnd_size);
 			scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 		}
@@ -705,7 +706,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
 	 * Restore original data
 	 */
 	scmd->cmd_len = ses->cmd_len;
-	memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
+	scmd->cmnd = ses->cmnd;
 	scmd->sc_data_direction = ses->data_direction;
 	scmd->sdb = ses->sdb;
 	scmd->request->next_rq = ses->next_rq;
@@ -1774,7 +1775,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
 	scmd->request = &req;
 	memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
 
-	memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
+	scmd->cmnd = req.cmd;
+	memset(scmd->cmnd, 0, BLK_MAX_CDB);
     
 	scmd->scsi_done		= scsi_reset_provider_done_command;
 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 67f412b..325270b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1090,6 +1090,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
 	cmd->tag = req->tag;
 	cmd->request = req;
 
+	cmd->cmnd = req->cmd;
+
 	return cmd;
 }
 
@@ -1127,8 +1129,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 		req->buffer = NULL;
 	}
 
-	BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd));
-	memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
 	cmd->cmd_len = req->cmd_len;
 	if (!req->data_len)
 		cmd->sc_data_direction = DMA_NONE;
@@ -1165,6 +1165,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
 	if (unlikely(!cmd))
 		return BLKPREP_DEFER;
 
+	memset(cmd->cmnd, 0, BLK_MAX_CDB);
 	return scsi_init_io(cmd, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(scsi_setup_fs_cmnd);
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index a0f308b..8c92ef3 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -107,6 +107,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
 	cmd->jiffies_at_alloc = jiffies;
 	cmd->request = rq;
 
+	cmd->cmnd = rq->cmd;
+
 	rq->special = cmd;
 	rq->cmd_type = REQ_TYPE_SPECIAL;
 	rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 971d13d..3addcd8 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -292,6 +292,7 @@ struct isd200_info {
 
 	/* maximum number of LUNs supported */
 	unsigned char MaxLUNs;
+	unsigned char cmnd[BLK_MAX_CDB];
 	struct scsi_cmnd srb;
 	struct scatterlist sg;
 };
@@ -450,6 +451,7 @@ static int isd200_action( struct us_data *us, int action,
 
 	memset(&ata, 0, sizeof(ata));
 	memset(&srb_dev, 0, sizeof(srb_dev));
+	srb->cmnd = info->cmnd;
 	srb->device = &srb_dev;
 	++srb->serial_number;
 
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 8d20e60..dea73e5 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -7,10 +7,28 @@
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/scatterlist.h>
+#include <linux/blkdev.h>
 
 struct Scsi_Host;
 struct scsi_device;
 
+/*
+ * MAX_COMMAND_SIZE is:
+ * The longest fixed-length SCSI CDB as per the SCSI standard.
+ * fixed-length means: commands that their size can be determined
+ * by their opcode and the CDB does not carry a length specifier, (unlike
+ * the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly
+ * true and the SCSI standard also defines extended commands and
+ * vendor specific commands that can be bigger than 16 bytes. The kernel
+ * will support these using the same infrastructure used for VARLEN CDB's.
+ * So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml
+ * supports without specifying a cmd_len by ULD's
+ */
+#define MAX_COMMAND_SIZE 16
+#if (MAX_COMMAND_SIZE > BLK_MAX_CDB)
+# error MAX_COMMAND_SIZE can not be smaller than BLK_MAX_CDB
+#endif
+
 struct scsi_data_buffer {
 	struct sg_table table;
 	unsigned length;
@@ -64,8 +82,7 @@ struct scsi_cmnd {
 	enum dma_data_direction sc_data_direction;
 
 	/* These elements define the operation we are about to perform */
-#define MAX_COMMAND_SIZE	16
-	unsigned char cmnd[MAX_COMMAND_SIZE];
+	unsigned char *cmnd;
 
 	struct timer_list eh_timeout;	/* Used to time out the command. */
 
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index d3a133b..2a9add2 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -75,11 +75,11 @@ struct scsi_eh_save {
 	int result;
 	enum dma_data_direction data_direction;
 	unsigned char cmd_len;
-	unsigned char cmnd[MAX_COMMAND_SIZE];
+	unsigned char *cmnd;
 	struct scsi_data_buffer sdb;
 	struct request *next_rq;
-
 	/* new command support */
+	unsigned char eh_cmnd[BLK_MAX_CDB];
 	struct scatterlist sense_sgl;
 };
 
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs
  2008-04-15 12:24                   ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh
  2008-04-15 12:30                     ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
@ 2008-04-15 12:34                     ` Boaz Harrosh
  2008-04-16  2:09                       ` FUJITA Tomonori
  2008-04-15 12:37                     ` [PATCH 3/3] iscsi_tcp: Enable large commands Boaz Harrosh
  2 siblings, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-15 12:34 UTC (permalink / raw)
  To: FUJITA Tomonori, James Bottomley
  Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz,
	Alasdair G Kergon, Geert Uytterhoeven


Add support for variable-length, extended, and vendor specific
CDBs to scsi-ml. It is now possible for initiators and ULD's
to issue these types of commands. LLDs need not change much.
All they need is to raise the .max_cmd_len to the longest command
they support (see iscsi patch).

- clean-up some code paths that did not expect commands to be
  larger than 16, and change cmd_len members' type to short as
  char is not enough.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
 block/scsi_ioctl.c       |    5 ++---
 drivers/scsi/constants.c |   10 +++-------
 drivers/scsi/scsi.c      |   22 +++++++++++-----------
 drivers/scsi/scsi_lib.c  |    8 ++++++--
 include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
 include/scsi/scsi_cmnd.h |    2 +-
 include/scsi/scsi_host.h |    8 +++-----
 7 files changed, 59 insertions(+), 36 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index a2c3a93..aaf07e4 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -33,13 +33,12 @@
 #include <scsi/scsi_cmnd.h>
 
 /* Command group 3 is reserved and should never be used.  */
-const unsigned char scsi_command_size[8] =
+const unsigned char scsi_command_size_tbl[8] =
 {
 	6, 10, 10, 12,
 	16, 12, 10, 10
 };
-
-EXPORT_SYMBOL(scsi_command_size);
+EXPORT_SYMBOL(scsi_command_size_tbl);
 
 #include <scsi/sg.h>
 
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 403a7f2..9785d73 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -28,7 +28,6 @@
 #define SERVICE_ACTION_OUT_12 0xa9
 #define SERVICE_ACTION_IN_16 0x9e
 #define SERVICE_ACTION_OUT_16 0x9f
-#define VARIABLE_LENGTH_CMD 0x7f
 
 
 
@@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short variable length command, "
 			       "len=%d ext_len=%d", len, cdb_len);
@@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short opcode=0x%x command, len=%d "
 			       "ext_len=%d", cdb0, len, cdb_len);
@@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
 	int k, len;
 
 	print_opcode_name(cdb, 0);
-	if (VARIABLE_LENGTH_CMD == cdb[0])
-		len = cdb[7] + 8;
-	else
-		len = COMMAND_SIZE(cdb[0]);
+	len = scsi_command_size(cdb);
 	/* print out all bytes in cdb */
 	for (k = 0; k < len; ++k) 
 		printk(" %02x", cdb[k]);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index f6980bd..3dabecb 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
 #define MIN_RESET_PERIOD (15*HZ)
 
 /*
- * Macro to determine the size of SCSI command. This macro takes vendor
- * unique commands into account. SCSI commands in groups 6 and 7 are
- * vendor unique and we will depend upon the command length being
- * supplied correctly in cmd_len.
- */
-#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
-				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 	unsigned long flags = 0;
 	unsigned long timeout;
 	int rtn = 0;
+	unsigned cmd_len;
 
 	/* check if the device is still usable */
 	if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
@@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 	 * Before we queue this command, check if the command
 	 * length exceeds what the host adapter can handle.
 	 */
-	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
+	cmd_len = cmd->cmd_len;
+	if (!cmd_len) {
+		BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD);
+		cmd_len = COMMAND_SIZE((cmd)->cmnd[0]);
+	}
+
+	if (cmd_len > cmd->device->host->max_cmd_len) {
 		SCSI_LOG_MLQUEUE(3,
-				printk("queuecommand : command too long.\n"));
+			printk("queuecommand : command too long. "
+			       "cdb_size=%d host->max_cmd_len=%d\n",
+			       cmd->cmd_len, cmd->device->host->max_cmd_len));
 		cmd->result = (DID_ABORT << 16);
 
 		scsi_done(cmd);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 325270b..e621505 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
 
 	req->cmd_len = COMMAND_SIZE(cmd[0]);
 	memcpy(req->cmd, cmd, req->cmd_len);
+
 	req->sense = sense;
 	req->sense_len = 0;
 	req->retries = retries;
@@ -445,7 +446,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 	scsi_set_resid(cmd, 0);
 	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 	if (cmd->cmd_len == 0)
-		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+		cmd->cmd_len = scsi_command_size(cmd->cmnd);
 }
 
 void scsi_device_unbusy(struct scsi_device *sdev)
@@ -1130,13 +1131,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 	}
 
 	cmd->cmd_len = req->cmd_len;
+	if (!cmd->cmd_len)
+		cmd->cmd_len = scsi_command_size(cmd->cmnd);
+
 	if (!req->data_len)
 		cmd->sc_data_direction = DMA_NONE;
 	else if (rq_data_dir(req) == WRITE)
 		cmd->sc_data_direction = DMA_TO_DEVICE;
 	else
 		cmd->sc_data_direction = DMA_FROM_DEVICE;
-	
+
 	cmd->transfersize = req->data_len;
 	cmd->allowed = req->retries;
 	cmd->timeout_per_command = req->timeout;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 1f74bcd..32742c4 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -30,13 +30,6 @@
 #endif
 
 /*
- *	SCSI command lengths
- */
-
-extern const unsigned char scsi_command_size[8];
-#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
-
-/*
  * Special value for scanning to specify scanning or rescanning of all
  * possible channels, (target) ids, or luns on a given shost.
  */
@@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
 #define MODE_SENSE_10         0x5a
 #define PERSISTENT_RESERVE_IN 0x5e
 #define PERSISTENT_RESERVE_OUT 0x5f
+#define VARIABLE_LENGTH_CMD   0x7f
 #define REPORT_LUNS           0xa0
 #define MAINTENANCE_IN        0xa3
 #define MOVE_MEDIUM           0xa5
@@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8];
 #define	ATA_12		      0xa1	/* 12-byte pass-thru */
 
 /*
+ *	SCSI command lengths
+ */
+
+#define SCSI_MAX_VARLEN_CDB_SIZE 260
+
+/* defined in T10 SCSI Primary Commands-2 (SPC2) */
+struct scsi_varlen_cdb_hdr {
+	u8 opcode;        /* opcode always == VARIABLE_LENGTH_CMD */
+	u8 control;
+	u8 misc[5];
+	u8 additional_cdb_length;         /* total cdb length - 8 */
+	__be16 service_action;
+	/* service specific data follows */
+};
+
+static inline unsigned
+scsi_varlen_cdb_length(const void *hdr)
+{
+	return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8;
+}
+
+extern const unsigned char scsi_command_size_tbl[8];
+#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
+
+static inline unsigned
+scsi_command_size(const unsigned char *cmnd)
+{
+	return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
+		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
+}
+
+/*
  *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
  *  T10/1561-D Revision 4 Draft dated 7th November 2002.
  */
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index dea73e5..f4dacb1 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -78,7 +78,7 @@ struct scsi_cmnd {
 	int allowed;
 	int timeout_per_command;
 
-	unsigned char cmd_len;
+	unsigned short cmd_len;
 	enum dma_data_direction sc_data_direction;
 
 	/* These elements define the operation we are about to perform */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 4913286..31f1bfd 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -573,13 +573,11 @@ struct Scsi_Host {
 	/*
 	 * The maximum length of SCSI commands that this host can accept.
 	 * Probably 12 for most host adapters, but could be 16 for others.
+	 * or 260 if the driver supports variable length cdbs.
 	 * For drivers that don't set this field, a value of 12 is
-	 * assumed.  I am leaving this as a number rather than a bit
-	 * because you never know what subsequent SCSI standards might do
-	 * (i.e. could there be a 20 byte or a 24-byte command a few years
-	 * down the road?).  
+	 * assumed.
 	 */
-	unsigned char max_cmd_len;
+	unsigned short max_cmd_len;
 
 	int this_id;
 	int can_queue;
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 3/3] iscsi_tcp: Enable large commands
  2008-04-15 12:24                   ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh
  2008-04-15 12:30                     ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
  2008-04-15 12:34                     ` [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
@ 2008-04-15 12:37                     ` Boaz Harrosh
  2008-04-15 13:08                       ` James Smart
  2 siblings, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-15 12:37 UTC (permalink / raw)
  To: FUJITA Tomonori, James Bottomley, Mike Christie
  Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz,
	Alasdair G Kergon, Geert Uytterhoeven


Let through up to the largest command of 260 defined by the scsi standard.
iscsi core supports this already. Now that the scsi-ml supports it we can
start using large commands.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/iscsi_tcp.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 555f4e3..6500192 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1859,7 +1859,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
 	shost->max_lun = iscsi_max_lun;
 	shost->max_id = 0;
 	shost->max_channel = 0;
-	shost->max_cmd_len = 16;
+	shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
 	shost->can_queue = cmds_max;
 
 	if (iscsi_host_add(shost, NULL))
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* Re: [PATCH 3/3] iscsi_tcp: Enable large commands
  2008-04-15 12:37                     ` [PATCH 3/3] iscsi_tcp: Enable large commands Boaz Harrosh
@ 2008-04-15 13:08                       ` James Smart
  2008-04-15 13:38                         ` Boaz Harrosh
  2008-04-15 13:46                         ` FUJITA Tomonori
  0 siblings, 2 replies; 77+ messages in thread
From: James Smart @ 2008-04-15 13:08 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: FUJITA Tomonori, James Bottomley, Mike Christie, linux-scsi,
	Jens Axboe, Bartlomiej Zolnierkiewicz, Alasdair G Kergon,
	Geert Uytterhoeven

Boaz Harrosh wrote:
> Let through up to the largest command of 260 defined by the scsi standard.
> iscsi core supports this already. Now that the scsi-ml supports it we can
> start using large commands.

Just to double-check:
if we use sg_io to pass through requests from user-land, which are addressed to
drivers or transports, and which may not be a SCSI command but rather just something
utilizing the sg_io infrastructure for management or pass-thru, are we limited to
260 bytes for request/cmd payload ?

-- james s

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 3/3] iscsi_tcp: Enable large commands
  2008-04-15 13:08                       ` James Smart
@ 2008-04-15 13:38                         ` Boaz Harrosh
  2008-04-15 13:57                           ` Benny Halevy
  2008-04-15 13:46                         ` FUJITA Tomonori
  1 sibling, 1 reply; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-15 13:38 UTC (permalink / raw)
  To: James.Smart
  Cc: FUJITA Tomonori, James Bottomley, Mike Christie, linux-scsi,
	Jens Axboe, Bartlomiej Zolnierkiewicz, Alasdair G Kergon,
	Geert Uytterhoeven

On Tue, Apr 15 2008 at 16:08 +0300, James Smart <James.Smart@Emulex.Com> wrote:
> Boaz Harrosh wrote:
>> Let through up to the largest command of 260 defined by the scsi standard.
>> iscsi core supports this already. Now that the scsi-ml supports it we can
>> start using large commands.
> 
> Just to double-check:
> if we use sg_io to pass through requests from user-land, which are addressed to
> drivers or transports, and which may not be a SCSI command but rather just something
> utilizing the sg_io infrastructure for management or pass-thru, are we limited to
> 260 bytes for request/cmd payload ?
> 
> -- james s

I think that only bsg, after the pending patches get accepted, will let you
pass larger then 16 bytes commands from user-land. sg_io is I think limited 
to 16. However this could be fixed. (With sg_io, did you mean commands going
through the sg.c driver?)

The block layer imposes no limits, and so is scsi-ml. The only limits are from
ULDs, and LLDs, like here, iscsi protocol does not support more then 
SCSI_MAX_VARLEN_CDB_SIZE (260).

If you need support in any other ULD, I will be happy to help.

Boaz


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-14 22:33                             ` FUJITA Tomonori
@ 2008-04-15 13:44                               ` Pete Wyckoff
  0 siblings, 0 replies; 77+ messages in thread
From: Pete Wyckoff @ 2008-04-15 13:44 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: linux-scsi, bharrosh, jens.axboe, linux-ide

fujita.tomonori@lab.ntt.co.jp wrote on Tue, 15 Apr 2008 07:33 +0900:
> BTW, have you had a chance to try the bsg patches to fix the problems
> that you reported? I think that Mike and I analyzed the problem
> correctly and the patches works for me, but it would be nice if you
> can confirm that they also work for you.

It's on my TODO list.  Machines were down and papers are due.  But I
hope you can push the patches as bug fixes anyway.

		-- Pete

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 3/3] iscsi_tcp: Enable large commands
  2008-04-15 13:08                       ` James Smart
  2008-04-15 13:38                         ` Boaz Harrosh
@ 2008-04-15 13:46                         ` FUJITA Tomonori
  1 sibling, 0 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-15 13:46 UTC (permalink / raw)
  To: James.Smart
  Cc: bharrosh, fujita.tomonori, James.Bottomley, michaelc, linux-scsi,
	jens.axboe, bzolnier, agk, Geert.Uytterhoeven

On Tue, 15 Apr 2008 09:08:23 -0400
James Smart <James.Smart@Emulex.Com> wrote:

> Boaz Harrosh wrote:
> > Let through up to the largest command of 260 defined by the scsi standard.
> > iscsi core supports this already. Now that the scsi-ml supports it we can
> > start using large commands.
> 
> Just to double-check:
> if we use sg_io to pass through requests from user-land, which are addressed to
> drivers or transports, and which may not be a SCSI command but rather just something
> utilizing the sg_io infrastructure for management or pass-thru, are we limited to
> 260 bytes for request/cmd payload ?

With SG_IO (block, sg.c, and bsg), the command length is still limited
to 16 bytes (BLK_MAX_CDB). We will remove the limit in bsg shortly.

As you know, bsg supports bidi data transfer and there is no limit on
the length of request and response payload. SAS management protocol
uses request and response payload for data transfer. It doesn't use
the command area (that is used for SCSI command).

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 3/3] iscsi_tcp: Enable large commands
  2008-04-15 13:38                         ` Boaz Harrosh
@ 2008-04-15 13:57                           ` Benny Halevy
  0 siblings, 0 replies; 77+ messages in thread
From: Benny Halevy @ 2008-04-15 13:57 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James.Smart, FUJITA Tomonori, James Bottomley, Mike Christie,
	linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz,
	Alasdair G Kergon, Geert Uytterhoeven

On Apr. 15, 2008, 16:38 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
> On Tue, Apr 15 2008 at 16:08 +0300, James Smart <James.Smart@Emulex.Com> wrote:
>> Boaz Harrosh wrote:
>>> Let through up to the largest command of 260 defined by the scsi standard.
>>> iscsi core supports this already. Now that the scsi-ml supports it we can
>>> start using large commands.
>> Just to double-check:
>> if we use sg_io to pass through requests from user-land, which are addressed to
>> drivers or transports, and which may not be a SCSI command but rather just something
>> utilizing the sg_io infrastructure for management or pass-thru, are we limited to
>> 260 bytes for request/cmd payload ?
>>
>> -- james s
> 
> I think that only bsg, after the pending patches get accepted, will let you
> pass larger then 16 bytes commands from user-land. sg_io is I think limited 
> to 16. However this could be fixed. (With sg_io, did you mean commands going
> through the sg.c driver?)
> 
> The block layer imposes no limits, and so is scsi-ml. The only limits are from
> ULDs, and LLDs, like here, iscsi protocol does not support more then 
> SCSI_MAX_VARLEN_CDB_SIZE (260).

Actually the 260 byte limit comes from SCSI variable length CDB maximum length.
iSCSI allows to send larger CDBs with the Extended CDB AHS that has a 16 bit
length field. Within the protocol constraints, the longest CDB would be
16 (in BHS) + 65532 (in AHS) = 65548 bytes long :)

Benny

> 
> If you need support in any other ULD, I will be happy to help.
> 
> Boaz
> 
> --
> 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


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-14 11:29                           ` Jens Axboe
  2008-04-14 12:08                             ` FUJITA Tomonori
@ 2008-04-15 22:50                             ` Bartlomiej Zolnierkiewicz
  2008-04-15 22:57                               ` FUJITA Tomonori
  1 sibling, 1 reply; 77+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-04-15 22:50 UTC (permalink / raw)
  To: Jens Axboe
  Cc: FUJITA Tomonori, linux-scsi, bharrosh, linux-ide, Andrew Morton


Hi,

On Monday 14 April 2008, Jens Axboe wrote:
> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> > This patch changes rq->cmd from the static array to a pointer to
> > support large commands.
> > 
> > We rarely handle large commands. So for optimization, a struct request
> > still has a static array for a command. rq_init sets rq->cmd pointer
> > to the static array.
> > 
> > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > Cc: Jens Axboe <jens.axboe@oracle.com>
> > ---
> >  block/blk-core.c       |    1 +
> >  drivers/ide/ide-io.c   |    1 +
> >  include/linux/blkdev.h |   12 ++++++++++--
> >  3 files changed, 12 insertions(+), 2 deletions(-)
> > 
> > diff --git a/block/blk-core.c b/block/blk-core.c
> > index 6669238..6f0968f 100644
> > --- a/block/blk-core.c
> > +++ b/block/blk-core.c
> > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> >  	rq->errors = 0;
> >  	rq->ref_count = 1;
> >  	rq->cmd_len = 0;
> > +	rq->cmd = rq->__cmd;
> >  	memset(rq->cmd, 0, BLK_MAX_CDB);
> >  	rq->data_len = 0;
> >  	rq->extra_len = 0;
> > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> > index 7153796..bac5ea1 100644
> > --- a/drivers/ide/ide-io.c
> > +++ b/drivers/ide/ide-io.c
> > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> >  {
> >  	memset(rq, 0, sizeof(*rq));
> >  	rq->ref_count = 1;
> > +	rq->cmd = rq->__cmd;
> >  }

Tomo, some more changes are needed:

Please think about all _static_/dynamic allocations of 'struct request'
used together with REQ_TYPE_SPECIAL etc., i.e.

static void idetape_init_rq(struct request *rq, u8 cmd)

[ rq can be from privately allocated driver's "stack" so no rq_init() ]

{
	memset(rq, 0, sizeof(*rq));
	rq->cmd_type = REQ_TYPE_SPECIAL;
	rq->cmd[0] = cmd;
}

in ide-tape.c or REQ_TYPE_SENSE in ide-cd.c:

static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
                                      struct request *failed_command)
{
        struct cdrom_info *info         = drive->driver_data;
        struct request *rq              = &info->request_sense_request;

        if (sense == NULL)
                sense = &info->sense_data;

        /* stuff the sense request in front of our current request */
        ide_cd_init_rq(drive, rq);

        rq->data = 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;

        (void) ide_do_drive_cmd(drive, rq, ide_preempt);
}

> >  EXPORT_SYMBOL(ide_init_drive_cmd);
> > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> > index b3a58ad..5710ae4 100644
> > --- a/include/linux/blkdev.h
> > +++ b/include/linux/blkdev.h
> > @@ -215,8 +215,9 @@ struct request {
> >  	/*
> >  	 * when request is used as a packet command carrier
> >  	 */
> > -	unsigned int cmd_len;
> > -	unsigned char cmd[BLK_MAX_CDB];
> > +	unsigned short cmd_len;
> > +	unsigned char __cmd[BLK_MAX_CDB];
> > +	unsigned char *cmd;

The source issue lies here:

rq->cmd _silently_ becomes something else and unconverted code will happily
compile without even a _single_ warning (+ memory corruption / oops later).

This is _guaranteed_ to cause problems:

- overlooked code (like the IDE code above, with the current approach
  you have to _manually_ audit all code and still _can't_ be sure about
  the result)

- unmerged code from other trees (i.e., I _have_ WIP patches mapping
  REQ_TYPE_TASKFILE requests onto rq->cmd)

- out of tree code (in theory we don't care but in this specific
  case there is no reason to break things silently)

Please just add new field instead (cost should be negligable and if
we're concerned about it I see no problem with using unnamed union like
it was done by Boaz). 

[ Probably it is also worth to add new length field instead of re-using
  ->cmd_len, just to stay on the safe side (+ for better consistency). ]

> >  	unsigned int data_len;
> >  	unsigned int extra_len;	/* length of alignment and padding */
> > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p)
> >  	page_cache_release(p.v);
> >  }
> >  
> > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd,
> > +			      unsigned short cmd_len)
> > +{
> > +	rq->cmd = cmd;
> > +	rq->cmd_len = cmd_len;
> > +}
> > +
> 
> This is 100% identical to what I suggested be done instead, so of course
> I agree with this.

Jens, I see that you've applied this patch to block tree
- please revert it for now, it needs to be re-designed.

Thanks,
Bart

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-15 22:50                             ` Bartlomiej Zolnierkiewicz
@ 2008-04-15 22:57                               ` FUJITA Tomonori
  2008-04-16  0:22                                 ` Bartlomiej Zolnierkiewicz
  2008-04-16  8:33                                 ` Jens Axboe
  0 siblings, 2 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-15 22:57 UTC (permalink / raw)
  To: bzolnier; +Cc: jens.axboe, fujita.tomonori, linux-scsi, bharrosh, linux-ide,
	akpm

On Wed, 16 Apr 2008 00:50:54 +0200
Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:

> 
> Hi,
> 
> On Monday 14 April 2008, Jens Axboe wrote:
> > On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> > > This patch changes rq->cmd from the static array to a pointer to
> > > support large commands.
> > > 
> > > We rarely handle large commands. So for optimization, a struct request
> > > still has a static array for a command. rq_init sets rq->cmd pointer
> > > to the static array.
> > > 
> > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > > Cc: Jens Axboe <jens.axboe@oracle.com>
> > > ---
> > >  block/blk-core.c       |    1 +
> > >  drivers/ide/ide-io.c   |    1 +
> > >  include/linux/blkdev.h |   12 ++++++++++--
> > >  3 files changed, 12 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/block/blk-core.c b/block/blk-core.c
> > > index 6669238..6f0968f 100644
> > > --- a/block/blk-core.c
> > > +++ b/block/blk-core.c
> > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> > >  	rq->errors = 0;
> > >  	rq->ref_count = 1;
> > >  	rq->cmd_len = 0;
> > > +	rq->cmd = rq->__cmd;
> > >  	memset(rq->cmd, 0, BLK_MAX_CDB);
> > >  	rq->data_len = 0;
> > >  	rq->extra_len = 0;
> > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> > > index 7153796..bac5ea1 100644
> > > --- a/drivers/ide/ide-io.c
> > > +++ b/drivers/ide/ide-io.c
> > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> > >  {
> > >  	memset(rq, 0, sizeof(*rq));
> > >  	rq->ref_count = 1;
> > > +	rq->cmd = rq->__cmd;
> > >  }
> 
> Tomo, some more changes are needed:
> 
> Please think about all _static_/dynamic allocations of 'struct request'
> used together with REQ_TYPE_SPECIAL etc., i.e.

I think that using struct request allocated statically is wrong from
the perspective of the block layer design, that is, you always need to
use blk_get_request. I think that except ide, everyone does.

I try to convert ide to use blk_get_request properly if you want.


> static void idetape_init_rq(struct request *rq, u8 cmd)
> 
> [ rq can be from privately allocated driver's "stack" so no rq_init() ]
> 
> {
> 	memset(rq, 0, sizeof(*rq));
> 	rq->cmd_type = REQ_TYPE_SPECIAL;
> 	rq->cmd[0] = cmd;
> }
> 
> in ide-tape.c or REQ_TYPE_SENSE in ide-cd.c:

Thanks, I overlooked this. As I did for ide_init_drive_cmd, we need:


+	rq->cmd = rq->__cmd;


> static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
>                                       struct request *failed_command)
> {
>         struct cdrom_info *info         = drive->driver_data;
>         struct request *rq              = &info->request_sense_request;
> 
>         if (sense == NULL)
>                 sense = &info->sense_data;
> 
>         /* stuff the sense request in front of our current request */
>         ide_cd_init_rq(drive, rq);
> 
>         rq->data = 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;
> 
>         (void) ide_do_drive_cmd(drive, rq, ide_preempt);
> }

This should work since I put the above hack to ide_init_drive_cmd (I
tested the patchset with an ide cdrom drive).


> > >  EXPORT_SYMBOL(ide_init_drive_cmd);
> > > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> > > index b3a58ad..5710ae4 100644
> > > --- a/include/linux/blkdev.h
> > > +++ b/include/linux/blkdev.h
> > > @@ -215,8 +215,9 @@ struct request {
> > >  	/*
> > >  	 * when request is used as a packet command carrier
> > >  	 */
> > > -	unsigned int cmd_len;
> > > -	unsigned char cmd[BLK_MAX_CDB];
> > > +	unsigned short cmd_len;
> > > +	unsigned char __cmd[BLK_MAX_CDB];
> > > +	unsigned char *cmd;
> 
> The source issue lies here:
> 
> rq->cmd _silently_ becomes something else and unconverted code will happily
> compile without even a _single_ warning (+ memory corruption / oops later).
> 
> This is _guaranteed_ to cause problems:
> 
> - overlooked code (like the IDE code above, with the current approach
>   you have to _manually_ audit all code and still _can't_ be sure about
>   the result)

As far as I know, only ide does that.


> - unmerged code from other trees (i.e., I _have_ WIP patches mapping
>   REQ_TYPE_TASKFILE requests onto rq->cmd)
> 
> - out of tree code (in theory we don't care but in this specific
>   case there is no reason to break things silently)

Again, I think that we can say that we need to use the block layer
properly, struct request always needs to be allocated via
blk_get_request.


> Please just add new field instead (cost should be negligable and if
> we're concerned about it I see no problem with using unnamed union like
> it was done by Boaz). 
> 
> [ Probably it is also worth to add new length field instead of re-using
>   ->cmd_len, just to stay on the safe side (+ for better consistency). ]

As we discussed, we don't like that hack:

http://marc.info/?t=120724777800003&r=1&w=2


> > >  	unsigned int data_len;
> > >  	unsigned int extra_len;	/* length of alignment and padding */
> > > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p)
> > >  	page_cache_release(p.v);
> > >  }
> > >  
> > > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd,
> > > +			      unsigned short cmd_len)
> > > +{
> > > +	rq->cmd = cmd;
> > > +	rq->cmd_len = cmd_len;
> > > +}
> > > +
> > 
> > This is 100% identical to what I suggested be done instead, so of course
> > I agree with this.
> 
> Jens, I see that you've applied this patch to block tree
> - please revert it for now, it needs to be re-designed.
> 
> Thanks,
> Bart
> --
> 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

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-15 22:57                               ` FUJITA Tomonori
@ 2008-04-16  0:22                                 ` Bartlomiej Zolnierkiewicz
  2008-04-16  8:33                                 ` Jens Axboe
  1 sibling, 0 replies; 77+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-04-16  0:22 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: jens.axboe, linux-scsi, bharrosh, linux-ide, akpm

On Wednesday 16 April 2008, FUJITA Tomonori wrote:
> On Wed, 16 Apr 2008 00:50:54 +0200
> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
> 
> > 
> > Hi,
> > 
> > On Monday 14 April 2008, Jens Axboe wrote:
> > > On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> > > > This patch changes rq->cmd from the static array to a pointer to
> > > > support large commands.
> > > > 
> > > > We rarely handle large commands. So for optimization, a struct request
> > > > still has a static array for a command. rq_init sets rq->cmd pointer
> > > > to the static array.
> > > > 
> > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > > > Cc: Jens Axboe <jens.axboe@oracle.com>
> > > > ---
> > > >  block/blk-core.c       |    1 +
> > > >  drivers/ide/ide-io.c   |    1 +
> > > >  include/linux/blkdev.h |   12 ++++++++++--
> > > >  3 files changed, 12 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/block/blk-core.c b/block/blk-core.c
> > > > index 6669238..6f0968f 100644
> > > > --- a/block/blk-core.c
> > > > +++ b/block/blk-core.c
> > > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> > > >  	rq->errors = 0;
> > > >  	rq->ref_count = 1;
> > > >  	rq->cmd_len = 0;
> > > > +	rq->cmd = rq->__cmd;
> > > >  	memset(rq->cmd, 0, BLK_MAX_CDB);
> > > >  	rq->data_len = 0;
> > > >  	rq->extra_len = 0;
> > > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> > > > index 7153796..bac5ea1 100644
> > > > --- a/drivers/ide/ide-io.c
> > > > +++ b/drivers/ide/ide-io.c
> > > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> > > >  {
> > > >  	memset(rq, 0, sizeof(*rq));
> > > >  	rq->ref_count = 1;
> > > > +	rq->cmd = rq->__cmd;
> > > >  }
> > 
> > Tomo, some more changes are needed:
> > 
> > Please think about all _static_/dynamic allocations of 'struct request'
> > used together with REQ_TYPE_SPECIAL etc., i.e.
> 
> I think that using struct request allocated statically is wrong from
> the perspective of the block layer design, that is, you always need to
> use blk_get_request. I think that except ide, everyone does.

There still are some others like:

- scsi/scsi_error.c::scsi_reset_provider()

- paride/pd.c::pd_special_command()

but yeah, IDE has the most users left.

> I try to convert ide to use blk_get_request properly if you want.

I would love to see the patches.

> > static void idetape_init_rq(struct request *rq, u8 cmd)
> > 
> > [ rq can be from privately allocated driver's "stack" so no rq_init() ]
> > 
> > {
> > 	memset(rq, 0, sizeof(*rq));
> > 	rq->cmd_type = REQ_TYPE_SPECIAL;
> > 	rq->cmd[0] = cmd;
> > }
> > 
> > in ide-tape.c or REQ_TYPE_SENSE in ide-cd.c:
> 
> Thanks, I overlooked this. As I did for ide_init_drive_cmd, we need:
> 
> 
> +	rq->cmd = rq->__cmd;
> 
> 
> > static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
> >                                       struct request *failed_command)
> > {
> >         struct cdrom_info *info         = drive->driver_data;
> >         struct request *rq              = &info->request_sense_request;
> > 
> >         if (sense == NULL)
> >                 sense = &info->sense_data;
> > 
> >         /* stuff the sense request in front of our current request */
> >         ide_cd_init_rq(drive, rq);
> > 
> >         rq->data = 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;
> > 
> >         (void) ide_do_drive_cmd(drive, rq, ide_preempt);
> > }
> 
> This should work since I put the above hack to ide_init_drive_cmd (I
> tested the patchset with an ide cdrom drive).

Indeed, it is called by ide_cd_init_rq() (I blame 2AM).

> > > >  EXPORT_SYMBOL(ide_init_drive_cmd);
> > > > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
> > > > index b3a58ad..5710ae4 100644
> > > > --- a/include/linux/blkdev.h
> > > > +++ b/include/linux/blkdev.h
> > > > @@ -215,8 +215,9 @@ struct request {
> > > >  	/*
> > > >  	 * when request is used as a packet command carrier
> > > >  	 */
> > > > -	unsigned int cmd_len;
> > > > -	unsigned char cmd[BLK_MAX_CDB];
> > > > +	unsigned short cmd_len;
> > > > +	unsigned char __cmd[BLK_MAX_CDB];
> > > > +	unsigned char *cmd;
> > 
> > The source issue lies here:
> > 
> > rq->cmd _silently_ becomes something else and unconverted code will happily
> > compile without even a _single_ warning (+ memory corruption / oops later).
> > 
> > This is _guaranteed_ to cause problems:
> > 
> > - overlooked code (like the IDE code above, with the current approach
> >   you have to _manually_ audit all code and still _can't_ be sure about
> >   the result)
> 
> As far as I know, only ide does that.

Well, if there are others you'll learn about them the hard-way... ;-)

[ The thing is that you can avoid answering this question completely
  with the "ugly" approach. ]

> > - unmerged code from other trees (i.e., I _have_ WIP patches mapping
> >   REQ_TYPE_TASKFILE requests onto rq->cmd)
> > 
> > - out of tree code (in theory we don't care but in this specific
> >   case there is no reason to break things silently)
> 
> Again, I think that we can say that we need to use the block layer
> properly, struct request always needs to be allocated via
> blk_get_request.

Hmm, in this case some code asserting that only blk_bet_request()
requests allowed in the block layer would be useful.

> > Please just add new field instead (cost should be negligable and if
> > we're concerned about it I see no problem with using unnamed union like
> > it was done by Boaz). 
> > 
> > [ Probably it is also worth to add new length field instead of re-using
> >   ->cmd_len, just to stay on the safe side (+ for better consistency). ]
> 
> As we discussed, we don't like that hack:
> 
> http://marc.info/?t=120724777800003&r=1&w=2

If you audit+fixup IDE I'm also fine with non-"hack" solution.

Thanks,
Bart

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs
  2008-04-15 12:34                     ` [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
@ 2008-04-16  2:09                       ` FUJITA Tomonori
  2008-04-16  6:40                         ` Boaz Harrosh
  0 siblings, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-16  2:09 UTC (permalink / raw)
  To: bharrosh
  Cc: fujita.tomonori, James.Bottomley, linux-scsi, jens.axboe,
	bzolnier, agk, Geert.Uytterhoeven

On Tue, 15 Apr 2008 15:34:47 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> 
> Add support for variable-length, extended, and vendor specific
> CDBs to scsi-ml. It is now possible for initiators and ULD's
> to issue these types of commands. LLDs need not change much.
> All they need is to raise the .max_cmd_len to the longest command
> they support (see iscsi patch).
> 
> - clean-up some code paths that did not expect commands to be
>   larger than 16, and change cmd_len members' type to short as
>   char is not enough.
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
>  block/scsi_ioctl.c       |    5 ++---
>  drivers/scsi/constants.c |   10 +++-------
>  drivers/scsi/scsi.c      |   22 +++++++++++-----------
>  drivers/scsi/scsi_lib.c  |    8 ++++++--
>  include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
>  include/scsi/scsi_cmnd.h |    2 +-
>  include/scsi/scsi_host.h |    8 +++-----
>  7 files changed, 59 insertions(+), 36 deletions(-)
> 
> diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
> index a2c3a93..aaf07e4 100644
> --- a/block/scsi_ioctl.c
> +++ b/block/scsi_ioctl.c
> @@ -33,13 +33,12 @@
>  #include <scsi/scsi_cmnd.h>
>  
>  /* Command group 3 is reserved and should never be used.  */
> -const unsigned char scsi_command_size[8] =
> +const unsigned char scsi_command_size_tbl[8] =
>  {
>  	6, 10, 10, 12,
>  	16, 12, 10, 10
>  };
> -
> -EXPORT_SYMBOL(scsi_command_size);
> +EXPORT_SYMBOL(scsi_command_size_tbl);
>  
>  #include <scsi/sg.h>
>  
> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
> index 403a7f2..9785d73 100644
> --- a/drivers/scsi/constants.c
> +++ b/drivers/scsi/constants.c
> @@ -28,7 +28,6 @@
>  #define SERVICE_ACTION_OUT_12 0xa9
>  #define SERVICE_ACTION_IN_16 0x9e
>  #define SERVICE_ACTION_OUT_16 0x9f
> -#define VARIABLE_LENGTH_CMD 0x7f
>  
>  
>  
> @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
>  	cdb0 = cdbp[0];
>  	switch(cdb0) {
>  	case VARIABLE_LENGTH_CMD:
> -		len = cdbp[7] + 8;
> +		len = scsi_varlen_cdb_length(cdbp);
>  		if (len < 10) {
>  			printk("short variable length command, "
>  			       "len=%d ext_len=%d", len, cdb_len);
> @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
>  	cdb0 = cdbp[0];
>  	switch(cdb0) {
>  	case VARIABLE_LENGTH_CMD:
> -		len = cdbp[7] + 8;
> +		len = scsi_varlen_cdb_length(cdbp);
>  		if (len < 10) {
>  			printk("short opcode=0x%x command, len=%d "
>  			       "ext_len=%d", cdb0, len, cdb_len);
> @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
>  	int k, len;
>  
>  	print_opcode_name(cdb, 0);
> -	if (VARIABLE_LENGTH_CMD == cdb[0])
> -		len = cdb[7] + 8;
> -	else
> -		len = COMMAND_SIZE(cdb[0]);
> +	len = scsi_command_size(cdb);
>  	/* print out all bytes in cdb */
>  	for (k = 0; k < len; ++k) 
>  		printk(" %02x", cdb[k]);
> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
> index f6980bd..3dabecb 100644
> --- a/drivers/scsi/scsi.c
> +++ b/drivers/scsi/scsi.c
> @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
>  #define MIN_RESET_PERIOD (15*HZ)
>  
>  /*
> - * Macro to determine the size of SCSI command. This macro takes vendor
> - * unique commands into account. SCSI commands in groups 6 and 7 are
> - * vendor unique and we will depend upon the command length being
> - * supplied correctly in cmd_len.
> - */
> -#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
> -				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
> -
> -/*
>   * Note - the initial logging level can be set here to log events at boot time.
>   * After the system is up, you may enable logging via the /proc interface.
>   */
> @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
>  	unsigned long flags = 0;
>  	unsigned long timeout;
>  	int rtn = 0;
> +	unsigned cmd_len;
>  
>  	/* check if the device is still usable */
>  	if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
> @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
>  	 * Before we queue this command, check if the command
>  	 * length exceeds what the host adapter can handle.
>  	 */
> -	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
> +	cmd_len = cmd->cmd_len;
> +	if (!cmd_len) {
> +		BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD);
> +		cmd_len = COMMAND_SIZE((cmd)->cmnd[0]);
> +	}

Hmm, how can cmd->cmd_len be zero here?


> +	if (cmd_len > cmd->device->host->max_cmd_len) {
>  		SCSI_LOG_MLQUEUE(3,
> -				printk("queuecommand : command too long.\n"));
> +			printk("queuecommand : command too long. "
> +			       "cdb_size=%d host->max_cmd_len=%d\n",
> +			       cmd->cmd_len, cmd->device->host->max_cmd_len));
>  		cmd->result = (DID_ABORT << 16);

Why can't we just do:

if (scsi_command_size(cmd->cmnd) > cmd->device->host->max_cmd_len) {


>  		scsi_done(cmd);
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index 325270b..e621505 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
>  
>  	req->cmd_len = COMMAND_SIZE(cmd[0]);
>  	memcpy(req->cmd, cmd, req->cmd_len);
> +

Please don't put a new line at a place unrelated with this patch.


>  	req->sense = sense;
>  	req->sense_len = 0;
>  	req->retries = retries;
> @@ -445,7 +446,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
>  	scsi_set_resid(cmd, 0);
>  	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
>  	if (cmd->cmd_len == 0)
> -		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
> +		cmd->cmd_len = scsi_command_size(cmd->cmnd);
>  }
>  
>  void scsi_device_unbusy(struct scsi_device *sdev)
> @@ -1130,13 +1131,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
>  	}
>  
>  	cmd->cmd_len = req->cmd_len;
> +	if (!cmd->cmd_len)
> +		cmd->cmd_len = scsi_command_size(cmd->cmnd);
> +

how can cmd->cmd_len be zero here? SG_IO path sets up req->cmd_len
properly for PC commands.


>  	if (!req->data_len)
>  		cmd->sc_data_direction = DMA_NONE;
>  	else if (rq_data_dir(req) == WRITE)
>  		cmd->sc_data_direction = DMA_TO_DEVICE;
>  	else
>  		cmd->sc_data_direction = DMA_FROM_DEVICE;
> -	
> +
>  	cmd->transfersize = req->data_len;
>  	cmd->allowed = req->retries;
>  	cmd->timeout_per_command = req->timeout;
> diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
> index 1f74bcd..32742c4 100644
> --- a/include/scsi/scsi.h
> +++ b/include/scsi/scsi.h
> @@ -30,13 +30,6 @@
>  #endif
>  
>  /*
> - *	SCSI command lengths
> - */
> -
> -extern const unsigned char scsi_command_size[8];
> -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
> -
> -/*
>   * Special value for scanning to specify scanning or rescanning of all
>   * possible channels, (target) ids, or luns on a given shost.
>   */
> @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
>  #define MODE_SENSE_10         0x5a
>  #define PERSISTENT_RESERVE_IN 0x5e
>  #define PERSISTENT_RESERVE_OUT 0x5f
> +#define VARIABLE_LENGTH_CMD   0x7f
>  #define REPORT_LUNS           0xa0
>  #define MAINTENANCE_IN        0xa3
>  #define MOVE_MEDIUM           0xa5
> @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8];
>  #define	ATA_12		      0xa1	/* 12-byte pass-thru */
>  
>  /*
> + *	SCSI command lengths
> + */
> +
> +#define SCSI_MAX_VARLEN_CDB_SIZE 260
> +
> +/* defined in T10 SCSI Primary Commands-2 (SPC2) */
> +struct scsi_varlen_cdb_hdr {
> +	u8 opcode;        /* opcode always == VARIABLE_LENGTH_CMD */
> +	u8 control;
> +	u8 misc[5];
> +	u8 additional_cdb_length;         /* total cdb length - 8 */
> +	__be16 service_action;
> +	/* service specific data follows */
> +};
> +
> +static inline unsigned
> +scsi_varlen_cdb_length(const void *hdr)
> +{
> +	return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8;
> +}
> +
> +extern const unsigned char scsi_command_size_tbl[8];
> +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
> +
> +static inline unsigned
> +scsi_command_size(const unsigned char *cmnd)
> +{
> +	return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
> +		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
> +}
> +
> +/*
>   *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
>   *  T10/1561-D Revision 4 Draft dated 7th November 2002.
>   */
> diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
> index dea73e5..f4dacb1 100644
> --- a/include/scsi/scsi_cmnd.h
> +++ b/include/scsi/scsi_cmnd.h
> @@ -78,7 +78,7 @@ struct scsi_cmnd {
>  	int allowed;
>  	int timeout_per_command;
>  
> -	unsigned char cmd_len;
> +	unsigned short cmd_len;
>  	enum dma_data_direction sc_data_direction;
>  
>  	/* These elements define the operation we are about to perform */
> diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
> index 4913286..31f1bfd 100644
> --- a/include/scsi/scsi_host.h
> +++ b/include/scsi/scsi_host.h
> @@ -573,13 +573,11 @@ struct Scsi_Host {
>  	/*
>  	 * The maximum length of SCSI commands that this host can accept.
>  	 * Probably 12 for most host adapters, but could be 16 for others.
> +	 * or 260 if the driver supports variable length cdbs.
>  	 * For drivers that don't set this field, a value of 12 is
> -	 * assumed.  I am leaving this as a number rather than a bit
> -	 * because you never know what subsequent SCSI standards might do
> -	 * (i.e. could there be a 20 byte or a 24-byte command a few years
> -	 * down the road?).  
> +	 * assumed.
>  	 */
> -	unsigned char max_cmd_len;
> +	unsigned short max_cmd_len;
>  
>  	int this_id;
>  	int can_queue;
> -- 
> 1.5.3.3
> 
> 
> --
> 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

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs
  2008-04-16  2:09                       ` FUJITA Tomonori
@ 2008-04-16  6:40                         ` Boaz Harrosh
  2008-04-16  6:49                           ` [PATCH 2/3 ver2] " Boaz Harrosh
  2008-04-17  4:01                           ` [PATCH 2/3] " FUJITA Tomonori
  0 siblings, 2 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-16  6:40 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: James.Bottomley, linux-scsi, jens.axboe, bzolnier, agk,
	Geert.Uytterhoeven

On Wed, Apr 16 2008 at 5:09 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> On Tue, 15 Apr 2008 15:34:47 +0300
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> Add support for variable-length, extended, and vendor specific
>> CDBs to scsi-ml. It is now possible for initiators and ULD's
>> to issue these types of commands. LLDs need not change much.
>> All they need is to raise the .max_cmd_len to the longest command
>> they support (see iscsi patch).
>>
>> - clean-up some code paths that did not expect commands to be
>>   larger than 16, and change cmd_len members' type to short as
>>   char is not enough.
>>
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
>> ---
>>  block/scsi_ioctl.c       |    5 ++---
>>  drivers/scsi/constants.c |   10 +++-------
>>  drivers/scsi/scsi.c      |   22 +++++++++++-----------
>>  drivers/scsi/scsi_lib.c  |    8 ++++++--
>>  include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
>>  include/scsi/scsi_cmnd.h |    2 +-
>>  include/scsi/scsi_host.h |    8 +++-----
>>  7 files changed, 59 insertions(+), 36 deletions(-)
>>
>> diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
>> index a2c3a93..aaf07e4 100644
>> --- a/block/scsi_ioctl.c
>> +++ b/block/scsi_ioctl.c
>> @@ -33,13 +33,12 @@
>>  #include <scsi/scsi_cmnd.h>
>>  
>>  /* Command group 3 is reserved and should never be used.  */
>> -const unsigned char scsi_command_size[8] =
>> +const unsigned char scsi_command_size_tbl[8] =
>>  {
>>  	6, 10, 10, 12,
>>  	16, 12, 10, 10
>>  };
>> -
>> -EXPORT_SYMBOL(scsi_command_size);
>> +EXPORT_SYMBOL(scsi_command_size_tbl);
>>  
>>  #include <scsi/sg.h>
>>  
>> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
>> index 403a7f2..9785d73 100644
>> --- a/drivers/scsi/constants.c
>> +++ b/drivers/scsi/constants.c
>> @@ -28,7 +28,6 @@
>>  #define SERVICE_ACTION_OUT_12 0xa9
>>  #define SERVICE_ACTION_IN_16 0x9e
>>  #define SERVICE_ACTION_OUT_16 0x9f
>> -#define VARIABLE_LENGTH_CMD 0x7f
>>  
>>  
>>  
>> @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
>>  	cdb0 = cdbp[0];
>>  	switch(cdb0) {
>>  	case VARIABLE_LENGTH_CMD:
>> -		len = cdbp[7] + 8;
>> +		len = scsi_varlen_cdb_length(cdbp);
>>  		if (len < 10) {
>>  			printk("short variable length command, "
>>  			       "len=%d ext_len=%d", len, cdb_len);
>> @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
>>  	cdb0 = cdbp[0];
>>  	switch(cdb0) {
>>  	case VARIABLE_LENGTH_CMD:
>> -		len = cdbp[7] + 8;
>> +		len = scsi_varlen_cdb_length(cdbp);
>>  		if (len < 10) {
>>  			printk("short opcode=0x%x command, len=%d "
>>  			       "ext_len=%d", cdb0, len, cdb_len);
>> @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
>>  	int k, len;
>>  
>>  	print_opcode_name(cdb, 0);
>> -	if (VARIABLE_LENGTH_CMD == cdb[0])
>> -		len = cdb[7] + 8;
>> -	else
>> -		len = COMMAND_SIZE(cdb[0]);
>> +	len = scsi_command_size(cdb);
>>  	/* print out all bytes in cdb */
>>  	for (k = 0; k < len; ++k) 
>>  		printk(" %02x", cdb[k]);
>> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
>> index f6980bd..3dabecb 100644
>> --- a/drivers/scsi/scsi.c
>> +++ b/drivers/scsi/scsi.c
>> @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
>>  #define MIN_RESET_PERIOD (15*HZ)
>>  
>>  /*
>> - * Macro to determine the size of SCSI command. This macro takes vendor
>> - * unique commands into account. SCSI commands in groups 6 and 7 are
>> - * vendor unique and we will depend upon the command length being
>> - * supplied correctly in cmd_len.
>> - */
>> -#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
>> -				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
>> -
>> -/*
>>   * Note - the initial logging level can be set here to log events at boot time.
>>   * After the system is up, you may enable logging via the /proc interface.
>>   */
>> @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
>>  	unsigned long flags = 0;
>>  	unsigned long timeout;
>>  	int rtn = 0;
>> +	unsigned cmd_len;
>>  
>>  	/* check if the device is still usable */
>>  	if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
>> @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
>>  	 * Before we queue this command, check if the command
>>  	 * length exceeds what the host adapter can handle.
>>  	 */
>> -	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
>> +	cmd_len = cmd->cmd_len;
>> +	if (!cmd_len) {
>> +		BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD);
>> +		cmd_len = COMMAND_SIZE((cmd)->cmnd[0]);
>> +	}
> 
> Hmm, how can cmd->cmd_len be zero here?
> 

With FS_PC commands this is zero here. Because ULD prepare the command
only after prep_fn.

> 
>> +	if (cmd_len > cmd->device->host->max_cmd_len) {
>>  		SCSI_LOG_MLQUEUE(3,
>> -				printk("queuecommand : command too long.\n"));
>> +			printk("queuecommand : command too long. "
>> +			       "cdb_size=%d host->max_cmd_len=%d\n",
>> +			       cmd->cmd_len, cmd->device->host->max_cmd_len));
>>  		cmd->result = (DID_ABORT << 16);
> 
> Why can't we just do:
> 
> if (scsi_command_size(cmd->cmnd) > cmd->device->host->max_cmd_len) {
> 

Because we can't. If ULD gave us length then we only use that, and we do
not assume we know anything about the command. scsi_command_size() only
knows about scsi commands and not all scsi commands at that, not all 
versions and dialects of scsi. The commit log of this patch sayes:
"support for variable-length, extended, and vendor specific"
This code here enables that.

> 
>>  		scsi_done(cmd);
>> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
>> index 325270b..e621505 100644
>> --- a/drivers/scsi/scsi_lib.c
>> +++ b/drivers/scsi/scsi_lib.c
>> @@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
>>  
>>  	req->cmd_len = COMMAND_SIZE(cmd[0]);
>>  	memcpy(req->cmd, cmd, req->cmd_len);
>> +
> 
> Please don't put a new line at a place unrelated with this patch.
> 
Ooops left over from the rebasing sorry.
> 
>>  	req->sense = sense;
>>  	req->sense_len = 0;
>>  	req->retries = retries;
>> @@ -445,7 +446,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
>>  	scsi_set_resid(cmd, 0);
>>  	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
>>  	if (cmd->cmd_len == 0)
>> -		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
>> +		cmd->cmd_len = scsi_command_size(cmd->cmnd);
>>  }
>>  
>>  void scsi_device_unbusy(struct scsi_device *sdev)
>> @@ -1130,13 +1131,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
>>  	}
>>  
>>  	cmd->cmd_len = req->cmd_len;
>> +	if (!cmd->cmd_len)
>> +		cmd->cmd_len = scsi_command_size(cmd->cmnd);
>> +
> 
> how can cmd->cmd_len be zero here? SG_IO path sets up req->cmd_len
> properly for PC commands.
> 

It is either that or BUG_ON(), I would say that a simple thing like that
I would let the Initiator get lazy if it wants to.

> 
>>  	if (!req->data_len)
>>  		cmd->sc_data_direction = DMA_NONE;
>>  	else if (rq_data_dir(req) == WRITE)
>>  		cmd->sc_data_direction = DMA_TO_DEVICE;
>>  	else
>>  		cmd->sc_data_direction = DMA_FROM_DEVICE;
>> -	
>> +
>>  	cmd->transfersize = req->data_len;
>>  	cmd->allowed = req->retries;
>>  	cmd->timeout_per_command = req->timeout;
>> diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
>> index 1f74bcd..32742c4 100644
>> --- a/include/scsi/scsi.h
>> +++ b/include/scsi/scsi.h
>> @@ -30,13 +30,6 @@
>>  #endif
>>  
>>  /*
>> - *	SCSI command lengths
>> - */
>> -
>> -extern const unsigned char scsi_command_size[8];
>> -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
>> -
>> -/*
>>   * Special value for scanning to specify scanning or rescanning of all
>>   * possible channels, (target) ids, or luns on a given shost.
>>   */
>> @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
>>  #define MODE_SENSE_10         0x5a
>>  #define PERSISTENT_RESERVE_IN 0x5e
>>  #define PERSISTENT_RESERVE_OUT 0x5f
>> +#define VARIABLE_LENGTH_CMD   0x7f
>>  #define REPORT_LUNS           0xa0
>>  #define MAINTENANCE_IN        0xa3
>>  #define MOVE_MEDIUM           0xa5
>> @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8];
>>  #define	ATA_12		      0xa1	/* 12-byte pass-thru */
>>  
>>  /*
>> + *	SCSI command lengths
>> + */
>> +
>> +#define SCSI_MAX_VARLEN_CDB_SIZE 260
>> +
>> +/* defined in T10 SCSI Primary Commands-2 (SPC2) */
>> +struct scsi_varlen_cdb_hdr {
>> +	u8 opcode;        /* opcode always == VARIABLE_LENGTH_CMD */
>> +	u8 control;
>> +	u8 misc[5];
>> +	u8 additional_cdb_length;         /* total cdb length - 8 */
>> +	__be16 service_action;
>> +	/* service specific data follows */
>> +};
>> +
>> +static inline unsigned
>> +scsi_varlen_cdb_length(const void *hdr)
>> +{
>> +	return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8;
>> +}
>> +
>> +extern const unsigned char scsi_command_size_tbl[8];
>> +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
>> +
>> +static inline unsigned
>> +scsi_command_size(const unsigned char *cmnd)
>> +{
>> +	return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
>> +		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
>> +}
>> +
>> +/*
>>   *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
>>   *  T10/1561-D Revision 4 Draft dated 7th November 2002.
>>   */
>> diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
>> index dea73e5..f4dacb1 100644
>> --- a/include/scsi/scsi_cmnd.h
>> +++ b/include/scsi/scsi_cmnd.h
>> @@ -78,7 +78,7 @@ struct scsi_cmnd {
>>  	int allowed;
>>  	int timeout_per_command;
>>  
>> -	unsigned char cmd_len;
>> +	unsigned short cmd_len;
>>  	enum dma_data_direction sc_data_direction;
>>  
>>  	/* These elements define the operation we are about to perform */
>> diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
>> index 4913286..31f1bfd 100644
>> --- a/include/scsi/scsi_host.h
>> +++ b/include/scsi/scsi_host.h
>> @@ -573,13 +573,11 @@ struct Scsi_Host {
>>  	/*
>>  	 * The maximum length of SCSI commands that this host can accept.
>>  	 * Probably 12 for most host adapters, but could be 16 for others.
>> +	 * or 260 if the driver supports variable length cdbs.
>>  	 * For drivers that don't set this field, a value of 12 is
>> -	 * assumed.  I am leaving this as a number rather than a bit
>> -	 * because you never know what subsequent SCSI standards might do
>> -	 * (i.e. could there be a 20 byte or a 24-byte command a few years
>> -	 * down the road?).  
>> +	 * assumed.
>>  	 */
>> -	unsigned char max_cmd_len;
>> +	unsigned short max_cmd_len;
>>  
>>  	int this_id;
>>  	int can_queue;
>> -- 
>> 1.5.3.3
>>
>>
>> --

As a reply to this mail I'll send a patch without the extra space.

Boaz


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [PATCH 2/3 ver2] scsi: varlen extended and vendor-specific cdbs
  2008-04-16  6:40                         ` Boaz Harrosh
@ 2008-04-16  6:49                           ` Boaz Harrosh
  2008-04-17  4:01                           ` [PATCH 2/3] " FUJITA Tomonori
  1 sibling, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-16  6:49 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: James.Bottomley, linux-scsi, jens.axboe, bzolnier, agk,
	Geert.Uytterhoeven


  Add support for variable-length, extended, and vendor specific
  CDBs to scsi-ml. It is now possible for initiators and ULD's
  to issue these types of commands. LLDs need not change much.
  All they need is to raise the .max_cmd_len to the longest command
  they support (see iscsi patch).

  - clean-up some code paths that did not expect commands to be
    larger than 16, and change cmd_len members' type to short as
    char is not enough.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
 block/scsi_ioctl.c       |    5 ++---
 drivers/scsi/constants.c |   10 +++-------
 drivers/scsi/scsi.c      |   22 +++++++++++-----------
 drivers/scsi/scsi_lib.c  |    8 ++++++--
 include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
 include/scsi/scsi_cmnd.h |    2 +-
 include/scsi/scsi_host.h |    8 +++-----
 7 files changed, 59 insertions(+), 36 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index a2c3a93..aaf07e4 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -33,13 +33,12 @@
 #include <scsi/scsi_cmnd.h>
 
 /* Command group 3 is reserved and should never be used.  */
-const unsigned char scsi_command_size[8] =
+const unsigned char scsi_command_size_tbl[8] =
 {
 	6, 10, 10, 12,
 	16, 12, 10, 10
 };
-
-EXPORT_SYMBOL(scsi_command_size);
+EXPORT_SYMBOL(scsi_command_size_tbl);
 
 #include <scsi/sg.h>
 
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 403a7f2..9785d73 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -28,7 +28,6 @@
 #define SERVICE_ACTION_OUT_12 0xa9
 #define SERVICE_ACTION_IN_16 0x9e
 #define SERVICE_ACTION_OUT_16 0x9f
-#define VARIABLE_LENGTH_CMD 0x7f
 
 
 
@@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short variable length command, "
 			       "len=%d ext_len=%d", len, cdb_len);
@@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short opcode=0x%x command, len=%d "
 			       "ext_len=%d", cdb0, len, cdb_len);
@@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
 	int k, len;
 
 	print_opcode_name(cdb, 0);
-	if (VARIABLE_LENGTH_CMD == cdb[0])
-		len = cdb[7] + 8;
-	else
-		len = COMMAND_SIZE(cdb[0]);
+	len = scsi_command_size(cdb);
 	/* print out all bytes in cdb */
 	for (k = 0; k < len; ++k) 
 		printk(" %02x", cdb[k]);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index f6980bd..3dabecb 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
 #define MIN_RESET_PERIOD (15*HZ)
 
 /*
- * Macro to determine the size of SCSI command. This macro takes vendor
- * unique commands into account. SCSI commands in groups 6 and 7 are
- * vendor unique and we will depend upon the command length being
- * supplied correctly in cmd_len.
- */
-#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
-				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 	unsigned long flags = 0;
 	unsigned long timeout;
 	int rtn = 0;
+	unsigned cmd_len;
 
 	/* check if the device is still usable */
 	if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
@@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 	 * Before we queue this command, check if the command
 	 * length exceeds what the host adapter can handle.
 	 */
-	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
+	cmd_len = cmd->cmd_len;
+	if (!cmd_len) {
+		BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD);
+		cmd_len = COMMAND_SIZE((cmd)->cmnd[0]);
+	}
+
+	if (cmd_len > cmd->device->host->max_cmd_len) {
 		SCSI_LOG_MLQUEUE(3,
-				printk("queuecommand : command too long.\n"));
+			printk("queuecommand : command too long. "
+			       "cdb_size=%d host->max_cmd_len=%d\n",
+			       cmd->cmd_len, cmd->device->host->max_cmd_len));
 		cmd->result = (DID_ABORT << 16);
 
 		scsi_done(cmd);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 325270b..e621505 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -445,7 +445,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 	scsi_set_resid(cmd, 0);
 	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 	if (cmd->cmd_len == 0)
-		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+		cmd->cmd_len = scsi_command_size(cmd->cmnd);
 }
 
 void scsi_device_unbusy(struct scsi_device *sdev)
@@ -1130,13 +1130,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 	}
 
 	cmd->cmd_len = req->cmd_len;
+	if (!cmd->cmd_len)
+		cmd->cmd_len = scsi_command_size(cmd->cmnd);
+
 	if (!req->data_len)
 		cmd->sc_data_direction = DMA_NONE;
 	else if (rq_data_dir(req) == WRITE)
 		cmd->sc_data_direction = DMA_TO_DEVICE;
 	else
 		cmd->sc_data_direction = DMA_FROM_DEVICE;
-	
+
 	cmd->transfersize = req->data_len;
 	cmd->allowed = req->retries;
 	cmd->timeout_per_command = req->timeout;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 1f74bcd..32742c4 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -30,13 +30,6 @@
 #endif
 
 /*
- *	SCSI command lengths
- */
-
-extern const unsigned char scsi_command_size[8];
-#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
-
-/*
  * Special value for scanning to specify scanning or rescanning of all
  * possible channels, (target) ids, or luns on a given shost.
  */
@@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
 #define MODE_SENSE_10         0x5a
 #define PERSISTENT_RESERVE_IN 0x5e
 #define PERSISTENT_RESERVE_OUT 0x5f
+#define VARIABLE_LENGTH_CMD   0x7f
 #define REPORT_LUNS           0xa0
 #define MAINTENANCE_IN        0xa3
 #define MOVE_MEDIUM           0xa5
@@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8];
 #define	ATA_12		      0xa1	/* 12-byte pass-thru */
 
 /*
+ *	SCSI command lengths
+ */
+
+#define SCSI_MAX_VARLEN_CDB_SIZE 260
+
+/* defined in T10 SCSI Primary Commands-2 (SPC2) */
+struct scsi_varlen_cdb_hdr {
+	u8 opcode;        /* opcode always == VARIABLE_LENGTH_CMD */
+	u8 control;
+	u8 misc[5];
+	u8 additional_cdb_length;         /* total cdb length - 8 */
+	__be16 service_action;
+	/* service specific data follows */
+};
+
+static inline unsigned
+scsi_varlen_cdb_length(const void *hdr)
+{
+	return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8;
+}
+
+extern const unsigned char scsi_command_size_tbl[8];
+#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
+
+static inline unsigned
+scsi_command_size(const unsigned char *cmnd)
+{
+	return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
+		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
+}
+
+/*
  *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
  *  T10/1561-D Revision 4 Draft dated 7th November 2002.
  */
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index dea73e5..f4dacb1 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -78,7 +78,7 @@ struct scsi_cmnd {
 	int allowed;
 	int timeout_per_command;
 
-	unsigned char cmd_len;
+	unsigned short cmd_len;
 	enum dma_data_direction sc_data_direction;
 
 	/* These elements define the operation we are about to perform */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 4913286..31f1bfd 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -573,13 +573,11 @@ struct Scsi_Host {
 	/*
 	 * The maximum length of SCSI commands that this host can accept.
 	 * Probably 12 for most host adapters, but could be 16 for others.
+	 * or 260 if the driver supports variable length cdbs.
 	 * For drivers that don't set this field, a value of 12 is
-	 * assumed.  I am leaving this as a number rather than a bit
-	 * because you never know what subsequent SCSI standards might do
-	 * (i.e. could there be a 20 byte or a 24-byte command a few years
-	 * down the road?).  
+	 * assumed.
 	 */
-	unsigned char max_cmd_len;
+	unsigned short max_cmd_len;
 
 	int this_id;
 	int can_queue;
-- 
1.5.3.3



^ permalink raw reply related	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-15 22:57                               ` FUJITA Tomonori
  2008-04-16  0:22                                 ` Bartlomiej Zolnierkiewicz
@ 2008-04-16  8:33                                 ` Jens Axboe
  2008-04-16  9:08                                   ` Boaz Harrosh
  2008-04-17  4:02                                   ` FUJITA Tomonori
  1 sibling, 2 replies; 77+ messages in thread
From: Jens Axboe @ 2008-04-16  8:33 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: bzolnier, linux-scsi, bharrosh, linux-ide, akpm

On Wed, Apr 16 2008, FUJITA Tomonori wrote:
> On Wed, 16 Apr 2008 00:50:54 +0200
> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
> 
> > 
> > Hi,
> > 
> > On Monday 14 April 2008, Jens Axboe wrote:
> > > On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> > > > This patch changes rq->cmd from the static array to a pointer to
> > > > support large commands.
> > > > 
> > > > We rarely handle large commands. So for optimization, a struct request
> > > > still has a static array for a command. rq_init sets rq->cmd pointer
> > > > to the static array.
> > > > 
> > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > > > Cc: Jens Axboe <jens.axboe@oracle.com>
> > > > ---
> > > >  block/blk-core.c       |    1 +
> > > >  drivers/ide/ide-io.c   |    1 +
> > > >  include/linux/blkdev.h |   12 ++++++++++--
> > > >  3 files changed, 12 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/block/blk-core.c b/block/blk-core.c
> > > > index 6669238..6f0968f 100644
> > > > --- a/block/blk-core.c
> > > > +++ b/block/blk-core.c
> > > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> > > >  	rq->errors = 0;
> > > >  	rq->ref_count = 1;
> > > >  	rq->cmd_len = 0;
> > > > +	rq->cmd = rq->__cmd;
> > > >  	memset(rq->cmd, 0, BLK_MAX_CDB);
> > > >  	rq->data_len = 0;
> > > >  	rq->extra_len = 0;
> > > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> > > > index 7153796..bac5ea1 100644
> > > > --- a/drivers/ide/ide-io.c
> > > > +++ b/drivers/ide/ide-io.c
> > > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> > > >  {
> > > >  	memset(rq, 0, sizeof(*rq));
> > > >  	rq->ref_count = 1;
> > > > +	rq->cmd = rq->__cmd;
> > > >  }
> > 
> > Tomo, some more changes are needed:
> > 
> > Please think about all _static_/dynamic allocations of 'struct request'
> > used together with REQ_TYPE_SPECIAL etc., i.e.
> 
> I think that using struct request allocated statically is wrong from
> the perspective of the block layer design, that is, you always need to
> use blk_get_request. I think that except ide, everyone does.
> 
> I try to convert ide to use blk_get_request properly if you want.

That would be best, but the on-stack allocation has the benefit that
it'll always work. So until we can completely get rid of that, lets just
make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
lot saner than doing a memset() anyway.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-16  8:33                                 ` Jens Axboe
@ 2008-04-16  9:08                                   ` Boaz Harrosh
  2008-04-16  9:42                                     ` Jens Axboe
  2008-04-17  3:59                                     ` FUJITA Tomonori
  2008-04-17  4:02                                   ` FUJITA Tomonori
  1 sibling, 2 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-16  9:08 UTC (permalink / raw)
  To: Jens Axboe; +Cc: FUJITA Tomonori, bzolnier, linux-scsi, linux-ide, akpm

On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> On Wed, Apr 16 2008, FUJITA Tomonori wrote:
>> On Wed, 16 Apr 2008 00:50:54 +0200
>> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
>>
>>> Hi,
>>>
>>> On Monday 14 April 2008, Jens Axboe wrote:
>>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
>>>>> This patch changes rq->cmd from the static array to a pointer to
>>>>> support large commands.
>>>>>
>>>>> We rarely handle large commands. So for optimization, a struct request
>>>>> still has a static array for a command. rq_init sets rq->cmd pointer
>>>>> to the static array.
>>>>>
>>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
>>>>> Cc: Jens Axboe <jens.axboe@oracle.com>
>>>>> ---
>>>>>  block/blk-core.c       |    1 +
>>>>>  drivers/ide/ide-io.c   |    1 +
>>>>>  include/linux/blkdev.h |   12 ++++++++++--
>>>>>  3 files changed, 12 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/block/blk-core.c b/block/blk-core.c
>>>>> index 6669238..6f0968f 100644
>>>>> --- a/block/blk-core.c
>>>>> +++ b/block/blk-core.c
>>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
>>>>>  	rq->errors = 0;
>>>>>  	rq->ref_count = 1;
>>>>>  	rq->cmd_len = 0;
>>>>> +	rq->cmd = rq->__cmd;
>>>>>  	memset(rq->cmd, 0, BLK_MAX_CDB);
>>>>>  	rq->data_len = 0;
>>>>>  	rq->extra_len = 0;
>>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
>>>>> index 7153796..bac5ea1 100644
>>>>> --- a/drivers/ide/ide-io.c
>>>>> +++ b/drivers/ide/ide-io.c
>>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
>>>>>  {
>>>>>  	memset(rq, 0, sizeof(*rq));
>>>>>  	rq->ref_count = 1;
>>>>> +	rq->cmd = rq->__cmd;
>>>>>  }
>>> Tomo, some more changes are needed:
>>>
>>> Please think about all _static_/dynamic allocations of 'struct request'
>>> used together with REQ_TYPE_SPECIAL etc., i.e.
>> I think that using struct request allocated statically is wrong from
>> the perspective of the block layer design, that is, you always need to
>> use blk_get_request. I think that except ide, everyone does.
>>
>> I try to convert ide to use blk_get_request properly if you want.
> 
> That would be best, but the on-stack allocation has the benefit that
> it'll always work. So until we can completely get rid of that, lets just
> make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
> lot saner than doing a memset() anyway.
> 

Just a patch that I had for ages since the bad old request bidi times,
perhaps is also good today. (rebased to for-2.6.26 branch)
---
From: Boaz Harrosh <bharrosh@panasas.com>
Date: Wed, 16 Apr 2008 12:05:33 +0300
Subject: [PATCH] Initialize all members of struct request in rq_init

Before, every member added/removed from struct request would entitle a change
to rq_init, for initialization. Now all members are default to zero and only
the none zero members are specifically initialized.

Users that need requests on the stack or pre-allocated, must call rq_init()
before use.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 block/blk-core.c |   22 ++--------------------
 1 files changed, 2 insertions(+), 20 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 6f0968f..3f4c563 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info);
  */
 void rq_init(struct request_queue *q, struct request *rq)
 {
+	memset(rq, 0, sizeof(*rq));
 	INIT_LIST_HEAD(&rq->queuelist);
 	INIT_LIST_HEAD(&rq->donelist);
 	rq->q = q;
 	rq->sector = rq->hard_sector = (sector_t) -1;
-	rq->nr_sectors = rq->hard_nr_sectors = 0;
-	rq->current_nr_sectors = rq->hard_cur_sectors = 0;
-	rq->bio = rq->biotail = NULL;
 	INIT_HLIST_NODE(&rq->hash);
 	RB_CLEAR_NODE(&rq->rb_node);
-	rq->rq_disk = NULL;
-	rq->nr_phys_segments = 0;
-	rq->nr_hw_segments = 0;
-	rq->ioprio = 0;
-	rq->special = NULL;
-	rq->buffer = NULL;
 	rq->tag = -1;
-	rq->errors = 0;
 	rq->ref_count = 1;
-	rq->cmd_len = 0;
 	rq->cmd = rq->__cmd;
-	memset(rq->cmd, 0, BLK_MAX_CDB);
-	rq->data_len = 0;
-	rq->extra_len = 0;
-	rq->sense_len = 0;
-	rq->data = NULL;
-	rq->sense = NULL;
-	rq->end_io = NULL;
-	rq->end_io_data = NULL;
-	rq->next_rq = NULL;
 }
+EXPORT_SYMBOL(rq_init);
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
 			  unsigned int nbytes, int error)
-- 
1.5.3.3


^ permalink raw reply related	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-16  9:08                                   ` Boaz Harrosh
@ 2008-04-16  9:42                                     ` Jens Axboe
  2008-04-16 22:28                                       ` Bartlomiej Zolnierkiewicz
  2008-04-17  3:59                                     ` FUJITA Tomonori
  1 sibling, 1 reply; 77+ messages in thread
From: Jens Axboe @ 2008-04-16  9:42 UTC (permalink / raw)
  To: Boaz Harrosh; +Cc: FUJITA Tomonori, bzolnier, linux-scsi, linux-ide, akpm

On Wed, Apr 16 2008, Boaz Harrosh wrote:
> On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> > On Wed, Apr 16 2008, FUJITA Tomonori wrote:
> >> On Wed, 16 Apr 2008 00:50:54 +0200
> >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
> >>
> >>> Hi,
> >>>
> >>> On Monday 14 April 2008, Jens Axboe wrote:
> >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> >>>>> This patch changes rq->cmd from the static array to a pointer to
> >>>>> support large commands.
> >>>>>
> >>>>> We rarely handle large commands. So for optimization, a struct request
> >>>>> still has a static array for a command. rq_init sets rq->cmd pointer
> >>>>> to the static array.
> >>>>>
> >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> >>>>> Cc: Jens Axboe <jens.axboe@oracle.com>
> >>>>> ---
> >>>>>  block/blk-core.c       |    1 +
> >>>>>  drivers/ide/ide-io.c   |    1 +
> >>>>>  include/linux/blkdev.h |   12 ++++++++++--
> >>>>>  3 files changed, 12 insertions(+), 2 deletions(-)
> >>>>>
> >>>>> diff --git a/block/blk-core.c b/block/blk-core.c
> >>>>> index 6669238..6f0968f 100644
> >>>>> --- a/block/blk-core.c
> >>>>> +++ b/block/blk-core.c
> >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> >>>>>  	rq->errors = 0;
> >>>>>  	rq->ref_count = 1;
> >>>>>  	rq->cmd_len = 0;
> >>>>> +	rq->cmd = rq->__cmd;
> >>>>>  	memset(rq->cmd, 0, BLK_MAX_CDB);
> >>>>>  	rq->data_len = 0;
> >>>>>  	rq->extra_len = 0;
> >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> >>>>> index 7153796..bac5ea1 100644
> >>>>> --- a/drivers/ide/ide-io.c
> >>>>> +++ b/drivers/ide/ide-io.c
> >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> >>>>>  {
> >>>>>  	memset(rq, 0, sizeof(*rq));
> >>>>>  	rq->ref_count = 1;
> >>>>> +	rq->cmd = rq->__cmd;
> >>>>>  }
> >>> Tomo, some more changes are needed:
> >>>
> >>> Please think about all _static_/dynamic allocations of 'struct request'
> >>> used together with REQ_TYPE_SPECIAL etc., i.e.
> >> I think that using struct request allocated statically is wrong from
> >> the perspective of the block layer design, that is, you always need to
> >> use blk_get_request. I think that except ide, everyone does.
> >>
> >> I try to convert ide to use blk_get_request properly if you want.
> > 
> > That would be best, but the on-stack allocation has the benefit that
> > it'll always work. So until we can completely get rid of that, lets just
> > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
> > lot saner than doing a memset() anyway.
> > 
> 
> Just a patch that I had for ages since the bad old request bidi times,
> perhaps is also good today. (rebased to for-2.6.26 branch)
> ---
> From: Boaz Harrosh <bharrosh@panasas.com>
> Date: Wed, 16 Apr 2008 12:05:33 +0300
> Subject: [PATCH] Initialize all members of struct request in rq_init
> 
> Before, every member added/removed from struct request would entitle a change
> to rq_init, for initialization. Now all members are default to zero and only
> the none zero members are specifically initialized.
> 
> Users that need requests on the stack or pre-allocated, must call rq_init()
> before use.
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> ---
>  block/blk-core.c |   22 ++--------------------
>  1 files changed, 2 insertions(+), 20 deletions(-)
> 
> diff --git a/block/blk-core.c b/block/blk-core.c
> index 6f0968f..3f4c563 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info);
>   */
>  void rq_init(struct request_queue *q, struct request *rq)
>  {
> +	memset(rq, 0, sizeof(*rq));
>  	INIT_LIST_HEAD(&rq->queuelist);
>  	INIT_LIST_HEAD(&rq->donelist);
>  	rq->q = q;
>  	rq->sector = rq->hard_sector = (sector_t) -1;
> -	rq->nr_sectors = rq->hard_nr_sectors = 0;
> -	rq->current_nr_sectors = rq->hard_cur_sectors = 0;
> -	rq->bio = rq->biotail = NULL;
>  	INIT_HLIST_NODE(&rq->hash);
>  	RB_CLEAR_NODE(&rq->rb_node);
> -	rq->rq_disk = NULL;
> -	rq->nr_phys_segments = 0;
> -	rq->nr_hw_segments = 0;
> -	rq->ioprio = 0;
> -	rq->special = NULL;
> -	rq->buffer = NULL;
>  	rq->tag = -1;
> -	rq->errors = 0;
>  	rq->ref_count = 1;
> -	rq->cmd_len = 0;
>  	rq->cmd = rq->__cmd;
> -	memset(rq->cmd, 0, BLK_MAX_CDB);
> -	rq->data_len = 0;
> -	rq->extra_len = 0;
> -	rq->sense_len = 0;
> -	rq->data = NULL;
> -	rq->sense = NULL;
> -	rq->end_io = NULL;
> -	rq->end_io_data = NULL;
> -	rq->next_rq = NULL;
>  }
> +EXPORT_SYMBOL(rq_init);
>  
>  static void req_bio_endio(struct request *rq, struct bio *bio,
>  			  unsigned int nbytes, int error)
> -- 
> 1.5.3.3
> 

Totally agree, if we expand rq_init() to all users (including on stack),
this must be included as well.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-16  9:42                                     ` Jens Axboe
@ 2008-04-16 22:28                                       ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 77+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-04-16 22:28 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Boaz Harrosh, FUJITA Tomonori, linux-scsi, linux-ide, akpm

On Wednesday 16 April 2008, Jens Axboe wrote:
> On Wed, Apr 16 2008, Boaz Harrosh wrote:
> > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> > > On Wed, Apr 16 2008, FUJITA Tomonori wrote:
> > >> On Wed, 16 Apr 2008 00:50:54 +0200
> > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
> > >>
> > >>> Hi,
> > >>>
> > >>> On Monday 14 April 2008, Jens Axboe wrote:
> > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> > >>>>> This patch changes rq->cmd from the static array to a pointer to
> > >>>>> support large commands.
> > >>>>>
> > >>>>> We rarely handle large commands. So for optimization, a struct request
> > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer
> > >>>>> to the static array.
> > >>>>>
> > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com>
> > >>>>> ---
> > >>>>>  block/blk-core.c       |    1 +
> > >>>>>  drivers/ide/ide-io.c   |    1 +
> > >>>>>  include/linux/blkdev.h |   12 ++++++++++--
> > >>>>>  3 files changed, 12 insertions(+), 2 deletions(-)
> > >>>>>
> > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c
> > >>>>> index 6669238..6f0968f 100644
> > >>>>> --- a/block/blk-core.c
> > >>>>> +++ b/block/blk-core.c
> > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> > >>>>>  	rq->errors = 0;
> > >>>>>  	rq->ref_count = 1;
> > >>>>>  	rq->cmd_len = 0;
> > >>>>> +	rq->cmd = rq->__cmd;
> > >>>>>  	memset(rq->cmd, 0, BLK_MAX_CDB);
> > >>>>>  	rq->data_len = 0;
> > >>>>>  	rq->extra_len = 0;
> > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> > >>>>> index 7153796..bac5ea1 100644
> > >>>>> --- a/drivers/ide/ide-io.c
> > >>>>> +++ b/drivers/ide/ide-io.c
> > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> > >>>>>  {
> > >>>>>  	memset(rq, 0, sizeof(*rq));
> > >>>>>  	rq->ref_count = 1;
> > >>>>> +	rq->cmd = rq->__cmd;
> > >>>>>  }
> > >>> Tomo, some more changes are needed:
> > >>>
> > >>> Please think about all _static_/dynamic allocations of 'struct request'
> > >>> used together with REQ_TYPE_SPECIAL etc., i.e.
> > >> I think that using struct request allocated statically is wrong from
> > >> the perspective of the block layer design, that is, you always need to
> > >> use blk_get_request. I think that except ide, everyone does.
> > >>
> > >> I try to convert ide to use blk_get_request properly if you want.
> > > 
> > > That would be best, but the on-stack allocation has the benefit that
> > > it'll always work. So until we can completely get rid of that, lets just
> > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
> > > lot saner than doing a memset() anyway.

Sounds OK to me.

> > Just a patch that I had for ages since the bad old request bidi times,
> > perhaps is also good today. (rebased to for-2.6.26 branch)
> > ---
> > From: Boaz Harrosh <bharrosh@panasas.com>
> > Date: Wed, 16 Apr 2008 12:05:33 +0300
> > Subject: [PATCH] Initialize all members of struct request in rq_init
> > 
> > Before, every member added/removed from struct request would entitle a change
> > to rq_init, for initialization. Now all members are default to zero and only
> > the none zero members are specifically initialized.
> > 
> > Users that need requests on the stack or pre-allocated, must call rq_init()
> > before use.
> > 
> > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> > ---
> >  block/blk-core.c |   22 ++--------------------
> >  1 files changed, 2 insertions(+), 20 deletions(-)
> > 
> > diff --git a/block/blk-core.c b/block/blk-core.c
> > index 6f0968f..3f4c563 100644
> > --- a/block/blk-core.c
> > +++ b/block/blk-core.c
> > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info);
> >   */
> >  void rq_init(struct request_queue *q, struct request *rq)
> >  {
> > +	memset(rq, 0, sizeof(*rq));
> >  	INIT_LIST_HEAD(&rq->queuelist);
> >  	INIT_LIST_HEAD(&rq->donelist);
> >  	rq->q = q;
> >  	rq->sector = rq->hard_sector = (sector_t) -1;
> > -	rq->nr_sectors = rq->hard_nr_sectors = 0;
> > -	rq->current_nr_sectors = rq->hard_cur_sectors = 0;
> > -	rq->bio = rq->biotail = NULL;
> >  	INIT_HLIST_NODE(&rq->hash);
> >  	RB_CLEAR_NODE(&rq->rb_node);
> > -	rq->rq_disk = NULL;
> > -	rq->nr_phys_segments = 0;
> > -	rq->nr_hw_segments = 0;
> > -	rq->ioprio = 0;
> > -	rq->special = NULL;
> > -	rq->buffer = NULL;
> >  	rq->tag = -1;
> > -	rq->errors = 0;
> >  	rq->ref_count = 1;
> > -	rq->cmd_len = 0;
> >  	rq->cmd = rq->__cmd;
> > -	memset(rq->cmd, 0, BLK_MAX_CDB);
> > -	rq->data_len = 0;
> > -	rq->extra_len = 0;
> > -	rq->sense_len = 0;
> > -	rq->data = NULL;
> > -	rq->sense = NULL;
> > -	rq->end_io = NULL;
> > -	rq->end_io_data = NULL;
> > -	rq->next_rq = NULL;
> >  }
> > +EXPORT_SYMBOL(rq_init);
> >  
> >  static void req_bio_endio(struct request *rq, struct bio *bio,
> >  			  unsigned int nbytes, int error)
> > -- 
> > 1.5.3.3
> > 
> 
> Totally agree, if we expand rq_init() to all users (including on stack),
> this must be included as well.

Completely, totally and fully agreed...

Thanks,
Bart

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-16  9:08                                   ` Boaz Harrosh
  2008-04-16  9:42                                     ` Jens Axboe
@ 2008-04-17  3:59                                     ` FUJITA Tomonori
  2008-04-17  7:07                                       ` Jens Axboe
  1 sibling, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-17  3:59 UTC (permalink / raw)
  To: bharrosh; +Cc: jens.axboe, fujita.tomonori, bzolnier, linux-scsi, linux-ide,
	akpm

On Wed, 16 Apr 2008 12:08:25 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> > On Wed, Apr 16 2008, FUJITA Tomonori wrote:
> >> On Wed, 16 Apr 2008 00:50:54 +0200
> >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
> >>
> >>> Hi,
> >>>
> >>> On Monday 14 April 2008, Jens Axboe wrote:
> >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> >>>>> This patch changes rq->cmd from the static array to a pointer to
> >>>>> support large commands.
> >>>>>
> >>>>> We rarely handle large commands. So for optimization, a struct request
> >>>>> still has a static array for a command. rq_init sets rq->cmd pointer
> >>>>> to the static array.
> >>>>>
> >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> >>>>> Cc: Jens Axboe <jens.axboe@oracle.com>
> >>>>> ---
> >>>>>  block/blk-core.c       |    1 +
> >>>>>  drivers/ide/ide-io.c   |    1 +
> >>>>>  include/linux/blkdev.h |   12 ++++++++++--
> >>>>>  3 files changed, 12 insertions(+), 2 deletions(-)
> >>>>>
> >>>>> diff --git a/block/blk-core.c b/block/blk-core.c
> >>>>> index 6669238..6f0968f 100644
> >>>>> --- a/block/blk-core.c
> >>>>> +++ b/block/blk-core.c
> >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> >>>>>  	rq->errors = 0;
> >>>>>  	rq->ref_count = 1;
> >>>>>  	rq->cmd_len = 0;
> >>>>> +	rq->cmd = rq->__cmd;
> >>>>>  	memset(rq->cmd, 0, BLK_MAX_CDB);
> >>>>>  	rq->data_len = 0;
> >>>>>  	rq->extra_len = 0;
> >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> >>>>> index 7153796..bac5ea1 100644
> >>>>> --- a/drivers/ide/ide-io.c
> >>>>> +++ b/drivers/ide/ide-io.c
> >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> >>>>>  {
> >>>>>  	memset(rq, 0, sizeof(*rq));
> >>>>>  	rq->ref_count = 1;
> >>>>> +	rq->cmd = rq->__cmd;
> >>>>>  }
> >>> Tomo, some more changes are needed:
> >>>
> >>> Please think about all _static_/dynamic allocations of 'struct request'
> >>> used together with REQ_TYPE_SPECIAL etc., i.e.
> >> I think that using struct request allocated statically is wrong from
> >> the perspective of the block layer design, that is, you always need to
> >> use blk_get_request. I think that except ide, everyone does.
> >>
> >> I try to convert ide to use blk_get_request properly if you want.
> > 
> > That would be best, but the on-stack allocation has the benefit that
> > it'll always work. So until we can completely get rid of that, lets just
> > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
> > lot saner than doing a memset() anyway.
> > 
> 
> Just a patch that I had for ages since the bad old request bidi times,
> perhaps is also good today. (rebased to for-2.6.26 branch)
> ---
> From: Boaz Harrosh <bharrosh@panasas.com>
> Date: Wed, 16 Apr 2008 12:05:33 +0300
> Subject: [PATCH] Initialize all members of struct request in rq_init
> 
> Before, every member added/removed from struct request would entitle a change
> to rq_init, for initialization. Now all members are default to zero and only
> the none zero members are specifically initialized.
> 
> Users that need requests on the stack or pre-allocated, must call rq_init()
> before use.
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> ---
>  block/blk-core.c |   22 ++--------------------
>  1 files changed, 2 insertions(+), 20 deletions(-)
> 
> diff --git a/block/blk-core.c b/block/blk-core.c
> index 6f0968f..3f4c563 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info);
>   */
>  void rq_init(struct request_queue *q, struct request *rq)
>  {
> +	memset(rq, 0, sizeof(*rq));

Hmm, rq_init comment says:

/*
 * We can't just memset() the structure, since the allocation path
 * already stored some information in the request.
 */

I think that we can't initialize rq->cmd_flags here.



>  	INIT_LIST_HEAD(&rq->queuelist);
>  	INIT_LIST_HEAD(&rq->donelist);
>  	rq->q = q;
>  	rq->sector = rq->hard_sector = (sector_t) -1;
> -	rq->nr_sectors = rq->hard_nr_sectors = 0;
> -	rq->current_nr_sectors = rq->hard_cur_sectors = 0;
> -	rq->bio = rq->biotail = NULL;
>  	INIT_HLIST_NODE(&rq->hash);
>  	RB_CLEAR_NODE(&rq->rb_node);
> -	rq->rq_disk = NULL;
> -	rq->nr_phys_segments = 0;
> -	rq->nr_hw_segments = 0;
> -	rq->ioprio = 0;
> -	rq->special = NULL;
> -	rq->buffer = NULL;
>  	rq->tag = -1;
> -	rq->errors = 0;
>  	rq->ref_count = 1;
> -	rq->cmd_len = 0;
>  	rq->cmd = rq->__cmd;
> -	memset(rq->cmd, 0, BLK_MAX_CDB);
> -	rq->data_len = 0;
> -	rq->extra_len = 0;
> -	rq->sense_len = 0;
> -	rq->data = NULL;
> -	rq->sense = NULL;
> -	rq->end_io = NULL;
> -	rq->end_io_data = NULL;
> -	rq->next_rq = NULL;
>  }
> +EXPORT_SYMBOL(rq_init);
>  
>  static void req_bio_endio(struct request *rq, struct bio *bio,
>  			  unsigned int nbytes, int error)
> -- 
> 1.5.3.3
> 
> --
> 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

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs
  2008-04-16  6:40                         ` Boaz Harrosh
  2008-04-16  6:49                           ` [PATCH 2/3 ver2] " Boaz Harrosh
@ 2008-04-17  4:01                           ` FUJITA Tomonori
  2008-04-17 12:25                             ` [PATCH 2/3 ver3] " Boaz Harrosh
  1 sibling, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-17  4:01 UTC (permalink / raw)
  To: bharrosh
  Cc: fujita.tomonori, James.Bottomley, linux-scsi, jens.axboe,
	bzolnier, agk, Geert.Uytterhoeven

On Wed, 16 Apr 2008 09:40:17 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On Wed, Apr 16 2008 at 5:09 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> > On Tue, 15 Apr 2008 15:34:47 +0300
> > Boaz Harrosh <bharrosh@panasas.com> wrote:
> > 
> >> Add support for variable-length, extended, and vendor specific
> >> CDBs to scsi-ml. It is now possible for initiators and ULD's
> >> to issue these types of commands. LLDs need not change much.
> >> All they need is to raise the .max_cmd_len to the longest command
> >> they support (see iscsi patch).
> >>
> >> - clean-up some code paths that did not expect commands to be
> >>   larger than 16, and change cmd_len members' type to short as
> >>   char is not enough.
> >>
> >> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> >> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> >> ---
> >>  block/scsi_ioctl.c       |    5 ++---
> >>  drivers/scsi/constants.c |   10 +++-------
> >>  drivers/scsi/scsi.c      |   22 +++++++++++-----------
> >>  drivers/scsi/scsi_lib.c  |    8 ++++++--
> >>  include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
> >>  include/scsi/scsi_cmnd.h |    2 +-
> >>  include/scsi/scsi_host.h |    8 +++-----
> >>  7 files changed, 59 insertions(+), 36 deletions(-)
> >>
> >> diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
> >> index a2c3a93..aaf07e4 100644
> >> --- a/block/scsi_ioctl.c
> >> +++ b/block/scsi_ioctl.c
> >> @@ -33,13 +33,12 @@
> >>  #include <scsi/scsi_cmnd.h>
> >>  
> >>  /* Command group 3 is reserved and should never be used.  */
> >> -const unsigned char scsi_command_size[8] =
> >> +const unsigned char scsi_command_size_tbl[8] =
> >>  {
> >>  	6, 10, 10, 12,
> >>  	16, 12, 10, 10
> >>  };
> >> -
> >> -EXPORT_SYMBOL(scsi_command_size);
> >> +EXPORT_SYMBOL(scsi_command_size_tbl);
> >>  
> >>  #include <scsi/sg.h>
> >>  
> >> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
> >> index 403a7f2..9785d73 100644
> >> --- a/drivers/scsi/constants.c
> >> +++ b/drivers/scsi/constants.c
> >> @@ -28,7 +28,6 @@
> >>  #define SERVICE_ACTION_OUT_12 0xa9
> >>  #define SERVICE_ACTION_IN_16 0x9e
> >>  #define SERVICE_ACTION_OUT_16 0x9f
> >> -#define VARIABLE_LENGTH_CMD 0x7f
> >>  
> >>  
> >>  
> >> @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
> >>  	cdb0 = cdbp[0];
> >>  	switch(cdb0) {
> >>  	case VARIABLE_LENGTH_CMD:
> >> -		len = cdbp[7] + 8;
> >> +		len = scsi_varlen_cdb_length(cdbp);
> >>  		if (len < 10) {
> >>  			printk("short variable length command, "
> >>  			       "len=%d ext_len=%d", len, cdb_len);
> >> @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
> >>  	cdb0 = cdbp[0];
> >>  	switch(cdb0) {
> >>  	case VARIABLE_LENGTH_CMD:
> >> -		len = cdbp[7] + 8;
> >> +		len = scsi_varlen_cdb_length(cdbp);
> >>  		if (len < 10) {
> >>  			printk("short opcode=0x%x command, len=%d "
> >>  			       "ext_len=%d", cdb0, len, cdb_len);
> >> @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
> >>  	int k, len;
> >>  
> >>  	print_opcode_name(cdb, 0);
> >> -	if (VARIABLE_LENGTH_CMD == cdb[0])
> >> -		len = cdb[7] + 8;
> >> -	else
> >> -		len = COMMAND_SIZE(cdb[0]);
> >> +	len = scsi_command_size(cdb);
> >>  	/* print out all bytes in cdb */
> >>  	for (k = 0; k < len; ++k) 
> >>  		printk(" %02x", cdb[k]);
> >> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
> >> index f6980bd..3dabecb 100644
> >> --- a/drivers/scsi/scsi.c
> >> +++ b/drivers/scsi/scsi.c
> >> @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
> >>  #define MIN_RESET_PERIOD (15*HZ)
> >>  
> >>  /*
> >> - * Macro to determine the size of SCSI command. This macro takes vendor
> >> - * unique commands into account. SCSI commands in groups 6 and 7 are
> >> - * vendor unique and we will depend upon the command length being
> >> - * supplied correctly in cmd_len.
> >> - */
> >> -#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
> >> -				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
> >> -
> >> -/*
> >>   * Note - the initial logging level can be set here to log events at boot time.
> >>   * After the system is up, you may enable logging via the /proc interface.
> >>   */
> >> @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
> >>  	unsigned long flags = 0;
> >>  	unsigned long timeout;
> >>  	int rtn = 0;
> >> +	unsigned cmd_len;
> >>  
> >>  	/* check if the device is still usable */
> >>  	if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
> >> @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
> >>  	 * Before we queue this command, check if the command
> >>  	 * length exceeds what the host adapter can handle.
> >>  	 */
> >> -	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
> >> +	cmd_len = cmd->cmd_len;
> >> +	if (!cmd_len) {
> >> +		BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD);
> >> +		cmd_len = COMMAND_SIZE((cmd)->cmnd[0]);
> >> +	}
> > 
> > Hmm, how can cmd->cmd_len be zero here?
> > 
> 
> With FS_PC commands this is zero here. Because ULD prepare the command
> only after prep_fn.

I don't think so. See what scsi_init_cmd_errh does. It's called before
scsi_dispatch_cmd.


> > 
> >> +	if (cmd_len > cmd->device->host->max_cmd_len) {
> >>  		SCSI_LOG_MLQUEUE(3,
> >> -				printk("queuecommand : command too long.\n"));
> >> +			printk("queuecommand : command too long. "
> >> +			       "cdb_size=%d host->max_cmd_len=%d\n",
> >> +			       cmd->cmd_len, cmd->device->host->max_cmd_len));
> >>  		cmd->result = (DID_ABORT << 16);
> > 
> > Why can't we just do:
> > 
> > if (scsi_command_size(cmd->cmnd) > cmd->device->host->max_cmd_len) {
> > 
> 
> Because we can't. If ULD gave us length then we only use that, and we do
> not assume we know anything about the command. scsi_command_size() only
> knows about scsi commands and not all scsi commands at that, not all 
> versions and dialects of scsi. The commit log of this patch sayes:
> "support for variable-length, extended, and vendor specific"
> This code here enables that.

Again, look at scsi_init_cmd_errh.


> > 
> >>  		scsi_done(cmd);
> >> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> >> index 325270b..e621505 100644
> >> --- a/drivers/scsi/scsi_lib.c
> >> +++ b/drivers/scsi/scsi_lib.c
> >> @@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
> >>  
> >>  	req->cmd_len = COMMAND_SIZE(cmd[0]);
> >>  	memcpy(req->cmd, cmd, req->cmd_len);
> >> +
> > 
> > Please don't put a new line at a place unrelated with this patch.
> > 
> Ooops left over from the rebasing sorry.
> > 
> >>  	req->sense = sense;
> >>  	req->sense_len = 0;
> >>  	req->retries = retries;
> >> @@ -445,7 +446,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
> >>  	scsi_set_resid(cmd, 0);
> >>  	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
> >>  	if (cmd->cmd_len == 0)
> >> -		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
> >> +		cmd->cmd_len = scsi_command_size(cmd->cmnd);
> >>  }
> >>  
> >>  void scsi_device_unbusy(struct scsi_device *sdev)
> >> @@ -1130,13 +1131,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
> >>  	}
> >>  
> >>  	cmd->cmd_len = req->cmd_len;
> >> +	if (!cmd->cmd_len)
> >> +		cmd->cmd_len = scsi_command_size(cmd->cmnd);
> >> +
> > 
> > how can cmd->cmd_len be zero here? SG_IO path sets up req->cmd_len
> > properly for PC commands.
> > 
> 
> It is either that or BUG_ON(), I would say that a simple thing like that
> I would let the Initiator get lazy if it wants to.

Please do only what the patch describes. This patch is expected to add
large command support. The above code is not related with that at all.

I don't think we need the above code. But if you still think we need
the above code, send a separate patch.


> > 
> >>  	if (!req->data_len)
> >>  		cmd->sc_data_direction = DMA_NONE;
> >>  	else if (rq_data_dir(req) == WRITE)
> >>  		cmd->sc_data_direction = DMA_TO_DEVICE;
> >>  	else
> >>  		cmd->sc_data_direction = DMA_FROM_DEVICE;
> >> -	
> >> +
> >>  	cmd->transfersize = req->data_len;
> >>  	cmd->allowed = req->retries;
> >>  	cmd->timeout_per_command = req->timeout;
> >> diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
> >> index 1f74bcd..32742c4 100644
> >> --- a/include/scsi/scsi.h
> >> +++ b/include/scsi/scsi.h
> >> @@ -30,13 +30,6 @@
> >>  #endif
> >>  
> >>  /*
> >> - *	SCSI command lengths
> >> - */
> >> -
> >> -extern const unsigned char scsi_command_size[8];
> >> -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
> >> -
> >> -/*
> >>   * Special value for scanning to specify scanning or rescanning of all
> >>   * possible channels, (target) ids, or luns on a given shost.
> >>   */
> >> @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
> >>  #define MODE_SENSE_10         0x5a
> >>  #define PERSISTENT_RESERVE_IN 0x5e
> >>  #define PERSISTENT_RESERVE_OUT 0x5f
> >> +#define VARIABLE_LENGTH_CMD   0x7f
> >>  #define REPORT_LUNS           0xa0
> >>  #define MAINTENANCE_IN        0xa3
> >>  #define MOVE_MEDIUM           0xa5
> >> @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8];
> >>  #define	ATA_12		      0xa1	/* 12-byte pass-thru */
> >>  
> >>  /*
> >> + *	SCSI command lengths
> >> + */
> >> +
> >> +#define SCSI_MAX_VARLEN_CDB_SIZE 260
> >> +
> >> +/* defined in T10 SCSI Primary Commands-2 (SPC2) */
> >> +struct scsi_varlen_cdb_hdr {
> >> +	u8 opcode;        /* opcode always == VARIABLE_LENGTH_CMD */
> >> +	u8 control;
> >> +	u8 misc[5];
> >> +	u8 additional_cdb_length;         /* total cdb length - 8 */
> >> +	__be16 service_action;
> >> +	/* service specific data follows */
> >> +};
> >> +
> >> +static inline unsigned
> >> +scsi_varlen_cdb_length(const void *hdr)
> >> +{
> >> +	return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8;
> >> +}
> >> +
> >> +extern const unsigned char scsi_command_size_tbl[8];
> >> +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
> >> +
> >> +static inline unsigned
> >> +scsi_command_size(const unsigned char *cmnd)
> >> +{
> >> +	return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
> >> +		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
> >> +}
> >> +
> >> +/*
> >>   *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
> >>   *  T10/1561-D Revision 4 Draft dated 7th November 2002.
> >>   */
> >> diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
> >> index dea73e5..f4dacb1 100644
> >> --- a/include/scsi/scsi_cmnd.h
> >> +++ b/include/scsi/scsi_cmnd.h
> >> @@ -78,7 +78,7 @@ struct scsi_cmnd {
> >>  	int allowed;
> >>  	int timeout_per_command;
> >>  
> >> -	unsigned char cmd_len;
> >> +	unsigned short cmd_len;
> >>  	enum dma_data_direction sc_data_direction;
> >>  
> >>  	/* These elements define the operation we are about to perform */
> >> diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
> >> index 4913286..31f1bfd 100644
> >> --- a/include/scsi/scsi_host.h
> >> +++ b/include/scsi/scsi_host.h
> >> @@ -573,13 +573,11 @@ struct Scsi_Host {
> >>  	/*
> >>  	 * The maximum length of SCSI commands that this host can accept.
> >>  	 * Probably 12 for most host adapters, but could be 16 for others.
> >> +	 * or 260 if the driver supports variable length cdbs.
> >>  	 * For drivers that don't set this field, a value of 12 is
> >> -	 * assumed.  I am leaving this as a number rather than a bit
> >> -	 * because you never know what subsequent SCSI standards might do
> >> -	 * (i.e. could there be a 20 byte or a 24-byte command a few years
> >> -	 * down the road?).  
> >> +	 * assumed.
> >>  	 */
> >> -	unsigned char max_cmd_len;
> >> +	unsigned short max_cmd_len;
> >>  
> >>  	int this_id;
> >>  	int can_queue;
> >> -- 
> >> 1.5.3.3
> >>
> >>
> >> --
> 
> As a reply to this mail I'll send a patch without the extra space.
> 
> Boaz
> 
> --
> 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

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-16  8:33                                 ` Jens Axboe
  2008-04-16  9:08                                   ` Boaz Harrosh
@ 2008-04-17  4:02                                   ` FUJITA Tomonori
  1 sibling, 0 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-17  4:02 UTC (permalink / raw)
  To: jens.axboe
  Cc: fujita.tomonori, bzolnier, linux-scsi, bharrosh, linux-ide, akpm

On Wed, 16 Apr 2008 10:33:06 +0200
Jens Axboe <jens.axboe@oracle.com> wrote:

> On Wed, Apr 16 2008, FUJITA Tomonori wrote:
> > On Wed, 16 Apr 2008 00:50:54 +0200
> > Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
> > 
> > > 
> > > Hi,
> > > 
> > > On Monday 14 April 2008, Jens Axboe wrote:
> > > > On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> > > > > This patch changes rq->cmd from the static array to a pointer to
> > > > > support large commands.
> > > > > 
> > > > > We rarely handle large commands. So for optimization, a struct request
> > > > > still has a static array for a command. rq_init sets rq->cmd pointer
> > > > > to the static array.
> > > > > 
> > > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > > > > Cc: Jens Axboe <jens.axboe@oracle.com>
> > > > > ---
> > > > >  block/blk-core.c       |    1 +
> > > > >  drivers/ide/ide-io.c   |    1 +
> > > > >  include/linux/blkdev.h |   12 ++++++++++--
> > > > >  3 files changed, 12 insertions(+), 2 deletions(-)
> > > > > 
> > > > > diff --git a/block/blk-core.c b/block/blk-core.c
> > > > > index 6669238..6f0968f 100644
> > > > > --- a/block/blk-core.c
> > > > > +++ b/block/blk-core.c
> > > > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> > > > >  	rq->errors = 0;
> > > > >  	rq->ref_count = 1;
> > > > >  	rq->cmd_len = 0;
> > > > > +	rq->cmd = rq->__cmd;
> > > > >  	memset(rq->cmd, 0, BLK_MAX_CDB);
> > > > >  	rq->data_len = 0;
> > > > >  	rq->extra_len = 0;
> > > > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> > > > > index 7153796..bac5ea1 100644
> > > > > --- a/drivers/ide/ide-io.c
> > > > > +++ b/drivers/ide/ide-io.c
> > > > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> > > > >  {
> > > > >  	memset(rq, 0, sizeof(*rq));
> > > > >  	rq->ref_count = 1;
> > > > > +	rq->cmd = rq->__cmd;
> > > > >  }
> > > 
> > > Tomo, some more changes are needed:
> > > 
> > > Please think about all _static_/dynamic allocations of 'struct request'
> > > used together with REQ_TYPE_SPECIAL etc., i.e.
> > 
> > I think that using struct request allocated statically is wrong from
> > the perspective of the block layer design, that is, you always need to
> > use blk_get_request. I think that except ide, everyone does.
> > 
> > I try to convert ide to use blk_get_request properly if you want.
> 
> That would be best, but the on-stack allocation has the benefit that
> it'll always work. So until we can completely get rid of that, lets just
> make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
> lot saner than doing a memset() anyway.

I'm fine with that.

There is one minor issue. rq_init doesn't initialize rq->cmd_flags so
the callers need to do it for themselves (If they don't, probably they
hit BUG_ON in blk_queue_end_tag).

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-17  3:59                                     ` FUJITA Tomonori
@ 2008-04-17  7:07                                       ` Jens Axboe
  2008-04-17 11:55                                         ` Bartlomiej Zolnierkiewicz
  2008-04-17 12:07                                         ` FUJITA Tomonori
  0 siblings, 2 replies; 77+ messages in thread
From: Jens Axboe @ 2008-04-17  7:07 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: bharrosh, bzolnier, linux-scsi, linux-ide, akpm

On Thu, Apr 17 2008, FUJITA Tomonori wrote:
> On Wed, 16 Apr 2008 12:08:25 +0300
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
> > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> > > On Wed, Apr 16 2008, FUJITA Tomonori wrote:
> > >> On Wed, 16 Apr 2008 00:50:54 +0200
> > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
> > >>
> > >>> Hi,
> > >>>
> > >>> On Monday 14 April 2008, Jens Axboe wrote:
> > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> > >>>>> This patch changes rq->cmd from the static array to a pointer to
> > >>>>> support large commands.
> > >>>>>
> > >>>>> We rarely handle large commands. So for optimization, a struct request
> > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer
> > >>>>> to the static array.
> > >>>>>
> > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com>
> > >>>>> ---
> > >>>>>  block/blk-core.c       |    1 +
> > >>>>>  drivers/ide/ide-io.c   |    1 +
> > >>>>>  include/linux/blkdev.h |   12 ++++++++++--
> > >>>>>  3 files changed, 12 insertions(+), 2 deletions(-)
> > >>>>>
> > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c
> > >>>>> index 6669238..6f0968f 100644
> > >>>>> --- a/block/blk-core.c
> > >>>>> +++ b/block/blk-core.c
> > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> > >>>>>  	rq->errors = 0;
> > >>>>>  	rq->ref_count = 1;
> > >>>>>  	rq->cmd_len = 0;
> > >>>>> +	rq->cmd = rq->__cmd;
> > >>>>>  	memset(rq->cmd, 0, BLK_MAX_CDB);
> > >>>>>  	rq->data_len = 0;
> > >>>>>  	rq->extra_len = 0;
> > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> > >>>>> index 7153796..bac5ea1 100644
> > >>>>> --- a/drivers/ide/ide-io.c
> > >>>>> +++ b/drivers/ide/ide-io.c
> > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> > >>>>>  {
> > >>>>>  	memset(rq, 0, sizeof(*rq));
> > >>>>>  	rq->ref_count = 1;
> > >>>>> +	rq->cmd = rq->__cmd;
> > >>>>>  }
> > >>> Tomo, some more changes are needed:
> > >>>
> > >>> Please think about all _static_/dynamic allocations of 'struct request'
> > >>> used together with REQ_TYPE_SPECIAL etc., i.e.
> > >> I think that using struct request allocated statically is wrong from
> > >> the perspective of the block layer design, that is, you always need to
> > >> use blk_get_request. I think that except ide, everyone does.
> > >>
> > >> I try to convert ide to use blk_get_request properly if you want.
> > > 
> > > That would be best, but the on-stack allocation has the benefit that
> > > it'll always work. So until we can completely get rid of that, lets just
> > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
> > > lot saner than doing a memset() anyway.
> > > 
> > 
> > Just a patch that I had for ages since the bad old request bidi times,
> > perhaps is also good today. (rebased to for-2.6.26 branch)
> > ---
> > From: Boaz Harrosh <bharrosh@panasas.com>
> > Date: Wed, 16 Apr 2008 12:05:33 +0300
> > Subject: [PATCH] Initialize all members of struct request in rq_init
> > 
> > Before, every member added/removed from struct request would entitle a change
> > to rq_init, for initialization. Now all members are default to zero and only
> > the none zero members are specifically initialized.
> > 
> > Users that need requests on the stack or pre-allocated, must call rq_init()
> > before use.
> > 
> > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> > ---
> >  block/blk-core.c |   22 ++--------------------
> >  1 files changed, 2 insertions(+), 20 deletions(-)
> > 
> > diff --git a/block/blk-core.c b/block/blk-core.c
> > index 6f0968f..3f4c563 100644
> > --- a/block/blk-core.c
> > +++ b/block/blk-core.c
> > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info);
> >   */
> >  void rq_init(struct request_queue *q, struct request *rq)
> >  {
> > +	memset(rq, 0, sizeof(*rq));
> 
> Hmm, rq_init comment says:
> 
> /*
>  * We can't just memset() the structure, since the allocation path
>  * already stored some information in the request.
>  */
> 
> I think that we can't initialize rq->cmd_flags here.

That is correct, the patch wont work as-is. The principle of clearing
every member except block internal is sound and should be applied,
though.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-17  7:07                                       ` Jens Axboe
@ 2008-04-17 11:55                                         ` Bartlomiej Zolnierkiewicz
  2008-04-17 11:58                                           ` Bartlomiej Zolnierkiewicz
  2008-04-17 12:07                                         ` FUJITA Tomonori
  1 sibling, 1 reply; 77+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-04-17 11:55 UTC (permalink / raw)
  To: Jens Axboe; +Cc: FUJITA Tomonori, bharrosh, linux-scsi, linux-ide, akpm

On Thu, Apr 17, 2008 at 9:07 AM, Jens Axboe <jens.axboe@oracle.com> wrote:
>
> On Thu, Apr 17 2008, FUJITA Tomonori wrote:
>  > On Wed, 16 Apr 2008 12:08:25 +0300
>  > Boaz Harrosh <bharrosh@panasas.com> wrote:
>  >
>  > > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
>  > > > On Wed, Apr 16 2008, FUJITA Tomonori wrote:
>  > > >> On Wed, 16 Apr 2008 00:50:54 +0200
>  > > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
>  > > >>
>  > > >>> Hi,
>  > > >>>
>  > > >>> On Monday 14 April 2008, Jens Axboe wrote:
>  > > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
>  > > >>>>> This patch changes rq->cmd from the static array to a pointer to
>  > > >>>>> support large commands.
>  > > >>>>>
>  > > >>>>> We rarely handle large commands. So for optimization, a struct request
>  > > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer
>  > > >>>>> to the static array.
>  > > >>>>>
>  > > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
>  > > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com>
>  > > >>>>> ---
>  > > >>>>>  block/blk-core.c       |    1 +
>  > > >>>>>  drivers/ide/ide-io.c   |    1 +
>  > > >>>>>  include/linux/blkdev.h |   12 ++++++++++--
>  > > >>>>>  3 files changed, 12 insertions(+), 2 deletions(-)
>  > > >>>>>
>  > > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c
>  > > >>>>> index 6669238..6f0968f 100644
>  > > >>>>> --- a/block/blk-core.c
>  > > >>>>> +++ b/block/blk-core.c
>  > > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
>  > > >>>>>       rq->errors = 0;
>  > > >>>>>       rq->ref_count = 1;
>  > > >>>>>       rq->cmd_len = 0;
>  > > >>>>> +     rq->cmd = rq->__cmd;
>  > > >>>>>       memset(rq->cmd, 0, BLK_MAX_CDB);
>  > > >>>>>       rq->data_len = 0;
>  > > >>>>>       rq->extra_len = 0;
>  > > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
>  > > >>>>> index 7153796..bac5ea1 100644
>  > > >>>>> --- a/drivers/ide/ide-io.c
>  > > >>>>> +++ b/drivers/ide/ide-io.c
>  > > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
>  > > >>>>>  {
>  > > >>>>>       memset(rq, 0, sizeof(*rq));
>  > > >>>>>       rq->ref_count = 1;
>  > > >>>>> +     rq->cmd = rq->__cmd;
>  > > >>>>>  }
>  > > >>> Tomo, some more changes are needed:
>  > > >>>
>  > > >>> Please think about all _static_/dynamic allocations of 'struct request'
>  > > >>> used together with REQ_TYPE_SPECIAL etc., i.e.
>  > > >> I think that using struct request allocated statically is wrong from
>  > > >> the perspective of the block layer design, that is, you always need to
>  > > >> use blk_get_request. I think that except ide, everyone does.
>  > > >>
>  > > >> I try to convert ide to use blk_get_request properly if you want.
>  > > >
>  > > > That would be best, but the on-stack allocation has the benefit that
>  > > > it'll always work. So until we can completely get rid of that, lets just
>  > > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
>  > > > lot saner than doing a memset() anyway.
>  > > >
>  > >
>  > > Just a patch that I had for ages since the bad old request bidi times,
>  > > perhaps is also good today. (rebased to for-2.6.26 branch)
>  > > ---
>  > > From: Boaz Harrosh <bharrosh@panasas.com>
>  > > Date: Wed, 16 Apr 2008 12:05:33 +0300
>  > > Subject: [PATCH] Initialize all members of struct request in rq_init
>  > >
>  > > Before, every member added/removed from struct request would entitle a change
>  > > to rq_init, for initialization. Now all members are default to zero and only
>  > > the none zero members are specifically initialized.
>  > >
>  > > Users that need requests on the stack or pre-allocated, must call rq_init()
>  > > before use.
>  > >
>  > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>  > > ---
>  > >  block/blk-core.c |   22 ++--------------------
>  > >  1 files changed, 2 insertions(+), 20 deletions(-)
>  > >
>  > > diff --git a/block/blk-core.c b/block/blk-core.c
>  > > index 6f0968f..3f4c563 100644
>  > > --- a/block/blk-core.c
>  > > +++ b/block/blk-core.c
>  > > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info);
>  > >   */
>  > >  void rq_init(struct request_queue *q, struct request *rq)
>  > >  {
>  > > +   memset(rq, 0, sizeof(*rq));
>  >
>  > Hmm, rq_init comment says:
>  >
>  > /*
>  >  * We can't just memset() the structure, since the allocation path
>  >  * already stored some information in the request.
>  >  */
>  >
>  > I think that we can't initialize rq->cmd_flags here.
>
>  That is correct, the patch wont work as-is. The principle of clearing
>  every member except block internal is sound and should be applied,
>  though.

While we're at it we may fix it as well (preferably in another pre-patch):

- move setting rq->cmd_flags from blk_alloc_request() to the callers
  (this is only get_request() ATM)

- re-order setting rq->cmd_flags vs calling rq_init() in get_request(),
  queue_lfush() and  start_ordered()

Thanks,
Bart

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-17 11:55                                         ` Bartlomiej Zolnierkiewicz
@ 2008-04-17 11:58                                           ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 77+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-04-17 11:58 UTC (permalink / raw)
  To: Jens Axboe; +Cc: FUJITA Tomonori, bharrosh, linux-scsi, linux-ide, akpm

On Thu, Apr 17, 2008 at 1:55 PM, Bartlomiej Zolnierkiewicz
<bzolnier@gmail.com> wrote:
>
> On Thu, Apr 17, 2008 at 9:07 AM, Jens Axboe <jens.axboe@oracle.com> wrote:
>  >
>  > On Thu, Apr 17 2008, FUJITA Tomonori wrote:
>  >  > On Wed, 16 Apr 2008 12:08:25 +0300
>  >  > Boaz Harrosh <bharrosh@panasas.com> wrote:
>  >  >
>  >  > > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
>  >  > > > On Wed, Apr 16 2008, FUJITA Tomonori wrote:
>  >  > > >> On Wed, 16 Apr 2008 00:50:54 +0200
>  >  > > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
>  >  > > >>
>  >  > > >>> Hi,
>  >  > > >>>
>  >  > > >>> On Monday 14 April 2008, Jens Axboe wrote:
>  >  > > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
>  >  > > >>>>> This patch changes rq->cmd from the static array to a pointer to
>  >  > > >>>>> support large commands.
>  >  > > >>>>>
>  >  > > >>>>> We rarely handle large commands. So for optimization, a struct request
>  >  > > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer
>  >  > > >>>>> to the static array.
>  >  > > >>>>>
>  >  > > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
>  >  > > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com>
>  >  > > >>>>> ---
>  >  > > >>>>>  block/blk-core.c       |    1 +
>  >  > > >>>>>  drivers/ide/ide-io.c   |    1 +
>  >  > > >>>>>  include/linux/blkdev.h |   12 ++++++++++--
>  >  > > >>>>>  3 files changed, 12 insertions(+), 2 deletions(-)
>  >  > > >>>>>
>  >  > > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c
>  >  > > >>>>> index 6669238..6f0968f 100644
>  >  > > >>>>> --- a/block/blk-core.c
>  >  > > >>>>> +++ b/block/blk-core.c
>  >  > > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
>  >  > > >>>>>       rq->errors = 0;
>  >  > > >>>>>       rq->ref_count = 1;
>  >  > > >>>>>       rq->cmd_len = 0;
>  >  > > >>>>> +     rq->cmd = rq->__cmd;
>  >  > > >>>>>       memset(rq->cmd, 0, BLK_MAX_CDB);
>  >  > > >>>>>       rq->data_len = 0;
>  >  > > >>>>>       rq->extra_len = 0;
>  >  > > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
>  >  > > >>>>> index 7153796..bac5ea1 100644
>  >  > > >>>>> --- a/drivers/ide/ide-io.c
>  >  > > >>>>> +++ b/drivers/ide/ide-io.c
>  >  > > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
>  >  > > >>>>>  {
>  >  > > >>>>>       memset(rq, 0, sizeof(*rq));
>  >  > > >>>>>       rq->ref_count = 1;
>  >  > > >>>>> +     rq->cmd = rq->__cmd;
>  >  > > >>>>>  }
>  >  > > >>> Tomo, some more changes are needed:
>  >  > > >>>
>  >  > > >>> Please think about all _static_/dynamic allocations of 'struct request'
>  >  > > >>> used together with REQ_TYPE_SPECIAL etc., i.e.
>  >  > > >> I think that using struct request allocated statically is wrong from
>  >  > > >> the perspective of the block layer design, that is, you always need to
>  >  > > >> use blk_get_request. I think that except ide, everyone does.
>  >  > > >>
>  >  > > >> I try to convert ide to use blk_get_request properly if you want.
>  >  > > >
>  >  > > > That would be best, but the on-stack allocation has the benefit that
>  >  > > > it'll always work. So until we can completely get rid of that, lets just
>  >  > > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
>  >  > > > lot saner than doing a memset() anyway.
>  >  > > >
>  >  > >
>  >  > > Just a patch that I had for ages since the bad old request bidi times,
>  >  > > perhaps is also good today. (rebased to for-2.6.26 branch)
>  >  > > ---
>  >  > > From: Boaz Harrosh <bharrosh@panasas.com>
>  >  > > Date: Wed, 16 Apr 2008 12:05:33 +0300
>  >  > > Subject: [PATCH] Initialize all members of struct request in rq_init
>  >  > >
>  >  > > Before, every member added/removed from struct request would entitle a change
>  >  > > to rq_init, for initialization. Now all members are default to zero and only
>  >  > > the none zero members are specifically initialized.
>  >  > >
>  >  > > Users that need requests on the stack or pre-allocated, must call rq_init()
>  >  > > before use.
>  >  > >
>  >  > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>  >  > > ---
>  >  > >  block/blk-core.c |   22 ++--------------------
>  >  > >  1 files changed, 2 insertions(+), 20 deletions(-)
>  >  > >
>  >  > > diff --git a/block/blk-core.c b/block/blk-core.c
>  >  > > index 6f0968f..3f4c563 100644
>  >  > > --- a/block/blk-core.c
>  >  > > +++ b/block/blk-core.c
>  >  > > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info);
>  >  > >   */
>  >  > >  void rq_init(struct request_queue *q, struct request *rq)
>  >  > >  {
>  >  > > +   memset(rq, 0, sizeof(*rq));
>  >  >
>  >  > Hmm, rq_init comment says:
>  >  >
>  >  > /*
>  >  >  * We can't just memset() the structure, since the allocation path
>  >  >  * already stored some information in the request.
>  >  >  */
>  >  >
>  >  > I think that we can't initialize rq->cmd_flags here.
>  >
>  >  That is correct, the patch wont work as-is. The principle of clearing
>  >  every member except block internal is sound and should be applied,
>  >  though.
>
>  While we're at it we may fix it as well (preferably in another pre-patch):
>
>  - move setting rq->cmd_flags from blk_alloc_request() to the callers
>   (this is only get_request() ATM)

ditto for elv_set_request() call

>  - re-order setting rq->cmd_flags vs calling rq_init() in get_request(),
>   queue_lfush() and  start_ordered()

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] block: add large command support
  2008-04-17  7:07                                       ` Jens Axboe
  2008-04-17 11:55                                         ` Bartlomiej Zolnierkiewicz
@ 2008-04-17 12:07                                         ` FUJITA Tomonori
  1 sibling, 0 replies; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-17 12:07 UTC (permalink / raw)
  To: jens.axboe
  Cc: fujita.tomonori, bharrosh, bzolnier, linux-scsi, linux-ide, akpm,
	James.Bottomley

On Thu, 17 Apr 2008 09:07:05 +0200
Jens Axboe <jens.axboe@oracle.com> wrote:

> On Thu, Apr 17 2008, FUJITA Tomonori wrote:
> > On Wed, 16 Apr 2008 12:08:25 +0300
> > Boaz Harrosh <bharrosh@panasas.com> wrote:
> > 
> > > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote:
> > > > On Wed, Apr 16 2008, FUJITA Tomonori wrote:
> > > >> On Wed, 16 Apr 2008 00:50:54 +0200
> > > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:
> > > >>
> > > >>> Hi,
> > > >>>
> > > >>> On Monday 14 April 2008, Jens Axboe wrote:
> > > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote:
> > > >>>>> This patch changes rq->cmd from the static array to a pointer to
> > > >>>>> support large commands.
> > > >>>>>
> > > >>>>> We rarely handle large commands. So for optimization, a struct request
> > > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer
> > > >>>>> to the static array.
> > > >>>>>
> > > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> > > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com>
> > > >>>>> ---
> > > >>>>>  block/blk-core.c       |    1 +
> > > >>>>>  drivers/ide/ide-io.c   |    1 +
> > > >>>>>  include/linux/blkdev.h |   12 ++++++++++--
> > > >>>>>  3 files changed, 12 insertions(+), 2 deletions(-)
> > > >>>>>
> > > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c
> > > >>>>> index 6669238..6f0968f 100644
> > > >>>>> --- a/block/blk-core.c
> > > >>>>> +++ b/block/blk-core.c
> > > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq)
> > > >>>>>  	rq->errors = 0;
> > > >>>>>  	rq->ref_count = 1;
> > > >>>>>  	rq->cmd_len = 0;
> > > >>>>> +	rq->cmd = rq->__cmd;
> > > >>>>>  	memset(rq->cmd, 0, BLK_MAX_CDB);
> > > >>>>>  	rq->data_len = 0;
> > > >>>>>  	rq->extra_len = 0;
> > > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
> > > >>>>> index 7153796..bac5ea1 100644
> > > >>>>> --- a/drivers/ide/ide-io.c
> > > >>>>> +++ b/drivers/ide/ide-io.c
> > > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq)
> > > >>>>>  {
> > > >>>>>  	memset(rq, 0, sizeof(*rq));
> > > >>>>>  	rq->ref_count = 1;
> > > >>>>> +	rq->cmd = rq->__cmd;
> > > >>>>>  }
> > > >>> Tomo, some more changes are needed:
> > > >>>
> > > >>> Please think about all _static_/dynamic allocations of 'struct request'
> > > >>> used together with REQ_TYPE_SPECIAL etc., i.e.
> > > >> I think that using struct request allocated statically is wrong from
> > > >> the perspective of the block layer design, that is, you always need to
> > > >> use blk_get_request. I think that except ide, everyone does.
> > > >>
> > > >> I try to convert ide to use blk_get_request properly if you want.
> > > > 
> > > > That would be best, but the on-stack allocation has the benefit that
> > > > it'll always work. So until we can completely get rid of that, lets just
> > > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a
> > > > lot saner than doing a memset() anyway.
> > > > 
> > > 
> > > Just a patch that I had for ages since the bad old request bidi times,
> > > perhaps is also good today. (rebased to for-2.6.26 branch)
> > > ---
> > > From: Boaz Harrosh <bharrosh@panasas.com>
> > > Date: Wed, 16 Apr 2008 12:05:33 +0300
> > > Subject: [PATCH] Initialize all members of struct request in rq_init
> > > 
> > > Before, every member added/removed from struct request would entitle a change
> > > to rq_init, for initialization. Now all members are default to zero and only
> > > the none zero members are specifically initialized.
> > > 
> > > Users that need requests on the stack or pre-allocated, must call rq_init()
> > > before use.
> > > 
> > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> > > ---
> > >  block/blk-core.c |   22 ++--------------------
> > >  1 files changed, 2 insertions(+), 20 deletions(-)
> > > 
> > > diff --git a/block/blk-core.c b/block/blk-core.c
> > > index 6f0968f..3f4c563 100644
> > > --- a/block/blk-core.c
> > > +++ b/block/blk-core.c
> > > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info);
> > >   */
> > >  void rq_init(struct request_queue *q, struct request *rq)
> > >  {
> > > +	memset(rq, 0, sizeof(*rq));
> > 
> > Hmm, rq_init comment says:
> > 
> > /*
> >  * We can't just memset() the structure, since the allocation path
> >  * already stored some information in the request.
> >  */
> > 
> > I think that we can't initialize rq->cmd_flags here.
> 
> That is correct, the patch wont work as-is. The principle of clearing
> every member except block internal is sound and should be applied,
> though.

1) calls rq_init() and initializes rq->cmd_flags manually.
2) adds a new helper function to just memset() against rq.
3) modifies the block layer so that rq_init() can memset() against rq.
4) uses blk_get_request

I think that the second option would be the best for now but I don't
have a good name for such function.

The third or fourth option looks preferable for me in the long term
(probably, for 2.6.27).

Here's a patch to initialize rq->cmd by hand. I think that it's ok for
now.

drivers/scsi_errro.c doesn't need this hack now (since it doesn't use
struct request) but pending Boaz's extended cdbs patch needs this hack
since it removes scmd->cmnd array and uses rq->cmd.

===
From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Subject: [PATCH] block: initialize the cmd pointer in struct request

struct request that is not allocated via blk_get_request needs to
set up the cmd pointer.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
---
 drivers/block/nbd.c        |    3 +++
 drivers/block/paride/pd.c  |    1 +
 drivers/ide/ide-tape.c     |    1 +
 drivers/ide/ide-taskfile.c |    3 +--
 drivers/ide/ide.c          |    2 ++
 drivers/scsi/scsi_error.c  |    1 +
 6 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 60cc543..ebc653d 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -534,6 +534,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
 	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
 			lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
 
+	memset(&sreq, 0, sizeof(sreq));
+	sreq.cmd = sreq.__cmd;
+
 	switch (cmd) {
 	case NBD_DISCONNECT:
 	        printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index df819f8..e82a669 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -717,6 +717,7 @@ static int pd_special_command(struct pd_unit *disk,
 	int err = 0;
 
 	memset(&rq, 0, sizeof(rq));
+	rq.cmd = rq.__cmd;
 	rq.errors = 0;
 	rq.rq_disk = disk->gd;
 	rq.ref_count = 1;
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 0598ecf..d9c0267 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -946,6 +946,7 @@ static void idetape_create_request_sense_cmd(idetape_pc_t *pc)
 static void idetape_init_rq(struct request *rq, u8 cmd)
 {
 	memset(rq, 0, sizeof(*rq));
+	rq->cmd = rq->__cmd;
 	rq->cmd_type = REQ_TYPE_SPECIAL;
 	rq->cmd[0] = cmd;
 }
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 4c86a8d..1c30a57 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -529,8 +529,7 @@ int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
 {
 	struct request rq;
 
-	memset(&rq, 0, sizeof(rq));
-	rq.ref_count = 1;
+	ide_init_drive_cmd(&rq);
 	rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
 	rq.buffer = buf;
 
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index fc69fe2..96aaec2 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -881,6 +881,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
 		ide_acpi_get_timing(hwif);
 
 	memset(&rq, 0, sizeof(rq));
+	rq.cmd = rq.__cmd;
 	memset(&rqpm, 0, sizeof(rqpm));
 	memset(&args, 0, sizeof(args));
 	rq.cmd_type = REQ_TYPE_PM_SUSPEND;
@@ -919,6 +920,7 @@ static int generic_ide_resume(struct device *dev)
 	ide_acpi_exec_tfs(drive);
 
 	memset(&rq, 0, sizeof(rq));
+	rq.cmd = rq.__cmd;
 	memset(&rqpm, 0, sizeof(rqpm));
 	memset(&args, 0, sizeof(args));
 	rq.cmd_type = REQ_TYPE_PM_RESUME;
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 045a086..020b678 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1690,6 +1690,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
 	unsigned long flags;
 	int rtn;
 
+	req.cmd = req.__cmd;
 	scmd->request = &req;
 	memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
 
-- 
1.5.4.2


^ permalink raw reply related	[flat|nested] 77+ messages in thread

* [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs
  2008-04-17  4:01                           ` [PATCH 2/3] " FUJITA Tomonori
@ 2008-04-17 12:25                             ` Boaz Harrosh
  2008-04-17 12:49                               ` Boaz Harrosh
  2008-04-17 13:04                               ` FUJITA Tomonori
  0 siblings, 2 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-17 12:25 UTC (permalink / raw)
  To: FUJITA Tomonori, James.Bottomley
  Cc: linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven


  Add support for variable-length, extended, and vendor specific
  CDBs to scsi-ml. It is now possible for initiators and ULD's
  to issue these types of commands. LLDs need not change much.
  All they need is to raise the .max_cmd_len to the longest command
  they support (see iscsi patch).

  - clean-up some code paths that did not expect commands to be
    larger than 16, and change cmd_len members' type to short as
    char is not enough.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
 block/scsi_ioctl.c       |    5 ++---
 drivers/scsi/constants.c |   10 +++-------
 drivers/scsi/scsi.c      |   15 ++++-----------
 drivers/scsi/scsi_lib.c  |    2 +-
 include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
 include/scsi/scsi_cmnd.h |    2 +-
 include/scsi/scsi_host.h |    8 +++-----
 7 files changed, 47 insertions(+), 35 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index a2c3a93..aaf07e4 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -33,13 +33,12 @@
 #include <scsi/scsi_cmnd.h>
 
 /* Command group 3 is reserved and should never be used.  */
-const unsigned char scsi_command_size[8] =
+const unsigned char scsi_command_size_tbl[8] =
 {
 	6, 10, 10, 12,
 	16, 12, 10, 10
 };
-
-EXPORT_SYMBOL(scsi_command_size);
+EXPORT_SYMBOL(scsi_command_size_tbl);
 
 #include <scsi/sg.h>
 
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 403a7f2..9785d73 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -28,7 +28,6 @@
 #define SERVICE_ACTION_OUT_12 0xa9
 #define SERVICE_ACTION_IN_16 0x9e
 #define SERVICE_ACTION_OUT_16 0x9f
-#define VARIABLE_LENGTH_CMD 0x7f
 
 
 
@@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short variable length command, "
 			       "len=%d ext_len=%d", len, cdb_len);
@@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
-		len = cdbp[7] + 8;
+		len = scsi_varlen_cdb_length(cdbp);
 		if (len < 10) {
 			printk("short opcode=0x%x command, len=%d "
 			       "ext_len=%d", cdb0, len, cdb_len);
@@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
 	int k, len;
 
 	print_opcode_name(cdb, 0);
-	if (VARIABLE_LENGTH_CMD == cdb[0])
-		len = cdb[7] + 8;
-	else
-		len = COMMAND_SIZE(cdb[0]);
+	len = scsi_command_size(cdb);
 	/* print out all bytes in cdb */
 	for (k = 0; k < len; ++k) 
 		printk(" %02x", cdb[k]);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index f6980bd..dd9dd65 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
 #define MIN_RESET_PERIOD (15*HZ)
 
 /*
- * Macro to determine the size of SCSI command. This macro takes vendor
- * unique commands into account. SCSI commands in groups 6 and 7 are
- * vendor unique and we will depend upon the command length being
- * supplied correctly in cmd_len.
- */
-#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
-				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -701,9 +692,11 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 	 * Before we queue this command, check if the command
 	 * length exceeds what the host adapter can handle.
 	 */
-	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
+	if (cmd->cmd_len > cmd->device->host->max_cmd_len) {
 		SCSI_LOG_MLQUEUE(3,
-				printk("queuecommand : command too long.\n"));
+			printk("queuecommand : command too long. "
+			       "cdb_size=%d host->max_cmd_len=%d\n",
+			       cmd->cmd_len, cmd->device->host->max_cmd_len));
 		cmd->result = (DID_ABORT << 16);
 
 		scsi_done(cmd);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 325270b..ba7e8ad 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -445,7 +445,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 	scsi_set_resid(cmd, 0);
 	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 	if (cmd->cmd_len == 0)
-		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+		cmd->cmd_len = scsi_command_size(cmd->cmnd);
 }
 
 void scsi_device_unbusy(struct scsi_device *sdev)
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 1f74bcd..32742c4 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -30,13 +30,6 @@
 #endif
 
 /*
- *	SCSI command lengths
- */
-
-extern const unsigned char scsi_command_size[8];
-#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
-
-/*
  * Special value for scanning to specify scanning or rescanning of all
  * possible channels, (target) ids, or luns on a given shost.
  */
@@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
 #define MODE_SENSE_10         0x5a
 #define PERSISTENT_RESERVE_IN 0x5e
 #define PERSISTENT_RESERVE_OUT 0x5f
+#define VARIABLE_LENGTH_CMD   0x7f
 #define REPORT_LUNS           0xa0
 #define MAINTENANCE_IN        0xa3
 #define MOVE_MEDIUM           0xa5
@@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8];
 #define	ATA_12		      0xa1	/* 12-byte pass-thru */
 
 /*
+ *	SCSI command lengths
+ */
+
+#define SCSI_MAX_VARLEN_CDB_SIZE 260
+
+/* defined in T10 SCSI Primary Commands-2 (SPC2) */
+struct scsi_varlen_cdb_hdr {
+	u8 opcode;        /* opcode always == VARIABLE_LENGTH_CMD */
+	u8 control;
+	u8 misc[5];
+	u8 additional_cdb_length;         /* total cdb length - 8 */
+	__be16 service_action;
+	/* service specific data follows */
+};
+
+static inline unsigned
+scsi_varlen_cdb_length(const void *hdr)
+{
+	return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8;
+}
+
+extern const unsigned char scsi_command_size_tbl[8];
+#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
+
+static inline unsigned
+scsi_command_size(const unsigned char *cmnd)
+{
+	return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
+		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
+}
+
+/*
  *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
  *  T10/1561-D Revision 4 Draft dated 7th November 2002.
  */
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index dea73e5..f4dacb1 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -78,7 +78,7 @@ struct scsi_cmnd {
 	int allowed;
 	int timeout_per_command;
 
-	unsigned char cmd_len;
+	unsigned short cmd_len;
 	enum dma_data_direction sc_data_direction;
 
 	/* These elements define the operation we are about to perform */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 4913286..31f1bfd 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -573,13 +573,11 @@ struct Scsi_Host {
 	/*
 	 * The maximum length of SCSI commands that this host can accept.
 	 * Probably 12 for most host adapters, but could be 16 for others.
+	 * or 260 if the driver supports variable length cdbs.
 	 * For drivers that don't set this field, a value of 12 is
-	 * assumed.  I am leaving this as a number rather than a bit
-	 * because you never know what subsequent SCSI standards might do
-	 * (i.e. could there be a 20 byte or a 24-byte command a few years
-	 * down the road?).  
+	 * assumed.
 	 */
-	unsigned char max_cmd_len;
+	unsigned short max_cmd_len;
 
 	int this_id;
 	int can_queue;
-- 
1.5.3.3


^ permalink raw reply related	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs
  2008-04-17 12:25                             ` [PATCH 2/3 ver3] " Boaz Harrosh
@ 2008-04-17 12:49                               ` Boaz Harrosh
  2008-04-17 13:04                               ` FUJITA Tomonori
  1 sibling, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-17 12:49 UTC (permalink / raw)
  To: FUJITA Tomonori, James.Bottomley
  Cc: linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven

On Thu, Apr 17 2008 at 15:25 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote:
>   Add support for variable-length, extended, and vendor specific
>   CDBs to scsi-ml. It is now possible for initiators and ULD's
>   to issue these types of commands. LLDs need not change much.
>   All they need is to raise the .max_cmd_len to the longest command
>   they support (see iscsi patch).
> 
>   - clean-up some code paths that did not expect commands to be
>     larger than 16, and change cmd_len members' type to short as
>     char is not enough.
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
>  block/scsi_ioctl.c       |    5 ++---
>  drivers/scsi/constants.c |   10 +++-------
>  drivers/scsi/scsi.c      |   15 ++++-----------
>  drivers/scsi/scsi_lib.c  |    2 +-
>  include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
>  include/scsi/scsi_cmnd.h |    2 +-
>  include/scsi/scsi_host.h |    8 +++-----
>  7 files changed, 47 insertions(+), 35 deletions(-)
> 
> diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
> index a2c3a93..aaf07e4 100644
> --- a/block/scsi_ioctl.c
> +++ b/block/scsi_ioctl.c
> @@ -33,13 +33,12 @@
>  #include <scsi/scsi_cmnd.h>
>  
>  /* Command group 3 is reserved and should never be used.  */
> -const unsigned char scsi_command_size[8] =
> +const unsigned char scsi_command_size_tbl[8] =
>  {
>  	6, 10, 10, 12,
>  	16, 12, 10, 10
>  };
> -
> -EXPORT_SYMBOL(scsi_command_size);
> +EXPORT_SYMBOL(scsi_command_size_tbl);
>  
>  #include <scsi/sg.h>
>  
> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
> index 403a7f2..9785d73 100644
> --- a/drivers/scsi/constants.c
> +++ b/drivers/scsi/constants.c
> @@ -28,7 +28,6 @@
>  #define SERVICE_ACTION_OUT_12 0xa9
>  #define SERVICE_ACTION_IN_16 0x9e
>  #define SERVICE_ACTION_OUT_16 0x9f
> -#define VARIABLE_LENGTH_CMD 0x7f
>  
>  
>  
> @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
>  	cdb0 = cdbp[0];
>  	switch(cdb0) {
>  	case VARIABLE_LENGTH_CMD:
> -		len = cdbp[7] + 8;
> +		len = scsi_varlen_cdb_length(cdbp);
>  		if (len < 10) {
>  			printk("short variable length command, "
>  			       "len=%d ext_len=%d", len, cdb_len);
> @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len)
>  	cdb0 = cdbp[0];
>  	switch(cdb0) {
>  	case VARIABLE_LENGTH_CMD:
> -		len = cdbp[7] + 8;
> +		len = scsi_varlen_cdb_length(cdbp);
>  		if (len < 10) {
>  			printk("short opcode=0x%x command, len=%d "
>  			       "ext_len=%d", cdb0, len, cdb_len);
> @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb)
>  	int k, len;
>  
>  	print_opcode_name(cdb, 0);
> -	if (VARIABLE_LENGTH_CMD == cdb[0])
> -		len = cdb[7] + 8;
> -	else
> -		len = COMMAND_SIZE(cdb[0]);
> +	len = scsi_command_size(cdb);
>  	/* print out all bytes in cdb */
>  	for (k = 0; k < len; ++k) 
>  		printk(" %02x", cdb[k]);
> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
> index f6980bd..dd9dd65 100644
> --- a/drivers/scsi/scsi.c
> +++ b/drivers/scsi/scsi.c
> @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd);
>  #define MIN_RESET_PERIOD (15*HZ)
>  
>  /*
> - * Macro to determine the size of SCSI command. This macro takes vendor
> - * unique commands into account. SCSI commands in groups 6 and 7 are
> - * vendor unique and we will depend upon the command length being
> - * supplied correctly in cmd_len.
> - */
> -#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
> -				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
> -
> -/*
>   * Note - the initial logging level can be set here to log events at boot time.
>   * After the system is up, you may enable logging via the /proc interface.
>   */
> @@ -701,9 +692,11 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
>  	 * Before we queue this command, check if the command
>  	 * length exceeds what the host adapter can handle.
>  	 */
> -	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
> +	if (cmd->cmd_len > cmd->device->host->max_cmd_len) {
>  		SCSI_LOG_MLQUEUE(3,
> -				printk("queuecommand : command too long.\n"));
> +			printk("queuecommand : command too long. "
> +			       "cdb_size=%d host->max_cmd_len=%d\n",
> +			       cmd->cmd_len, cmd->device->host->max_cmd_len));
>  		cmd->result = (DID_ABORT << 16);
>  
>  		scsi_done(cmd);
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index 325270b..ba7e8ad 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -445,7 +445,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
>  	scsi_set_resid(cmd, 0);
>  	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
>  	if (cmd->cmd_len == 0)
> -		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
> +		cmd->cmd_len = scsi_command_size(cmd->cmnd);
>  }
>  
>  void scsi_device_unbusy(struct scsi_device *sdev)
> diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
> index 1f74bcd..32742c4 100644
> --- a/include/scsi/scsi.h
> +++ b/include/scsi/scsi.h
> @@ -30,13 +30,6 @@
>  #endif
>  
>  /*
> - *	SCSI command lengths
> - */
> -
> -extern const unsigned char scsi_command_size[8];
> -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
> -
> -/*
>   * Special value for scanning to specify scanning or rescanning of all
>   * possible channels, (target) ids, or luns on a given shost.
>   */
> @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
>  #define MODE_SENSE_10         0x5a
>  #define PERSISTENT_RESERVE_IN 0x5e
>  #define PERSISTENT_RESERVE_OUT 0x5f
> +#define VARIABLE_LENGTH_CMD   0x7f
>  #define REPORT_LUNS           0xa0
>  #define MAINTENANCE_IN        0xa3
>  #define MOVE_MEDIUM           0xa5
> @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8];
>  #define	ATA_12		      0xa1	/* 12-byte pass-thru */
>  
>  /*
> + *	SCSI command lengths
> + */
> +
> +#define SCSI_MAX_VARLEN_CDB_SIZE 260
> +
> +/* defined in T10 SCSI Primary Commands-2 (SPC2) */
> +struct scsi_varlen_cdb_hdr {
> +	u8 opcode;        /* opcode always == VARIABLE_LENGTH_CMD */
> +	u8 control;
> +	u8 misc[5];
> +	u8 additional_cdb_length;         /* total cdb length - 8 */
> +	__be16 service_action;
> +	/* service specific data follows */
> +};
> +
> +static inline unsigned
> +scsi_varlen_cdb_length(const void *hdr)
> +{
> +	return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8;
> +}
> +
> +extern const unsigned char scsi_command_size_tbl[8];
> +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
> +
> +static inline unsigned
> +scsi_command_size(const unsigned char *cmnd)
> +{
> +	return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
> +		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
> +}
> +
> +/*
>   *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
>   *  T10/1561-D Revision 4 Draft dated 7th November 2002.
>   */
> diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
> index dea73e5..f4dacb1 100644
> --- a/include/scsi/scsi_cmnd.h
> +++ b/include/scsi/scsi_cmnd.h
> @@ -78,7 +78,7 @@ struct scsi_cmnd {
>  	int allowed;
>  	int timeout_per_command;
>  
> -	unsigned char cmd_len;
> +	unsigned short cmd_len;
>  	enum dma_data_direction sc_data_direction;
>  
>  	/* These elements define the operation we are about to perform */
> diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
> index 4913286..31f1bfd 100644
> --- a/include/scsi/scsi_host.h
> +++ b/include/scsi/scsi_host.h
> @@ -573,13 +573,11 @@ struct Scsi_Host {
>  	/*
>  	 * The maximum length of SCSI commands that this host can accept.
>  	 * Probably 12 for most host adapters, but could be 16 for others.
> +	 * or 260 if the driver supports variable length cdbs.
>  	 * For drivers that don't set this field, a value of 12 is
> -	 * assumed.  I am leaving this as a number rather than a bit
> -	 * because you never know what subsequent SCSI standards might do
> -	 * (i.e. could there be a 20 byte or a 24-byte command a few years
> -	 * down the road?).  
> +	 * assumed.
>  	 */
> -	unsigned char max_cmd_len;
> +	unsigned short max_cmd_len;
>  
>  	int this_id;
>  	int can_queue;

I have tested above patch both, booting and general usage of sata disks
and cdrom on an x86_64 work station, and also my OSD varlen setup. And
it works, so Tomo was right, we do not need the extra checks, the one at
scsi_init_cmd_errh() takes care of all the cases.

When I developed this, (20 month ago) I used to hit a BUG_ON(!cmd->cmd_len);
in scsi_dispatch_cmd(). But I have just tested above patch (+ the BUG_ON) and
it does not trigger.

Thanks Tomo
Boaz

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs
  2008-04-17 12:25                             ` [PATCH 2/3 ver3] " Boaz Harrosh
  2008-04-17 12:49                               ` Boaz Harrosh
@ 2008-04-17 13:04                               ` FUJITA Tomonori
  2008-04-17 13:29                                 ` Boaz Harrosh
  1 sibling, 1 reply; 77+ messages in thread
From: FUJITA Tomonori @ 2008-04-17 13:04 UTC (permalink / raw)
  To: bharrosh
  Cc: fujita.tomonori, James.Bottomley, linux-scsi, jens.axboe,
	bzolnier, agk, Geert.Uytterhoeven

On Thu, 17 Apr 2008 15:25:23 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> 
>   Add support for variable-length, extended, and vendor specific
>   CDBs to scsi-ml. It is now possible for initiators and ULD's
>   to issue these types of commands. LLDs need not change much.
>   All they need is to raise the .max_cmd_len to the longest command
>   they support (see iscsi patch).
> 
>   - clean-up some code paths that did not expect commands to be
>     larger than 16, and change cmd_len members' type to short as
>     char is not enough.
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
>  block/scsi_ioctl.c       |    5 ++---
>  drivers/scsi/constants.c |   10 +++-------
>  drivers/scsi/scsi.c      |   15 ++++-----------
>  drivers/scsi/scsi_lib.c  |    2 +-
>  include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
>  include/scsi/scsi_cmnd.h |    2 +-
>  include/scsi/scsi_host.h |    8 +++-----
>  7 files changed, 47 insertions(+), 35 deletions(-)

looks fine to me though I've not tested it.

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs
  2008-04-17 13:04                               ` FUJITA Tomonori
@ 2008-04-17 13:29                                 ` Boaz Harrosh
  0 siblings, 0 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-04-17 13:29 UTC (permalink / raw)
  To: FUJITA Tomonori, Pete Wyckoff
  Cc: James.Bottomley, linux-scsi, jens.axboe, bzolnier, agk,
	Geert.Uytterhoeven

On Thu, Apr 17 2008 at 16:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:
> On Thu, 17 Apr 2008 15:25:23 +0300
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>>   Add support for variable-length, extended, and vendor specific
>>   CDBs to scsi-ml. It is now possible for initiators and ULD's
>>   to issue these types of commands. LLDs need not change much.
>>   All they need is to raise the .max_cmd_len to the longest command
>>   they support (see iscsi patch).
>>
>>   - clean-up some code paths that did not expect commands to be
>>     larger than 16, and change cmd_len members' type to short as
>>     char is not enough.
>>
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
>> ---
>>  block/scsi_ioctl.c       |    5 ++---
>>  drivers/scsi/constants.c |   10 +++-------
>>  drivers/scsi/scsi.c      |   15 ++++-----------
>>  drivers/scsi/scsi_lib.c  |    2 +-
>>  include/scsi/scsi.h      |   40 +++++++++++++++++++++++++++++++++-------
>>  include/scsi/scsi_cmnd.h |    2 +-
>>  include/scsi/scsi_host.h |    8 +++-----
>>  7 files changed, 47 insertions(+), 35 deletions(-)
> 
> looks fine to me though I've not tested it.
> --

I agree, we need more testing. I'm doing that right now.
I've been running with the old patch for ages and also
Pete had a nice heavy load on that code. But this here
was not tried as log. Pete if you have a ready made setup
maybe you can give it a go. Tomo perhaps you can add these
3 patches to your tests.

You need:
   linux-block for-2.6.26 branch - for block support of large commands
   scsi-misc - for iscsi's bidi and extended commands
   these three patches. - scsi varlen support
And then the patch for bsg.

But over all I have audit the code and it looks good, Tomo
was right it was redundant code.

Boaz


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [PATCH 4/4] iscsi_tcp: Enable large command
  2008-04-13 16:41   ` [PATCH 4/4] iscsi_tcp: Enable large command Boaz Harrosh
@ 2008-04-18 17:11     ` Mike Christie
  0 siblings, 0 replies; 77+ messages in thread
From: Mike Christie @ 2008-04-18 17:11 UTC (permalink / raw)
  To: Boaz Harrosh; +Cc: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton

Boaz Harrosh wrote:
> Let through up to the largest command of 260 defined by the scsi standard.
> iscsi core supports this already. Now that the scsi-ml supports it we can
> start using large commands.
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> ---
>  drivers/scsi/iscsi_tcp.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
> index 555f4e3..6500192 100644
> --- a/drivers/scsi/iscsi_tcp.c
> +++ b/drivers/scsi/iscsi_tcp.c
> @@ -1859,7 +1859,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
>  	shost->max_lun = iscsi_max_lun;
>  	shost->max_id = 0;
>  	shost->max_channel = 0;
> -	shost->max_cmd_len = 16;
> +	shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
>  	shost->can_queue = cmds_max;
>  
>  	if (iscsi_host_add(shost, NULL))

This is fine whenever all this stuff gets in.

acked-by: Mike Christie <michaelc@cs.wisc.edu>

^ permalink raw reply	[flat|nested] 77+ messages in thread

end of thread, other threads:[~2008-04-18 17:13 UTC | newest]

Thread overview: 77+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh
2008-03-25 16:22 ` [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
2008-03-25 16:32 ` [PATCH 2/3] block layer varlen-cdb Boaz Harrosh
2008-04-03 16:43   ` James Bottomley
2008-04-03 17:26     ` Benny Halevy
2008-04-03 18:32     ` [PATCH 2/3 ver2] block layer extended-cdb support Boaz Harrosh
2008-04-04 11:46       ` Jens Axboe
2008-04-06  9:35         ` Boaz Harrosh
2008-04-06 11:05           ` Boaz Harrosh
2008-04-07  8:31             ` Jens Axboe
2008-04-12  5:52           ` FUJITA Tomonori
2008-04-13  9:13             ` Boaz Harrosh
2008-04-13 16:17               ` FUJITA Tomonori
2008-04-13 16:50                 ` Boaz Harrosh
2008-04-14  9:49                   ` [PATCH 2/3 ver3] " Boaz Harrosh
2008-04-14 11:04                     ` FUJITA Tomonori
2008-04-14 11:28                       ` Boaz Harrosh
2008-04-14 12:08                         ` FUJITA Tomonori
2008-04-14 12:22                           ` Boaz Harrosh
2008-04-14 11:04                   ` [PATCH 2/3 ver2] " FUJITA Tomonori
2008-04-14 10:50                 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
2008-04-14 10:50                   ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori
2008-04-14 10:50                     ` [PATCH 2/4] block: no need to initialize rq->cmd with blk_get_request FUJITA Tomonori
2008-04-14 10:50                       ` [PATCH 3/4] block: replace sizeof(rq->cmd) with BLK_MAX_CDB FUJITA Tomonori
2008-04-14 10:50                         ` [PATCH 4/4] block: add large command support FUJITA Tomonori
2008-04-14 11:29                           ` Jens Axboe
2008-04-14 12:08                             ` FUJITA Tomonori
2008-04-15 22:50                             ` Bartlomiej Zolnierkiewicz
2008-04-15 22:57                               ` FUJITA Tomonori
2008-04-16  0:22                                 ` Bartlomiej Zolnierkiewicz
2008-04-16  8:33                                 ` Jens Axboe
2008-04-16  9:08                                   ` Boaz Harrosh
2008-04-16  9:42                                     ` Jens Axboe
2008-04-16 22:28                                       ` Bartlomiej Zolnierkiewicz
2008-04-17  3:59                                     ` FUJITA Tomonori
2008-04-17  7:07                                       ` Jens Axboe
2008-04-17 11:55                                         ` Bartlomiej Zolnierkiewicz
2008-04-17 11:58                                           ` Bartlomiej Zolnierkiewicz
2008-04-17 12:07                                         ` FUJITA Tomonori
2008-04-17  4:02                                   ` FUJITA Tomonori
2008-04-14 14:41                           ` Pete Wyckoff
2008-04-14 22:33                             ` FUJITA Tomonori
2008-04-15 13:44                               ` Pete Wyckoff
2008-04-15  7:45                             ` Boaz Harrosh
2008-04-15 10:05                               ` FUJITA Tomonori
2008-04-15  7:29                           ` Jens Axboe
2008-04-14 11:21                   ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori
2008-04-14 11:38                   ` Boaz Harrosh
2008-04-14 12:36                     ` Boaz Harrosh
2008-04-14 13:06                       ` FUJITA Tomonori
2008-04-15 12:24                   ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh
2008-04-15 12:30                     ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
2008-04-15 12:34                     ` [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
2008-04-16  2:09                       ` FUJITA Tomonori
2008-04-16  6:40                         ` Boaz Harrosh
2008-04-16  6:49                           ` [PATCH 2/3 ver2] " Boaz Harrosh
2008-04-17  4:01                           ` [PATCH 2/3] " FUJITA Tomonori
2008-04-17 12:25                             ` [PATCH 2/3 ver3] " Boaz Harrosh
2008-04-17 12:49                               ` Boaz Harrosh
2008-04-17 13:04                               ` FUJITA Tomonori
2008-04-17 13:29                                 ` Boaz Harrosh
2008-04-15 12:37                     ` [PATCH 3/3] iscsi_tcp: Enable large commands Boaz Harrosh
2008-04-15 13:08                       ` James Smart
2008-04-15 13:38                         ` Boaz Harrosh
2008-04-15 13:57                           ` Benny Halevy
2008-04-15 13:46                         ` FUJITA Tomonori
2008-04-13 14:07             ` [PATCH 2/3 ver2] block layer extended-cdb support James Bottomley
2008-04-13 16:17               ` FUJITA Tomonori
2008-03-25 16:36 ` [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
2008-04-03 16:07 ` [PATCHSET 0/3] Is it time for " Boaz Harrosh
2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh
2008-04-13 16:37   ` [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
2008-04-13 16:39   ` [PATCH 2/4] block layer extended-cdb support Boaz Harrosh
2008-04-13 16:39   ` [PATCH 3/4] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh
2008-04-13 16:41   ` [PATCH 4/4] iscsi_tcp: Enable large command Boaz Harrosh
2008-04-18 17:11     ` Mike Christie
     [not found] <20080209193224.GA21448@Chamillionaire.breakpoint.cc>
     [not found] ` <200802100006.11086.bzolnier@gmail.com>
     [not found]   ` <20080210052621.GA22257@infradead.org>
     [not found]     ` <200802101438.46698.bzolnier@gmail.com>
2008-02-10 14:43       ` Current git --> kaboom [bisect] seems IDE related Christoph Hellwig
2008-02-10 15:07         ` Boaz Harrosh
2008-03-25 15:57           ` [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).