Is it time for varlen extended and vendor-specific cdbs
Subsystems (19)
cover Is it time for varlen extended and vendor-specific cdbs
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
PATCH 1/1 Let scsi_cmnd->cmnd use request->cmd buffer
- 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
--- 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(-)
drivers/firewire/fw-sbp2.c +1 -1
@@ -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 =
drivers/s390/scsi/zfcp_dbf.c +1 -1
@@ -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;
drivers/s390/scsi/zfcp_fsf.c +1 -1
@@ -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);
drivers/scsi/53c700.c +3 -3
@@ -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 ; }
drivers/scsi/a100u2w.c +1 -1
@@ -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); }/**
drivers/scsi/gdth.c +1 -1
@@ -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 ;
drivers/scsi/hptiop.c +3 -3
@@ -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 ;
drivers/scsi/ibmvscsi/ibmvscsi.c +1 -1
@@ -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)) {
drivers/scsi/initio.c +1 -1
@@ -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 */
drivers/scsi/qla1280.c +2 -2
@@ -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. */
drivers/scsi/scsi_error.c +8 -6
@@ -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));
drivers/scsi/scsi_lib.c +3 -2
@@ -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);
drivers/scsi/scsi_tgt_lib.c +2 -0
@@ -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 ;
drivers/usb/storage/isd200.c +2 -0
@@ -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;
include/scsi/scsi_cmnd.h +19 -2
@@ -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. */
include/scsi/scsi_eh.h +2 -2
@@ -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; };
Signature · 1 line
1.5.3.3
PATCH 2/3 block layer varlen-cdb
In reply to Boaz Harrosh- 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.
--- block/blk-core.c | 2 ++ include/linux/blkdev.h | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-)
block/blk-core.c +2 -0
@@ -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,
include/linux/blkdev.h +25 -2
@@ -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 )
Signature · 1 line
1.5.3.3
James Bottomley
maintainerRe: [PATCH 2/3] block layer varlen-cdb
Quoted 6 lines · Boaz Harrosh
- add
varlen_cdbandvarlen_cdb_lento 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 afix_lengthcommand up to 16 bytes or avariable_length, larger then 16 bytes, commands but never both, we hold the two types in a union to save space. The
Quoted 8 lines
presence of
varlen_cdb_lenand cmd_len==0 signals avarlen_cdbmode.
- 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 unsignedcmd_lenis 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.
Quoted 11 lines
Signed-off-by Boaz Harrosh <[email protected]>--- block/blk-core.c | 2 ++ include/linux/blkdev.h | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-)block/blk-core.c +0
-0
block/blk-core.c void rq_init(struct request_queue *q, struct request *rq) · line 145
Quoted 5 lines
block/blk-core.c +2
-0@@ -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/
Quoted 11 lines
block/blk-core.c +0
-0} static void req_bio_endio(struct request *rq, struct bio *bio,include/linux/blkdev.h +0
-0@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */
include/linux/blkdev.h struct request { · line 223
Quoted 10 lines
include/linux/blkdev.h +8
-2-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/
Quoted 13 lines
include/linux/blkdev.h +6
-0+ };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;
include/linux/blkdev.h enum { · line 508
Quoted 10 lines
include/linux/blkdev.h +10
-0+} + +/* 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).
include/linux/blkdev.h enum { · line 512
Quoted 3 lines
include/linux/blkdev.h +0
-0static inline int blk_queue_full (struct request_queue *q,int rw) {if (rw ==READ )
James
Re: [PATCH 2/3] block layer varlen-cdb
Quoted 27 lines · James Bottomley
Quoted 6 lines · Boaz Harrosh
- add
varlen_cdbandvarlen_cdb_lento 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 afix_lengthcommand up to 16 bytes or avariable_length, larger then 16 bytes, commands but never both, we hold the two types in a union to save space. TheQuoted 8 lines
presence of
varlen_cdb_lenand cmd_len==0 signals avarlen_cdbmode.
- 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 unsignedcmd_lenis 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.Quoted 6 lines
Signed-off-by Boaz Harrosh <[email protected]>--- block/blk-core.c | 2 ++ include/linux/blkdev.h | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-)
Quoted 12 lines
block/blk-core.c void rq_init(struct request_queue *q, struct request *rq) · line 145
Quoted 10 lines
block/blk-core.c +2
-0@@ -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).
Quoted 49 lines
Quoted 12 lines
block/blk-core.c +0
-0} static void req_bio_endio(struct request *rq, struct bio *bio,include/linux/blkdev.h +0
-0@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ include/linux/blkdev.h struct request { · line 223
Quoted 10 lines
include/linux/blkdev.h +8
-2-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/
Quoted 13 lines
include/linux/blkdev.h +6
-0+ };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;include/linux/blkdev.h enum { · line 508
Quoted 10 lines
include/linux/blkdev.h +10
-0+} + +/* 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 ; +}
Quoted 7 lines
These accessors look wrong ... I think what we want is
rq_get_cdbandrq_set_cdbthat handles both <=BLK_MAX_CDBby simply a memcpy and >BLK_MAX_CDBby setting up thelarge_cdbpointer. That way we can accessorize the whole lot and the drivers don't have to care about whatBLK_MAX_CDBis 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
Quoted 12 lines
include/linux/blkdev.h enum { · line 512
Quoted 4 lines
include/linux/blkdev.h +0
-0static 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 2/3 block layer extended-cdb support
In reply to James BottomleyQuoted 96 lines · James Bottomley
Quoted 6 lines · Boaz Harrosh
- add
varlen_cdbandvarlen_cdb_lento 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 afix_lengthcommand up to 16 bytes or avariable_length, larger then 16 bytes, commands but never both, we hold the two types in a union to save space. TheQuoted 8 lines
presence of
varlen_cdb_lenand cmd_len==0 signals avarlen_cdbmode.
- 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 unsignedcmd_lenis 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.Quoted 11 lines
Signed-off-by Boaz Harrosh <[email protected]>--- block/blk-core.c | 2 ++ include/linux/blkdev.h | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-)block/blk-core.c +0
-0block/blk-core.c void rq_init(struct request_queue *q, struct request *rq) · line 145
Quoted 5 lines
block/blk-core.c +2
-0@@ -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/
Quoted 11 lines
block/blk-core.c +0
-0} static void req_bio_endio(struct request *rq, struct bio *bio,include/linux/blkdev.h +0
-0@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ include/linux/blkdev.h struct request { · line 223
Quoted 10 lines
include/linux/blkdev.h +8
-2-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/
Quoted 13 lines
include/linux/blkdev.h +6
-0+ };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;include/linux/blkdev.h enum { · line 508
Quoted 10 lines
include/linux/blkdev.h +10
-0+} + +/* 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_cdbandrq_set_cdbthat handles both <=BLK_MAX_CDBby simply a memcpy and >BLK_MAX_CDBby setting up thelarge_cdbpointer. That way we can accessorize the whole lot and the drivers don't have to care about whatBLK_MAX_CDBis set to (it simply becomes an internal convenience of block ... and possibly allows us to eliminate the request carries command data entirely).
Quoted 7 lines
include/linux/blkdev.h enum { · line 511
Quoted 3 lines
include/linux/blkdev.h +0
-0static 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
---
Quoted 1 line
From
1da591a5ef9697f37604721bfe437a2609bb8217Mon Sep 17 00:00:00 2001
From: Boaz Harrosh <[email protected]>
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.
--- block/blk-core.c | 2 ++ include/linux/blkdev.h | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-)
block/blk-core.c +2 -0
@@ -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,
include/linux/blkdev.h +39 -2
53 lines not on this page · raw message
Signature · 1 line
1.5.3.3
Re: [PATCH 2/3 ver2] block layer extended-cdb support
Quoted 10 lines · Boaz Harrosh
static void req_bio_endio(struct request *rq, struct bio *bio,
include/linux/blkdev.h +0
-1@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ -unsigned int cmd_len;
include/linux/blkdev.h struct request { · line 224
Quoted 10 lines
include/linux/blkdev.h +9
-1-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.
Signature · 1 line
Jens Axboe
Re: [PATCH 2/3 ver2] block layer extended-cdb support
Quoted 37 lines · Jens Axboe
Quoted 10 lines · Boaz Harrosh
static void req_bio_endio(struct request *rq, struct bio *bio,
include/linux/blkdev.h +0
-1@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ -unsigned int cmd_len;include/linux/blkdev.h struct request { · line 224
Quoted 10 lines
include/linux/blkdev.h +9
-1-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()dorq->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
Quoted 8 lines
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()plusrq_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
Re: [PATCH 2/3 ver2] block layer extended-cdb support
Quoted 55 lines · Boaz Harrosh
Quoted 36 lines · Jens Axboe
Quoted 10 lines · Boaz Harrosh
static void req_bio_endio(struct request *rq, struct bio *bio,
include/linux/blkdev.h +0
-1@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ -unsigned int cmd_len;include/linux/blkdev.h struct request { · line 224
Quoted 10 lines
include/linux/blkdev.h +9
-1-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()dorq->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 beQuoted 8 lines
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()plusrq_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.
Quoted 2 lines
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
Re: [PATCH 2/3 ver2] block layer extended-cdb support
Quoted 71 lines · Boaz Harrosh
Quoted 55 lines · Boaz Harrosh
Quoted 36 lines · Jens Axboe
Quoted 10 lines · Boaz Harrosh
static void req_bio_endio(struct request *rq, struct bio *bio,
include/linux/blkdev.h +0
-1@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ -unsigned int cmd_len;include/linux/blkdev.h struct request { · line 224
Quoted 10 lines
include/linux/blkdev.h +9
-1-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()dorq->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 beQuoted 8 lines
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()plusrq_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.
Quoted 2 lines
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).
Quoted 2 lines
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.
Signature · 1 line
Jens Axboe
Re: [PATCH 2/3 ver2] block layer extended-cdb support
In reply to Boaz HarroshQuoted 47 lines · On Sun, 06 Apr 2008 12:35:04 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 37 lines · Jens Axboe
Quoted 10 lines · Boaz Harrosh
static void req_bio_endio(struct request *rq, struct bio *bio,
include/linux/blkdev.h +0
-1@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ -unsigned int cmd_len;include/linux/blkdev.h struct request { · line 224
Quoted 10 lines
include/linux/blkdev.h +9
-1-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()dorq->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 beQuoted 8 lines
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()plusrq_get_cdb_len()could just go away.
Quoted 8 lines
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?
Re: [PATCH 2/3 ver2] block layer extended-cdb support
Quoted 57 lines · FUJITA Tomonori
Quoted 45 lines · On Sun, 06 Apr 2008 12:35:04 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 36 lines · Jens Axboe
Quoted 10 lines · Boaz Harrosh
static void req_bio_endio(struct request *rq, struct bio *bio,
include/linux/blkdev.h +0
-1@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ -unsigned int cmd_len;include/linux/blkdev.h struct request { · line 224
Quoted 10 lines
include/linux/blkdev.h +9
-1-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()dorq->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 beQuoted 8 lines
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()plusrq_get_cdb_len()could just go away.Quoted 8 lines
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.
Quoted 4 lines
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
Re: [PATCH 2/3 ver2] block layer extended-cdb support
Quoted 58 lines · On Sun, 13 Apr 2008 12:13:18 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 57 lines · FUJITA Tomonori
Quoted 53 lines · On Sun, 06 Apr 2008 12:35:04 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 36 lines · Jens Axboe
Quoted 10 lines · Boaz Harrosh
static void req_bio_endio(struct request *rq, struct bio *bio,
include/linux/blkdev.h +0
-1@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ -unsigned int cmd_len;include/linux/blkdev.h struct request { · line 224
Quoted 10 lines
include/linux/blkdev.h +9
-1-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()dorq->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 beQuoted 8 lines
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()plusrq_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.
Quoted 8 lines
Quoted 4 lines
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.
Quoted 4 lines
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.
Re: [PATCH 2/3 ver2] block layer extended-cdb support
Quoted 83 lines · FUJITA Tomonori
Quoted 57 lines · On Sun, 13 Apr 2008 12:13:18 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 56 lines · FUJITA Tomonori
Quoted 53 lines · On Sun, 06 Apr 2008 12:35:04 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 36 lines · Jens Axboe
Quoted 10 lines · Boaz Harrosh
static void req_bio_endio(struct request *rq, struct bio *bio,
include/linux/blkdev.h +0
-1@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ -unsigned int cmd_len;include/linux/blkdev.h struct request { · line 224
Quoted 10 lines
include/linux/blkdev.h +9
-1-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()dorq->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 beQuoted 8 lines
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()plusrq_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.
Quoted 7 lines
Quoted 4 lines
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.
Quoted 4 lines
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 usevarlen_cdb_len?
Quoted 8 lines
For me, as Jens proposed, having only
cmd_lenis 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
PATCH 2/3 block layer extended-cdb support
Quoted 26 lines · Boaz Harrosh
Quoted 9 lines · FUJITA Tomonori
On Sun, 13 Apr 2008 12:13:18 +0300
Boaz Harrosh <[email protected]> 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 usevarlen_cdb_len?Quoted 8 lines
For me, as Jens proposed, having only
cmd_lenis 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.
Quoted 8 lines
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 <[email protected]>
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.
--- block/blk-core.c | 2 ++ include/linux/blkdev.h | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletions(-)
block/blk-core.c +2 -0
@@ -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,
include/linux/blkdev.h +24 -1
@@ -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 )
Signature · 1 line
1.5.3.3
Re: [PATCH 2/3 ver3] block layer extended-cdb support
Quoted 33 lines · On Mon, 14 Apr 2008 12:49:49 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 32 lines · Boaz Harrosh
Quoted 9 lines · FUJITA Tomonori
On Sun, 13 Apr 2008 12:13:18 +0300
Boaz Harrosh <[email protected]> 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 usevarlen_cdb_len?Quoted 8 lines
For me, as Jens proposed, having only
cmd_lenis 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++
Quoted 6 lines
Quoted 2 lines
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 haveBLK_MAX_CDBright 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.
Quoted 3 lines
But please note!!!
I think having onecmd_lenis 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.
Re: [PATCH 2/3 ver3] block layer extended-cdb support
Quoted 49 lines · FUJITA Tomonori
Quoted 32 lines · On Mon, 14 Apr 2008 12:49:49 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 31 lines · Boaz Harrosh
Quoted 9 lines · FUJITA Tomonori
On Sun, 13 Apr 2008 12:13:18 +0300
Boaz Harrosh <[email protected]> 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 usevarlen_cdb_len?Quoted 8 lines
For me, as Jens proposed, having only
cmd_lenis 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++
Quoted 6 lines
Quoted 2 lines
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 haveBLK_MAX_CDBright 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.
Quoted 6 lines
Quoted 3 lines
But please note!!!
I think having onecmd_lenis 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
Re: [PATCH 2/3 ver3] block layer extended-cdb support
Quoted 57 lines · On Mon, 14 Apr 2008 14:28:45 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 49 lines · FUJITA Tomonori
Quoted 32 lines · On Mon, 14 Apr 2008 12:49:49 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 31 lines · Boaz Harrosh
Quoted 9 lines · FUJITA Tomonori
On Sun, 13 Apr 2008 12:13:18 +0300
Boaz Harrosh <[email protected]> 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 usevarlen_cdb_len?Quoted 8 lines
For me, as Jens proposed, having only
cmd_lenis 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++
Quoted 6 lines
Quoted 2 lines
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 haveBLK_MAX_CDBright 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.Quoted 6 lines
Quoted 3 lines
But please note!!!
I think having onecmd_lenis 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.
Quoted 10 lines
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?
Re: [PATCH 2/3 ver3] block layer extended-cdb support
Quoted 77 lines · FUJITA Tomonori
Quoted 54 lines · On Mon, 14 Apr 2008 14:28:45 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 48 lines · FUJITA Tomonori
Quoted 32 lines · On Mon, 14 Apr 2008 12:49:49 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 31 lines · Boaz Harrosh
Quoted 9 lines · FUJITA Tomonori
On Sun, 13 Apr 2008 12:13:18 +0300
Boaz Harrosh <[email protected]> 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 usevarlen_cdb_len?Quoted 8 lines
For me, as Jens proposed, having only
cmd_lenis 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++
Quoted 6 lines
Quoted 2 lines
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 haveBLK_MAX_CDBright 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.Quoted 5 lines
Quoted 3 lines
But please note!!!
I think having onecmd_lenis 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.
Quoted 10 lines
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.
Quoted 5 lines
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
Re: [PATCH 2/3 ver2] block layer extended-cdb support
In reply to Boaz HarroshQuoted 93 lines · On Sun, 13 Apr 2008 19:50:26 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 83 lines · FUJITA Tomonori
Quoted 57 lines · On Sun, 13 Apr 2008 12:13:18 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 56 lines · FUJITA Tomonori
Quoted 53 lines · On Sun, 06 Apr 2008 12:35:04 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 36 lines · Jens Axboe
Quoted 10 lines · Boaz Harrosh
static void req_bio_endio(struct request *rq, struct bio *bio,
include/linux/blkdev.h +0
-1@@ -213,8 +213,15 @@ struct request {/* * when request is used as a packet command carrier */ -unsigned int cmd_len;include/linux/blkdev.h struct request { · line 224
Quoted 10 lines
include/linux/blkdev.h +9
-1-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()dorq->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 beQuoted 8 lines
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()plusrq_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.
Quoted 7 lines
Quoted 4 lines
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.
Quoted 4 lines
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 usevarlen_cdb_len?Quoted 8 lines
For me, as Jens proposed, having only
cmd_lenis 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.
--
Quoted 6 lines
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.
Quoted 11 lines
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
cover add large command support to the block layer
In reply to FUJITA TomonoriThis 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:
Quoted 5 lines
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.
PATCH 1/4 block: no need to initialize rq->cmd in prepare_flush_fn hook
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.
--- drivers/block/ps3disk.c | 1 - drivers/scsi/sd.c | 1 - 2 files changed, 0 insertions(+), 2 deletions(-)
drivers/block/ps3disk.c +0 -1
@@ -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 ; }
drivers/scsi/sd.c +0 -1
@@ -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 ;
Signature · 1 line
1.5.4.2
PATCH 2/4 block: no need to initialize rq->cmd with blk_get_request
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.
--- 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(-)
block/scsi_ioctl.c +0 -3
@@ -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 ;
drivers/block/pktcdvd.c +0 -2
@@ -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 ;
drivers/cdrom/cdrom.c +0 -1
@@ -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 ;
drivers/md/dm-emc.c +0 -2
@@ -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 ;
drivers/md/dm-mpath-hp-sw.c +0 -1
@@ -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 ]);
drivers/md/dm-mpath-rdac.c +0 -1
@@ -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 ;
Signature · 1 line
1.5.4.2
PATCH 3/4 block: replace sizeof(rq->cmd) with BLK_MAX_CDB
This is a preparation for changing rq->cmd from the static array to a pointer.
--- 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(-)
block/blk-core.c +2 -2
@@ -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" ); }
drivers/ide/ide-cd.c +2 -2
@@ -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 ;
drivers/ide/ide-cd_verbose.c +1 -1
@@ -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" ); }
Signature · 1 line
1.5.4.2
PATCH 4/4 block: add large command support
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.
--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)
block/blk-core.c +1 -0
@@ -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 ;
drivers/ide/ide-io.c +1 -0
@@ -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);
include/linux/blkdev.h +10 -2
@@ -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);
Signature · 1 line
1.5.4.2
Re: [PATCH 4/4] block: add large command support
Quoted 56 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +1
-0@@ -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);include/linux/blkdev.h +3
-2@@ -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 */
include/linux/blkdev.h static inline void put_dev_sector(Sector p) · line 822
Quoted 10 lines
include/linux/blkdev.h +7
-0@@ -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.
Signature · 1 line
Jens Axboe
Re: [PATCH 4/4] block: add large command support
Quoted 60 lines · On Mon, 14 Apr 2008 13:29:20 +0200 Jens Axboe <[email protected]> wrote:
Quoted 59 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +1
-0@@ -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);include/linux/blkdev.h +3
-2@@ -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); }
Quoted 10 lines
include/linux/blkdev.h static inline void put_dev_sector(Sector p) · line 822
Quoted 7 lines
include/linux/blkdev.h +7
-0+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.
Re: [PATCH 4/4] block: add large command support
In reply to Jens AxboeHi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0
Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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);
}Quoted 6 lines
Quoted 6 lines
drivers/ide/ide-io.c +0
-0EXPORT_SYMBOL (ide_init_drive_cmd);include/linux/blkdev.h +0
-0@@ -215,8 +215,9 @@ struct request {
Quoted 8 lines
include/linux/blkdev.h struct request { · line 220
Quoted 8 lines
include/linux/blkdev.h +3
-2/* * 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). ]
Quoted 6 lines
Quoted 6 lines
include/linux/blkdev.h +0
-0unsigned 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); }
Quoted 10 lines
include/linux/blkdev.h static inline void put_dev_sector(Sector p) · line 822
Quoted 7 lines
include/linux/blkdev.h +7
-0+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
Re: [PATCH 4/4] block: add large command support
Quoted 45 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.
Quoted 11 lines
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.corREQ_TYPE_SENSEinide-cd.c:
Thanks, I overlooked this. As I did for ide_init_drive_cmd, we need:
+ rq->cmd = rq->__cmd;
Quoted 16 lines
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;
Quoted 7 lines
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).
Quoted 17 lines
Quoted 6 lines
Quoted 6 lines
drivers/ide/ide-io.c +0
-0EXPORT_SYMBOL (ide_init_drive_cmd);include/linux/blkdev.h +0
-0@@ -215,8 +215,9 @@ struct request {Quoted 8 lines
include/linux/blkdev.h struct request { · line 220
Quoted 8 lines
include/linux/blkdev.h +3
-2/* * 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:
Quoted 8 lines
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.
Quoted 5 lines
- unmerged code from other trees (i.e., I _have_ WIP patches mapping
REQ_TYPE_TASKFILErequests ontorq->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.
Quoted 6 lines
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
Quoted 26 lines
Quoted 6 lines
Quoted 6 lines
include/linux/blkdev.h +0
-0unsigned 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); }Quoted 10 lines
include/linux/blkdev.h static inline void put_dev_sector(Sector p) · line 822
Quoted 7 lines
include/linux/blkdev.h +7
-0+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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/4] block: add large command support
Quoted 48 lines · FUJITA Tomonori
Quoted 45 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 6 lines
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly if you want.
I would love to see the patches.
Quoted 36 lines
Quoted 11 lines
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.corREQ_TYPE_SENSEinide-cd.c:Thanks, I overlooked this. As I did for
ide_init_drive_cmd, we need:(quoted diff) +1
-0+ rq->cmd = rq->__cmd;Quoted 20 lines
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;
Quoted 8 lines
Quoted 5 lines
/* 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).
Quoted 20 lines
Quoted 20 lines
Quoted 6 lines
Quoted 6 lines
drivers/ide/ide-io.c +0
-0EXPORT_SYMBOL (ide_init_drive_cmd);include/linux/blkdev.h +0
-0@@ -215,8 +215,9 @@ struct request {Quoted 8 lines
include/linux/blkdev.h struct request { · line 220
Quoted 8 lines
include/linux/blkdev.h +3
-2/* * 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).
Quoted 7 lines
Quoted 5 lines
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. ]
Quoted 9 lines
Quoted 5 lines
- unmerged code from other trees (i.e., I _have_ WIP patches mapping
REQ_TYPE_TASKFILErequests ontorq->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.
Quoted 10 lines
Quoted 6 lines
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:
If you audit+fixup IDE I'm also fine with non-"hack" solution.
Thanks,
Bart
Re: [PATCH 4/4] block: add large command support
In reply to FUJITA TomonoriQuoted 48 lines · FUJITA Tomonori
Quoted 45 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 8 lines
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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_requestproperly 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.
Signature · 1 line
Jens Axboe
Re: [PATCH 4/4] block: add large command support
Quoted 53 lines · Jens Axboe
Quoted 52 lines · FUJITA Tomonori
Quoted 43 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.
Quoted 7 lines
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly 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 amemset()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 <[email protected]>
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.
--- block/blk-core.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-)
block/blk-core.c +2 -20
@@ -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)
Signature · 1 line
1.5.3.3
Re: [PATCH 4/4] block: add large command support
Quoted 127 lines · Boaz Harrosh
Quoted 53 lines · Jens Axboe
Quoted 52 lines · FUJITA Tomonori
Quoted 43 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.Quoted 7 lines
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly 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 amemset()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 <[email protected]>
Date: Wed, 16 Apr 2008 12:05:33 +0300
Subject: [PATCH] Initialize all members of struct request inrq_initBefore, 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 <[email protected]>--- block/blk-core.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-)block/blk-core.c +2
-20@@ -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)Signature · 1 line
1.5.3.3
Totally agree, if we expand rq_init() to all users (including on stack), this must be included as well.
Signature · 1 line
Jens Axboe
Re: [PATCH 4/4] block: add large command support
Quoted 55 lines · Jens Axboe
Quoted 54 lines · Boaz Harrosh
Quoted 53 lines · Jens Axboe
Quoted 52 lines · FUJITA Tomonori
Quoted 43 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly 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 amemset()anyway.
Sounds OK to me.
Quoted 60 lines
Quoted 60 lines
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 <[email protected]>
Date: Wed, 16 Apr 2008 12:05:33 +0300
Subject: [PATCH] Initialize all members of struct request inrq_initBefore, 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 <[email protected]>--- block/blk-core.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-)block/blk-core.c +2
-20@@ -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);
Quoted 8 lines
Quoted 5 lines
block/blk-core.c +0
-0static void req_bio_endio (struct request *rq,struct bio *bio,unsigned int nbytes,int error)Signature · 1 line
1.5.3.3Totally 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
Re: [PATCH 4/4] block: add large command support
In reply to Boaz HarroshQuoted 86 lines · On Wed, 16 Apr 2008 12:08:25 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 53 lines · Jens Axboe
Quoted 52 lines · FUJITA Tomonori
Quoted 43 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.Quoted 7 lines
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly 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 amemset()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 <[email protected]>
Date: Wed, 16 Apr 2008 12:05:33 +0300
Subject: [PATCH] Initialize all members of struct request inrq_initBefore, 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 <[email protected]>--- block/blk-core.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-)block/blk-core.c +0
-0
block/blk-core.c EXPORT_SYMBOL(blk_get_backing_dev_info); · line 116
Quoted 4 lines
block/blk-core.c +1
-0@@ -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.
Quoted 41 lines
block/blk-core.c +1
-20INIT_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)Signature · 6 lines
1.5.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/4] block: add large command support
Quoted 96 lines · FUJITA Tomonori
Quoted 86 lines · On Wed, 16 Apr 2008 12:08:25 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 53 lines · Jens Axboe
Quoted 52 lines · FUJITA Tomonori
Quoted 43 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.Quoted 7 lines
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly 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 amemset()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 <[email protected]>
Date: Wed, 16 Apr 2008 12:05:33 +0300
Subject: [PATCH] Initialize all members of struct request inrq_initBefore, 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 <[email protected]>--- block/blk-core.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-)block/blk-core.c +0
-0block/blk-core.c EXPORT_SYMBOL(blk_get_backing_dev_info); · line 116
Quoted 4 lines
block/blk-core.c +1
-0@@ -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_initcomment says:
Quoted 6 lines
/*
* We can't justmemset()the structure, since the allocation path
* already stored some information in the request.
*/I think that we can't initialize
rq->cmd_flagshere.
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.
Signature · 1 line
Jens Axboe
Re: [PATCH 4/4] block: add large command support
Quoted 103 lines · Jens Axboe
Quoted 101 lines · FUJITA Tomonori
Quoted 86 lines · On Wed, 16 Apr 2008 12:08:25 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 53 lines · Jens Axboe
Quoted 52 lines · FUJITA Tomonori
Quoted 43 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.Quoted 7 lines
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly 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 amemset()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 <[email protected]>
Date: Wed, 16 Apr 2008 12:05:33 +0300
Subject: [PATCH] Initialize all members of struct request inrq_initBefore, 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 <[email protected]>--- block/blk-core.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-)block/blk-core.c +0
-0block/blk-core.c EXPORT_SYMBOL(blk_get_backing_dev_info); · line 116
Quoted 4 lines
block/blk-core.c +1
-0@@ -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_initcomment says:/*
* We can't justmemset()the structure, since the allocation path
* already stored some information in the request.
*/
Quoted 5 lines
Quoted 1 line
I think that we can't initialize
rq->cmd_flagshere.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
Re: [PATCH 4/4] block: add large command support
Quoted 107 lines · Bartlomiej Zolnierkiewicz
Quoted 105 lines · Jens Axboe
Quoted 102 lines · FUJITA Tomonori
Quoted 86 lines · On Wed, 16 Apr 2008 12:08:25 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 53 lines · Jens Axboe
Quoted 52 lines · FUJITA Tomonori
Quoted 43 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.Quoted 7 lines
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly 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 amemset()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 <[email protected]>
Date: Wed, 16 Apr 2008 12:05:33 +0300
Subject: [PATCH] Initialize all members of struct request inrq_initBefore, 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 <[email protected]>--- block/blk-core.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-)block/blk-core.c +0
-0block/blk-core.c EXPORT_SYMBOL(blk_get_backing_dev_info); · line 116
Quoted 4 lines
block/blk-core.c +1
-0@@ -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_initcomment says:/*
* We can't justmemset()the structure, since the allocation path
* already stored some information in the request.
*/I think that we can't initialize
rq->cmd_flagshere.
Quoted 8 lines
Quoted 3 lines
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_flagsfromblk_alloc_request()to the callers (this is onlyget_request()ATM)
ditto for elv_set_request() call
Quoted 2 lines
- re-order setting
rq->cmd_flagsvs callingrq_init()inget_request(),queue_lfush()andstart_ordered()
Re: [PATCH 4/4] block: add large command support
In reply to Jens AxboeQuoted 102 lines · On Thu, 17 Apr 2008 09:07:05 +0200 Jens Axboe <[email protected]> wrote:
Quoted 101 lines · FUJITA Tomonori
Quoted 86 lines · On Wed, 16 Apr 2008 12:08:25 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 53 lines · Jens Axboe
Quoted 52 lines · FUJITA Tomonori
Quoted 43 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.Quoted 7 lines
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly 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 amemset()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 <[email protected]>
Date: Wed, 16 Apr 2008 12:05:33 +0300
Subject: [PATCH] Initialize all members of struct request inrq_initBefore, 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 <[email protected]>--- block/blk-core.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-)block/blk-core.c +0
-0block/blk-core.c EXPORT_SYMBOL(blk_get_backing_dev_info); · line 116
Quoted 4 lines
block/blk-core.c +1
-0@@ -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_initcomment says:/*
* We can't justmemset()the structure, since the allocation path
* already stored some information in the request.
*/
Quoted 5 lines
Quoted 1 line
I think that we can't initialize
rq->cmd_flagshere.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 <[email protected]>
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.
--- 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(-)
drivers/block/nbd.c +3 -0
@@ -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);
drivers/block/paride/pd.c +1 -0
@@ -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 ;
drivers/ide/ide-tape.c +1 -0
@@ -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; }
drivers/ide/ide-taskfile.c +1 -2
@@ -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;
drivers/ide/ide.c +2 -0
@@ -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 ;
drivers/scsi/scsi_error.c +1 -0
@@ -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));
Signature · 1 line
1.5.4.2
Re: [PATCH 4/4] block: add large command support
In reply to Jens AxboeQuoted 56 lines · On Wed, 16 Apr 2008 10:33:06 +0200 Jens Axboe <[email protected]> wrote:
Quoted 55 lines · FUJITA Tomonori
Quoted 45 lines · On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz…
Hi,
Quoted 30 lines · Jens Axboe
Quoted 29 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>--- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-)block/blk-core.c +1
-0@@ -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 ;drivers/ide/ide-io.c +0
-0Quoted 8 lines
drivers/ide/ide-io.c void ide_init_drive_cmd (struct request *rq) · line 1599
Quoted 8 lines
drivers/ide/ide-io.c +1
-0@@ -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:
Quoted 2 lines
Please think about all _static_/dynamic allocations of 'struct request' used together with
REQ_TYPE_SPECIALetc., 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.
Quoted 6 lines
Quoted 1 line
I try to convert ide to use
blk_get_requestproperly 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 amemset()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).
Re: [PATCH 4/4] block: add large command support
In reply to FUJITA Tomonori[email protected] wrote on Mon, 14 Apr 2008 19:50 +0900:
Quoted 9 lines
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>
[..]
Quoted 17 lines
include/linux/blkdev.h +3
-2@@ -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 */
include/linux/blkdev.h static inline void put_dev_sector(Sector p) · line 821
Quoted 9 lines
include/linux/blkdev.h +6
-0@@ -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
Re: [PATCH 4/4] block: add large command support
Quoted 60 lines · On Mon, 14 Apr 2008 10:41:54 -0400 Pete Wyckoff <[email protected]> wrote:
[email protected] wrote on Mon, 14 Apr 2008 19:50 +0900:
Quoted 9 lines
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>[..]
Quoted 17 lines
include/linux/blkdev.h +3
-2@@ -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 */ include/linux/blkdev.h static inline void put_dev_sector(Sector p) · line 821
Quoted 9 lines
include/linux/blkdev.h +6
-0@@ -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);
Quoted 6 lines
Could use (
rq->cmd!=rq->__cmd) instead, but nothing had better ever touchrq->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.
Quoted 3 lines
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.
Quoted 5 lines
Boaz's concern about big
rq->cmd_lenstill 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.
Quoted 3 lines
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,
Re: [PATCH 4/4] block: add large command support
[email protected] wrote on Tue, 15 Apr 2008 07:33 +0900:
Quoted 4 lines
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
Re: [PATCH 4/4] block: add large command support
In reply to Pete WyckoffQuoted 54 lines · Pete Wyckoff
[email protected] wrote on Mon, 14 Apr 2008 19:50 +0900:
Quoted 9 lines
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>[..]
Quoted 17 lines
include/linux/blkdev.h +3
-2@@ -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 */ include/linux/blkdev.h static inline void put_dev_sector(Sector p) · line 821
Quoted 9 lines
include/linux/blkdev.h +6
-0@@ -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);
Quoted 9 lines
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 touchrq->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.
Quoted 14 lines
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_lenstill 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.
Quoted 4 lines
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.
Quoted 2 lines
-- Pete--
Boaz
Re: [PATCH 4/4] block: add large command support
Quoted 61 lines · On Tue, 15 Apr 2008 10:45:52 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 60 lines · Pete Wyckoff
[email protected] wrote on Mon, 14 Apr 2008 19:50 +0900:
Quoted 9 lines
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.Signed-off-by FUJITA Tomonori <[email protected]>Cc Jens Axboe <[email protected]>[..]
Quoted 17 lines
include/linux/blkdev.h +3
-2@@ -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 */ include/linux/blkdev.h static inline void put_dev_sector(Sector p) · line 821
Quoted 9 lines
include/linux/blkdev.h +6
-0@@ -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);
Quoted 7 lines
Quoted 3 lines
Could use (
rq->cmd!=rq->__cmd) instead, but nothing had better ever touchrq->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.
Quoted 4 lines
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.
Jens Axboe
AppliedRe: [PATCH 4/4] block: add large command support
In reply to FUJITA TomonoriQuoted 6 lines · FUJITA Tomonori
This patch changes
rq->cmdfrom 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_initsetsrq->cmdpointer to the static array.
I applied 1-4, thanks.
Signature · 1 line
Jens Axboe
Re: [PATCH 0/4] add large command support to the block layer
In reply to FUJITA TomonoriQuoted 1 line · On Mon, 14 Apr 2008 19:50:33 +0900 FUJITA Tomonori…
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.
Re: [PATCH 0/4] add large command support to the block layer
In reply to FUJITA TomonoriQuoted 30 lines · 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_initsetsrq->cmdpointer to the static array. In short,rq_init()does
rq->cmd=rq->__cmd;So we can access to
rq->cmdandrq->cmd_lenas before.Boaz argues that having single
cmd_lenis dangerous:Quoted 5 lines
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->cmdfrom 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.
Quoted 7 lines
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 useblk_get_requestproperly.
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
Re: [PATCH 0/4] add large command support to the block layer
Quoted 38 lines · Boaz Harrosh
Quoted 29 lines · 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_initsetsrq->cmdpointer to the static array. In short,rq_init()does
rq->cmd=rq->__cmd;So we can access to
rq->cmdandrq->cmd_lenas before.Boaz argues that having single
cmd_lenis dangerous:Quoted 5 lines
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->cmdfrom 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.Quoted 7 lines
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 useblk_get_requestproperly.
Quoted 6 lines
I still think that my last patch with one
cmd_lenand 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.
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
Re: [PATCH 0/4] add large command support to the block layer
Quoted 81 lines · On Mon, 14 Apr 2008 15:22:21 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 80 lines · FUJITA Tomonori
Quoted 54 lines · On Mon, 14 Apr 2008 14:28:45 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 48 lines · FUJITA Tomonori
Quoted 32 lines · On Mon, 14 Apr 2008 12:49:49 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 31 lines · Boaz Harrosh
Quoted 9 lines · FUJITA Tomonori
On Sun, 13 Apr 2008 12:13:18 +0300
Boaz Harrosh <[email protected]> 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 usevarlen_cdb_len?Quoted 8 lines
For me, as Jens proposed, having only
cmd_lenis 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++
Quoted 6 lines
Quoted 2 lines
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 haveBLK_MAX_CDBright 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.Quoted 5 lines
Quoted 3 lines
But please note!!!
I think having onecmd_lenis 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.
Quoted 10 lines
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.
Quoted 8 lines
Quoted 2 lines
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.
Quoted 1 line
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.
cover scsi: variable-length CDBs support
In reply to FUJITA TomonoriBased 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
PATCH 1/3 Let scsi_cmnd->cmnd use request->cmd buffer
- 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
--- 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(-)
drivers/firewire/fw-sbp2.c +1 -1
@@ -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 =
drivers/s390/scsi/zfcp_dbf.c +1 -1
@@ -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;
drivers/s390/scsi/zfcp_fsf.c +1 -1
@@ -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);
drivers/scsi/53c700.c +3 -3
@@ -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 ; }
drivers/scsi/a100u2w.c +1 -1
@@ -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); }/**
drivers/scsi/gdth.c +1 -1
@@ -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 ;
drivers/scsi/hptiop.c +3 -3
@@ -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 ;
drivers/scsi/ibmvscsi/ibmvscsi.c +1 -1
@@ -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)) {
drivers/scsi/initio.c +1 -1
@@ -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 */
drivers/scsi/qla1280.c +2 -2
@@ -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. */
drivers/scsi/scsi_error.c +8 -6
@@ -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));
drivers/scsi/scsi_lib.c +3 -2
@@ -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);
drivers/scsi/scsi_tgt_lib.c +2 -0
@@ -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 ;
drivers/usb/storage/isd200.c +2 -0
@@ -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;
include/scsi/scsi_cmnd.h +19 -2
@@ -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. */
include/scsi/scsi_eh.h +2 -2
@@ -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; };
Signature · 1 line
1.5.3.3
PATCH 2/3 scsi: varlen extended and vendor-specific cdbs
In reply to Boaz HarroshAdd 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.
--- 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(-)
block/scsi_ioctl.c +2 -3
@@ -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>
drivers/scsi/constants.c +3 -7
@@ -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]);
drivers/scsi/scsi.c +11 -11
@@ -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);
drivers/scsi/scsi_lib.c +6 -2
@@ -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;
include/scsi/scsi.h +33 -7
@@ -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. */
include/scsi/scsi_cmnd.h +1 -1
@@ -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 */
include/scsi/scsi_host.h +3 -5
@@ -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;
Signature · 1 line
1.5.3.3
Re: [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs
Quoted 114 lines · On Tue, 15 Apr 2008 15:34:47 +0300 Boaz Harrosh <[email protected]> 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_lenmembers' type to short as char is not enough.Signed-off-by Boaz Harrosh <[email protected]>Signed-off-by Benny Halevy <[email protected]>--- 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(-)block/scsi_ioctl.c +2
-3@@ -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> drivers/scsi/constants.c +3
-7@@ -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]);drivers/scsi/scsi.c +1
-9@@ -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 )) {
drivers/scsi/scsi.c int scsi_dispatch_cmd(struct scsi_cmnd *cmd) · line 700
Quoted 9 lines
drivers/scsi/scsi.c +5
-1@@ -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?
drivers/scsi/scsi.c int scsi_dispatch_cmd(struct scsi_cmnd *cmd) · line 707
Quoted 7 lines
drivers/scsi/scsi.c +4
-1+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) {
drivers/scsi/scsi_lib.c int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, · line 198
Quoted 10 lines
drivers/scsi/scsi.c +0
-0scsi_done (cmd);drivers/scsi/scsi_lib.c +1
-0@@ -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.
Quoted 13 lines
drivers/scsi/scsi_lib.c +1
-1req->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)
drivers/scsi/scsi_lib.c int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) · line 1136
Quoted 6 lines
drivers/scsi/scsi_lib.c +3
-0@@ -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.
Quoted 118 lines
drivers/scsi/scsi_lib.c +1
-1if (!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;include/scsi/scsi.h +33
-7@@ -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. */ include/scsi/scsi_cmnd.h +1
-1@@ -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 */ include/scsi/scsi_host.h +3
-5@@ -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;Signature · 7 lines
1.5.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs
Quoted 113 lines · FUJITA Tomonori
Quoted 110 lines · On Tue, 15 Apr 2008 15:34:47 +0300 Boaz Harrosh <[email protected]> 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_lenmembers' type to short as char is not enough.Signed-off-by Boaz Harrosh <[email protected]>Signed-off-by Benny Halevy <[email protected]>--- 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(-)block/scsi_ioctl.c +2
-3@@ -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> drivers/scsi/constants.c +3
-7@@ -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]);drivers/scsi/scsi.c +1
-9@@ -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;
Quoted 15 lines
drivers/scsi/scsi.c int scsi_dispatch_cmd(struct scsi_cmnd *cmd) · line 700
Quoted 12 lines
drivers/scsi/scsi.c +5
-1/* 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_lenbe zero here?
With FS_PC commands this is zero here. Because ULD prepare the command only after prep_fn.
Quoted 11 lines
drivers/scsi/scsi.c int scsi_dispatch_cmd(struct scsi_cmnd *cmd) · line 707
Quoted 8 lines
drivers/scsi/scsi.c +4
-1+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:
Quoted 2 lines
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.
Quoted 8 lines
Quoted 8 lines
drivers/scsi/scsi.c +0
-0scsi_done (cmd);drivers/scsi/scsi_lib.c +0
-0@@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
Quoted 6 lines
drivers/scsi/scsi_lib.c int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, · line 198
Quoted 3 lines
drivers/scsi/scsi_lib.c +1
-0req->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.
Quoted 16 lines
Quoted 16 lines
drivers/scsi/scsi_lib.c +1
-1req->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) }
Quoted 8 lines
drivers/scsi/scsi_lib.c int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) · line 1136
Quoted 4 lines
drivers/scsi/scsi_lib.c +3
-0cmd->cmd_len = req->cmd_len; +if (!cmd->cmd_len) + cmd->cmd_len =scsi_command_size (cmd->cmnd); +how can
cmd->cmd_lenbe zero here?SG_IOpath sets upreq->cmd_lenproperly 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.
Quoted 109 lines
Quoted 109 lines
drivers/scsi/scsi_lib.c +1
-1if (!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;include/scsi/scsi.h +33
-7@@ -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. */ include/scsi/scsi_cmnd.h +1
-1@@ -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 */ include/scsi/scsi_host.h +3
-5@@ -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;
Quoted 7 lines
Quoted 7 lines
include/scsi/scsi_host.h +0
-0int this_id;int can_queue;Signature · 4 lines
1.5.3.3 --
As a reply to this mail I'll send a patch without the extra space.
Boaz
PATCH 2/3 scsi: varlen extended and vendor-specific cdbs
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.
--- 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(-)
block/scsi_ioctl.c +2 -3
@@ -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>
drivers/scsi/constants.c +3 -7
@@ -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]);
drivers/scsi/scsi.c +11 -11
@@ -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);
drivers/scsi/scsi_lib.c +5 -2
@@ -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;
include/scsi/scsi.h +33 -7
@@ -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. */
include/scsi/scsi_cmnd.h +1 -1
@@ -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 */
include/scsi/scsi_host.h +3 -5
@@ -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;
Signature · 1 line
1.5.3.3
Re: [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs
In reply to Boaz HarroshQuoted 130 lines · On Wed, 16 Apr 2008 09:40:17 +0300 Boaz Harrosh <[email protected]> wrote:
Quoted 113 lines · FUJITA Tomonori
Quoted 110 lines · On Tue, 15 Apr 2008 15:34:47 +0300 Boaz Harrosh <[email protected]> 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_lenmembers' type to short as char is not enough.Signed-off-by Boaz Harrosh <[email protected]>Signed-off-by Benny Halevy <[email protected]>--- 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(-)block/scsi_ioctl.c +2
-3@@ -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> drivers/scsi/constants.c +3
-7@@ -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]);drivers/scsi/scsi.c +1
-9@@ -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;Quoted 15 lines
drivers/scsi/scsi.c int scsi_dispatch_cmd(struct scsi_cmnd *cmd) · line 700
Quoted 12 lines
drivers/scsi/scsi.c +5
-1/* 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_lenbe zero here?
Quoted 2 lines
With
FS_PCcommands this is zero here. Because ULD prepare the command only afterprep_fn.
I don't think so. See what scsi_init_cmd_errh does. It's called before scsi_dispatch_cmd.
Quoted 14 lines
Quoted 11 lines
drivers/scsi/scsi.c int scsi_dispatch_cmd(struct scsi_cmnd *cmd) · line 707
Quoted 8 lines
drivers/scsi/scsi.c +4
-1+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:
Quoted 2 lines
if (
scsi_command_size(cmd->cmnd)>cmd->device->host->max_cmd_len) {
Quoted 6 lines
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.
Quoted 40 lines
Quoted 8 lines
Quoted 8 lines
drivers/scsi/scsi.c +0
-0scsi_done (cmd);drivers/scsi/scsi_lib.c +0
-0@@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,Quoted 6 lines
drivers/scsi/scsi_lib.c int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, · line 198
Quoted 3 lines
drivers/scsi/scsi_lib.c +1
-0req->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.
Quoted 16 lines
Quoted 16 lines
drivers/scsi/scsi_lib.c +1
-1req->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) }Quoted 8 lines
drivers/scsi/scsi_lib.c int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) · line 1136
Quoted 4 lines
drivers/scsi/scsi_lib.c +3
-0cmd->cmd_len = req->cmd_len; +if (!cmd->cmd_len) + cmd->cmd_len =scsi_command_size (cmd->cmnd); +how can
cmd->cmd_lenbe zero here?SG_IOpath sets upreq->cmd_lenproperly for PC commands.
Quoted 2 lines
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.
Quoted 125 lines
Quoted 109 lines
Quoted 109 lines
drivers/scsi/scsi_lib.c +1
-1if (!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;include/scsi/scsi.h +33
-7@@ -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. */ include/scsi/scsi_cmnd.h +1
-1@@ -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 */ include/scsi/scsi_host.h +3
-5@@ -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;Quoted 7 lines
Quoted 7 lines
include/scsi/scsi_host.h +0
-0int this_id;int can_queue;Signature · 4 lines
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 2/3 scsi: varlen extended and vendor-specific cdbs
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.
--- 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(-)
block/scsi_ioctl.c +2 -3
@@ -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>
drivers/scsi/constants.c +3 -7
@@ -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]);
drivers/scsi/scsi.c +4 -11
@@ -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);
drivers/scsi/scsi_lib.c +1 -1
@@ -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)
include/scsi/scsi.h +33 -7
@@ -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. */
include/scsi/scsi_cmnd.h +1 -1
@@ -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 */
include/scsi/scsi_host.h +3 -5
@@ -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;
Signature · 1 line
1.5.3.3
Re: [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs
Quoted 220 lines · Boaz Harrosh
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_lenmembers' type to short as char is not enough.Signed-off-by Boaz Harrosh <[email protected]>Signed-off-by Benny Halevy <[email protected]>--- 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(-)block/scsi_ioctl.c +2
-3@@ -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> drivers/scsi/constants.c +3
-7@@ -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]);drivers/scsi/scsi.c +4
-11@@ -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);drivers/scsi/scsi_lib.c +1
-1@@ -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)include/scsi/scsi.h +33
-7@@ -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. */ include/scsi/scsi_cmnd.h +1
-1@@ -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 */ include/scsi/scsi_host.h +1
-1@@ -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
include/scsi/scsi_host.h struct Scsi_Host { · line 583
Quoted 10 lines
include/scsi/scsi_host.h +2
-4-* 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
Re: [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs
In reply to Boaz HarroshQuoted 13 lines · On Thu, 17 Apr 2008 15:25:23 +0300 Boaz Harrosh <[email protected]> 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_lenmembers' type to short as char is not enough.Signed-off-by Boaz Harrosh <[email protected]>Signed-off-by Benny Halevy <[email protected]>
Quoted 9 lines
--- 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.
Re: [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs
Quoted 25 lines · FUJITA Tomonori
Quoted 12 lines · On Thu, 17 Apr 2008 15:25:23 +0300 Boaz Harrosh <[email protected]> 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_lenmembers' type to short as char is not enough.Signed-off-by Boaz Harrosh <[email protected]>Signed-off-by Benny Halevy <[email protected]>Quoted 9 lines
--- 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(-)
Quoted 2 lines
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
PATCH 3/3 iscsi_tcp: Enable large commands
In reply to Boaz HarroshLet 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.
--- drivers/scsi/iscsi_tcp.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/scsi/iscsi_tcp.c +1 -1
@@ -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 ))
Signature · 1 line
1.5.3.3
Re: [PATCH 3/3] iscsi_tcp: Enable large commands
Quoted 3 lines · Boaz Harrosh
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
Re: [PATCH 3/3] iscsi_tcp: Enable large commands
Quoted 5 lines · James Smart
Quoted 3 lines · Boaz Harrosh
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.
Quoted 7 lines
Just to double-check:
if we usesg_ioto 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 thesg_ioinfrastructure 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
Re: [PATCH 3/3] iscsi_tcp: Enable large commands
Quoted 13 lines · Boaz Harrosh
Quoted 11 lines · James Smart
Quoted 3 lines · Boaz Harrosh
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 usesg_ioto 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 thesg_ioinfrastructure for management or pass-thru, are we limited to 260 bytes for request/cmd payload ?-- james s
Quoted 8 lines
I think that only bsg, after the pending patches get accepted, will let you pass larger then 16 bytes commands from user-land.
sg_iois I think limited to 16. However this could be fixed. (Withsg_io, did you mean commands going through thesg.cdriver?)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
Quoted 9 lines
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/3] iscsi_tcp: Enable large commands
In reply to James SmartQuoted 10 lines · On Tue, 15 Apr 2008 09:08:23 -0400 James Smart <[email protected]> wrote:
Quoted 3 lines · Boaz Harrosh
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 usesg_ioto 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 thesg_ioinfrastructure 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).
James Bottomley
maintainerRe: [PATCH 2/3 ver2] block layer extended-cdb support
In reply to FUJITA TomonoriQuoted 2 lines · FUJITA Tomonori
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
Re: [PATCH 2/3 ver2] block layer extended-cdb support
Quoted 11 lines · On Sun, 13 Apr 2008 09:07:55 -0500 James Bottomley…
Quoted 2 lines · FUJITA Tomonori
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).
Quoted 3 lines
The only block device I know that implements
SG_IOis 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.
PATCH 3/3 scsi: varlen extended and vendor-specific cdbs
In reply to Boaz HarroshAdd 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.
--- 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(-)
block/scsi_ioctl.c +2 -2
@@ -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>
drivers/scsi/constants.c +3 -7
@@ -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]);
drivers/scsi/scsi.c +11 -11
@@ -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);
drivers/scsi/scsi_lib.c +22 -5
@@ -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;
include/scsi/scsi.h +33 -7
@@ -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. */
include/scsi/scsi_cmnd.h +1 -1
@@ -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 */
include/scsi/scsi_host.h +3 -5
@@ -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;
Signature · 1 line
1.5.3.3
Quoted 8 lines · Boaz Harrosh
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
cover Is it time for varlen extended and vendor-specific cdbs
In reply to Boaz HarroshYet 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
PATCH 1/4 Let scsi_cmnd->cmnd use request->cmd buffer
- 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
--- 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(-)
drivers/firewire/fw-sbp2.c +1 -1
@@ -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 =
drivers/s390/scsi/zfcp_dbf.c +1 -1
@@ -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;
drivers/s390/scsi/zfcp_fsf.c +1 -1
@@ -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);
drivers/scsi/53c700.c +3 -3
@@ -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 ; }
drivers/scsi/a100u2w.c +1 -1
@@ -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); }/**
drivers/scsi/gdth.c +1 -1
@@ -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 ;
drivers/scsi/hptiop.c +3 -3
@@ -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 ;
drivers/scsi/ibmvscsi/ibmvscsi.c +1 -1
@@ -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)) {
drivers/scsi/initio.c +1 -1
@@ -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 */
drivers/scsi/qla1280.c +2 -2
@@ -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. */
drivers/scsi/scsi_error.c +8 -6
@@ -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));
drivers/scsi/scsi_lib.c +3 -2
@@ -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);
drivers/scsi/scsi_tgt_lib.c +2 -0
@@ -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 ;
drivers/usb/storage/isd200.c +2 -0
@@ -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;
include/scsi/scsi_cmnd.h +19 -2
@@ -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. */
include/scsi/scsi_eh.h +2 -2
@@ -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; };
Signature · 1 line
1.5.3.3
PATCH 2/4 block layer extended-cdb support
In reply to Boaz Harrosh - 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.
--- block/blk-core.c | 2 ++ include/linux/blkdev.h | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-)
block/blk-core.c +2 -0
@@ -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,
include/linux/blkdev.h +39 -2
53 lines not on this page · raw message
Signature · 1 line
1.5.3.3
PATCH 3/4 scsi: varlen extended and vendor-specific cdbs
In reply to Boaz HarroshAdd 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.
--- 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(-)
block/scsi_ioctl.c +2 -2
@@ -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>
drivers/scsi/constants.c +3 -7
@@ -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]);
drivers/scsi/scsi.c +11 -11
@@ -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);
drivers/scsi/scsi_lib.c +12 -6
@@ -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;
include/scsi/scsi.h +33 -7
@@ -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. */
include/scsi/scsi_cmnd.h +1 -1
@@ -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 */
include/scsi/scsi_host.h +3 -5
@@ -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;
Signature · 1 line
1.5.3.3
PATCH 4/4 iscsi_tcp: Enable large command
In reply to Boaz HarroshLet 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.
--- drivers/scsi/iscsi_tcp.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/scsi/iscsi_tcp.c +1 -1
@@ -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 ))
Signature · 1 line
1.5.3.3
Re: [PATCH 4/4] iscsi_tcp: Enable large command
Quoted 14 lines · Boaz Harrosh
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 <[email protected]>--- drivers/scsi/iscsi_tcp.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)drivers/scsi/iscsi_tcp.c +0
-0
drivers/scsi/iscsi_tcp.c iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, · line 1865
Quoted 8 lines
drivers/scsi/iscsi_tcp.c +1
-1@@ -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.