* [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs
@ 2008-03-25 16:21 Boaz Harrosh
2008-03-25 16:22 ` [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh
` (4 more replies)
0 siblings, 5 replies; 77+ messages in thread
From: Boaz Harrosh @ 2008-03-25 16:21 UTC (permalink / raw)
To: James Bottomley, Jens Axboe, Christoph Hellwig, linux-scsi,
Andrew
Submitted is a patchset for adding support for variable-length, extended,
and vendor specific CDBs. It should now cover the entire range of the
SCSI standard. (and/or any other use of command packets in block devices)
They are based on scsi-misc/scsi-rc-fixes/linux-block. They are aimed
for the 2.6.26 merge window. Andrew please also include them in -mm
for testing.
Difference from last time, is at struct request. I did a smallish
hack to save the extra pointer space. The pointer now shares it's
space with the request->cmd, as they are mutual exclusive. The
flag to switch between them is when cmd_len == 0 and varlen_cdb_len != 0
I've added 2 accessors to hide the mess. I think this approach
should be safe with legacy drivers.
This is on top of the size shrink to struct scsi_cmnd gained
in the first patch. We save upto 12 bytes on 32 bit ARCHs
So over all, this cleans things up, and add fixtures without
*any extra cost*.
[1/3] Let scsi_cmnd->cmnd use request->cmd buffer
Here I let scsi_cmnd->cmnd point to the space allocated by
request->cmd, instead of copying the data. The scsi_cmnd->cmd_len
is guaranteed to contain the right length of the command.
I have tried to go over every single place in the kernel that uses
scsi_cmnd->cmnd and make sure it looks sane. Surprisingly to me,
that was not at all bad. I hope I did not miss anything.
I've tested on an x86_64 machine booting from a sata disk and
ran the iscsi regression tests as well as my bidi and varlen tests
on top of the complete patchset and all tests passed.
[2/3] block layer varlen-cd
Here I added an option to use a user supplied buffer for an arbitrary
large command. Buffer must be kept valid until execution of request
ends. The pointer to the buffer shares it's space with the fixed
length command, so the size of struct request does not change.
[3/3] scsi: varlen extended and vendor-specific cdbs
Adds support for variable length, extended, and vendor-specific
cdbs at the scsi mid-layer.
Boaz
^ permalink raw reply [flat|nested] 77+ messages in thread* [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer 2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh @ 2008-03-25 16:22 ` Boaz Harrosh 2008-03-25 16:32 ` [PATCH 2/3] block layer varlen-cdb Boaz Harrosh ` (3 subsequent siblings) 4 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-03-25 16:22 UTC (permalink / raw) To: James Bottomley, Jens Axboe, Christoph Hellwig, linux-scsi, Andrew - struct scsi_cmnd had a 16 bytes command buffer of its own. This is an unnecessary duplication and copy of request's cmd. It is probably left overs from the time that scsi_cmnd could function without a request attached. So clean that up. - Once above is done, few places, apart from scsi-ml, needed adjustments due to changing the data type of scsi_cmnd->cmnd. - Lots of drivers still use MAX_COMMAND_SIZE. So I have left that #define but equate it to BLK_MAX_CDB. The way I see it and is reflected in the patch below is. MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB as per the SCSI standard and is not related to the implementation. BLK_MAX_CDB. - The allocated space at the request level - I have audit all ISA drivers and made sure none use ->cmnd in a DMA Operation. Same audit was done by Andi Kleen. (*)fixed-length here means commands that their size can be determined by their opcode and the CDB does not carry a length specifier, (unlike the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly true and the SCSI standard also defines extended commands and vendor specific commands that can be bigger than 16 bytes. The kernel will support these using the same infrastructure used for VARLEN CDB's. So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml supports without specifying a cmd_len by ULD's Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- drivers/firewire/fw-sbp2.c | 2 +- drivers/s390/scsi/zfcp_dbf.c | 2 +- drivers/s390/scsi/zfcp_fsf.c | 2 +- drivers/scsi/53c700.c | 6 +++--- drivers/scsi/a100u2w.c | 2 +- drivers/scsi/gdth.c | 2 +- drivers/scsi/hptiop.c | 6 +++--- drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- drivers/scsi/initio.c | 2 +- drivers/scsi/qla1280.c | 4 ++-- drivers/scsi/scsi_error.c | 14 ++++++++------ drivers/scsi/scsi_lib.c | 5 +++-- drivers/scsi/scsi_tgt_lib.c | 2 ++ drivers/usb/storage/isd200.c | 2 ++ include/scsi/scsi_cmnd.h | 21 +++++++++++++++++++-- include/scsi/scsi_eh.h | 4 ++-- 16 files changed, 51 insertions(+), 27 deletions(-) diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 62b4e47..2260e56 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -1492,7 +1492,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) memset(orb->request.command_block, 0, sizeof(orb->request.command_block)); - memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); + memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len); orb->base.callback = complete_command_orb; orb->base.request_bus = diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 701046c..7a7f619 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -724,7 +724,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, rec->scsi_result = scsi_cmnd->result; rec->scsi_cmnd = (unsigned long)scsi_cmnd; rec->scsi_serial = scsi_cmnd->serial_number; - memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd, + memcpy(rec->scsi_opcode, scsi_cmnd->cmnd, min((int)scsi_cmnd->cmd_len, ZFCP_DBF_SCSI_OPCODE)); rec->scsi_retries = scsi_cmnd->retries; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 2ed3c7b..df38e1d 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4227,7 +4227,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n", scpnt->result); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, - (void *) &scpnt->cmnd, scpnt->cmd_len); + scpnt->cmnd, scpnt->cmd_len); ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n", fcp_rsp_iu->fcp_sns_len); diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index f4c4fe9..f5a9add 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, (struct NCR_700_command_slot *)SCp->host_scribble; dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); + MAX_COMMAND_SIZE, DMA_TO_DEVICE); if (slot->flags == NCR_700_FLAG_AUTOSENSE) { char *cmnd = NCR_700_get_sense_cmnd(SCp->device); #ifdef NCR_700_DEBUG @@ -1004,7 +1004,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, * here */ NCR_700_unmap(hostdata, SCp, slot); dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), + MAX_COMMAND_SIZE, DMA_TO_DEVICE); cmnd[0] = REQUEST_SENSE; @@ -1901,7 +1901,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) } slot->resume_offset = 0; slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); + MAX_COMMAND_SIZE, DMA_TO_DEVICE); NCR_700_start_command(SCp); return 0; } diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 792b2e8..ced3eeb 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -895,7 +895,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru } else { scb->tag_msg = 0; /* No tag support */ } - memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len); + memcpy(scb->cdb, cmd->cmnd, scb->cdb_len); } /** diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index c6d6e7c..8e2e964 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -465,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, scp->request = (struct request *)&wait; scp->timeout_per_command = timeout*HZ; scp->cmd_len = 12; - memcpy(scp->cmnd, cmnd, 12); + scp->cmnd = cmnd; cmndinfo.priority = IOCTL_PRI; cmndinfo.internal_cmd_str = gdtcmd; cmndinfo.internal_command = 1; diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 44dccf2..5d9322c 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -761,9 +761,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, scp, host->host_no, scp->device->channel, scp->device->id, scp->device->lun, - *((u32 *)&scp->cmnd), - *((u32 *)&scp->cmnd + 1), - *((u32 *)&scp->cmnd + 2), + ((u32 *)scp->cmnd)[0], + ((u32 *)scp->cmnd)[1], + ((u32 *)scp->cmnd)[2], _req->index, _req->req_virt); scp->result = 0; diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 78d46a9..df9b865 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -738,7 +738,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, srp_cmd = &evt_struct->iu.srp.cmd; memset(srp_cmd, 0x00, SRP_MAX_IU_LEN); srp_cmd->opcode = SRP_CMD; - memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd)); + memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb)); srp_cmd->lun = ((u64) lun) << 48; if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 0cc8868..40e9875 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c cblk->hastat = 0; cblk->tastat = 0; /* Command the command */ - memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len); + memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len); /* Set up tags */ if (cmnd->device->tagged_supported) { /* Tag Support */ diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 68c0d09..b53420b 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -2863,7 +2863,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Load SCSI command packet. */ pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd)); /* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ /* Set transfer direction. */ @@ -3132,7 +3132,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Load SCSI command packet. */ pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd)); /*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ /* Set transfer direction. */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1221d2c..0b42aa5 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -626,7 +626,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) * @scmd: SCSI command structure to hijack * @ses: structure to save restore information * @cmnd: CDB to send. Can be NULL if no new cmnd is needed - * @cmnd_size: size in bytes of @cmnd + * @cmnd_size: size in bytes of @cmnd (must be <= BLK_MAX_CDB) * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) * * This function is used to save a scsi command information before re-execution @@ -648,12 +648,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, * command. */ ses->cmd_len = scmd->cmd_len; - memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd)); + ses->cmnd = scmd->cmnd; ses->data_direction = scmd->sc_data_direction; ses->sdb = scmd->sdb; ses->next_rq = scmd->request->next_rq; ses->result = scmd->result; + scmd->cmnd = ses->eh_cmnd; + memset(scmd->cmnd, 0, BLK_MAX_CDB); memset(&scmd->sdb, 0, sizeof(scmd->sdb)); scmd->request->next_rq = NULL; @@ -665,14 +667,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, scmd->sdb.table.sgl = &ses->sense_sgl; scmd->sc_data_direction = DMA_FROM_DEVICE; scmd->sdb.table.nents = 1; - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); scmd->cmnd[0] = REQUEST_SENSE; scmd->cmnd[4] = scmd->sdb.length; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } else { scmd->sc_data_direction = DMA_NONE; if (cmnd) { - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); + BUG_ON(cmnd_size > BLK_MAX_CDB); memcpy(scmd->cmnd, cmnd, cmnd_size); scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } @@ -705,7 +706,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) * Restore original data */ scmd->cmd_len = ses->cmd_len; - memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd)); + scmd->cmnd = ses->cmnd; scmd->sc_data_direction = ses->data_direction; scmd->sdb = ses->sdb; scmd->request->next_rq = ses->next_rq; @@ -1774,7 +1775,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scmd->request = &req; memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); - memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd)); + scmd->cmnd = req.cmd; + memset(scmd->cmnd, 0, BLK_MAX_CDB); scmd->scsi_done = scsi_reset_provider_done_command; memset(&scmd->sdb, 0, sizeof(scmd->sdb)); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f40898d..75f3aab 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1092,6 +1092,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, cmd->tag = req->tag; cmd->request = req; + cmd->cmnd = req->cmd; + return cmd; } @@ -1129,8 +1131,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) req->buffer = NULL; } - BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); - memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); cmd->cmd_len = req->cmd_len; if (!req->data_len) cmd->sc_data_direction = DMA_NONE; @@ -1167,6 +1167,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) if (unlikely(!cmd)) return BLKPREP_DEFER; + memset(cmd->cmnd, 0, BLK_MAX_CDB); return scsi_init_io(cmd, GFP_ATOMIC); } EXPORT_SYMBOL(scsi_setup_fs_cmnd); diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index a0f308b..8c92ef3 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -107,6 +107,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, cmd->jiffies_at_alloc = jiffies; cmd->request = rq; + cmd->cmnd = rq->cmd; + rq->special = cmd; rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd_flags |= REQ_TYPE_BLOCK_PC; diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 971d13d..3addcd8 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -292,6 +292,7 @@ struct isd200_info { /* maximum number of LUNs supported */ unsigned char MaxLUNs; + unsigned char cmnd[BLK_MAX_CDB]; struct scsi_cmnd srb; struct scatterlist sg; }; @@ -450,6 +451,7 @@ static int isd200_action( struct us_data *us, int action, memset(&ata, 0, sizeof(ata)); memset(&srb_dev, 0, sizeof(srb_dev)); + srb->cmnd = info->cmnd; srb->device = &srb_dev; ++srb->serial_number; diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 8d20e60..dea73e5 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -7,10 +7,28 @@ #include <linux/types.h> #include <linux/timer.h> #include <linux/scatterlist.h> +#include <linux/blkdev.h> struct Scsi_Host; struct scsi_device; +/* + * MAX_COMMAND_SIZE is: + * The longest fixed-length SCSI CDB as per the SCSI standard. + * fixed-length means: commands that their size can be determined + * by their opcode and the CDB does not carry a length specifier, (unlike + * the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly + * true and the SCSI standard also defines extended commands and + * vendor specific commands that can be bigger than 16 bytes. The kernel + * will support these using the same infrastructure used for VARLEN CDB's. + * So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml + * supports without specifying a cmd_len by ULD's + */ +#define MAX_COMMAND_SIZE 16 +#if (MAX_COMMAND_SIZE > BLK_MAX_CDB) +# error MAX_COMMAND_SIZE can not be smaller than BLK_MAX_CDB +#endif + struct scsi_data_buffer { struct sg_table table; unsigned length; @@ -64,8 +82,7 @@ struct scsi_cmnd { enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ -#define MAX_COMMAND_SIZE 16 - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char *cmnd; struct timer_list eh_timeout; /* Used to time out the command. */ diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 37a7614..93af44f 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -73,11 +73,11 @@ struct scsi_eh_save { int result; enum dma_data_direction data_direction; unsigned char cmd_len; - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char *cmnd; struct scsi_data_buffer sdb; struct request *next_rq; - /* new command support */ + unsigned char eh_cmnd[BLK_MAX_CDB]; struct scatterlist sense_sgl; }; -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH 2/3] block layer varlen-cdb 2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh 2008-03-25 16:22 ` [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh @ 2008-03-25 16:32 ` Boaz Harrosh 2008-04-03 16:43 ` James Bottomley 2008-03-25 16:36 ` [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh ` (2 subsequent siblings) 4 siblings, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-03-25 16:32 UTC (permalink / raw) To: James Bottomley, Jens Axboe, Christoph Hellwig, linux-scsi, Andrew - add varlen_cdb and varlen_cdb_len to hold a large user cdb if needed. They start as empty. Allocation of buffer must be done by user and held until request execution is done. - Since there can be either a fix_length command up to 16 bytes or a variable_length, larger then 16 bytes, commands but never both, we hold the two types in a union to save space. The presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb mode. - Please use added rq_{set,get}_varlen_cdb() to set every thing up in a way that will not confuse drivers that do not support varlen_cdb's. - Note that this patch does not add any size to struct request since the unsigned cmd_len is split here to 2 ushorts, which is more then enough. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- block/blk-core.c | 2 ++ include/linux/blkdev.h | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 2a438a9..70d32f7 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq) rq->end_io = NULL; rq->end_io_data = NULL; rq->next_rq = NULL; + rq->varlen_cdb_len = 0; + rq->varlen_cdb = NULL; } static void req_bio_endio(struct request *rq, struct bio *bio, diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 6f79d40..f829571 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -213,8 +213,15 @@ struct request { /* * when request is used as a packet command carrier */ - unsigned int cmd_len; - unsigned char cmd[BLK_MAX_CDB]; + unsigned short cmd_len; + unsigned short varlen_cdb_len; /* length of varlen_cdb buffer */ + union { + unsigned char cmd[BLK_MAX_CDB]; + unsigned char *varlen_cdb;/* an optional variable-length cdb. + * points to a user buffer that must + * be valid until end of request + */ + }; unsigned int data_len; unsigned int extra_len; /* length of alignment and padding */ @@ -484,6 +491,22 @@ enum { #define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC) #define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META) +static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short cdb_len) +{ + rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */ + rq->varlen_cdb_len = cdb_len; + rq->varlen_cdb = cdb; +} + +/* If ! a varlen_cdb than return NULL */ +static inline u8 *rq_get_varlen_cdb(struct request *rq) +{ + if (!rq->cmd_len && rq->varlen_cdb_len) + return rq->varlen_cdb; + else + return NULL; +} + static inline int blk_queue_full(struct request_queue *q, int rw) { if (rw == READ) -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3] block layer varlen-cdb 2008-03-25 16:32 ` [PATCH 2/3] block layer varlen-cdb Boaz Harrosh @ 2008-04-03 16:43 ` James Bottomley 2008-04-03 17:26 ` Benny Halevy 2008-04-03 18:32 ` [PATCH 2/3 ver2] block layer extended-cdb support Boaz Harrosh 0 siblings, 2 replies; 77+ messages in thread From: James Bottomley @ 2008-04-03 16:43 UTC (permalink / raw) To: Boaz Harrosh; +Cc: Jens Axboe, Christoph Hellwig, linux-scsi, Andrew Morton On Tue, 2008-03-25 at 18:32 +0200, Boaz Harrosh wrote: > - add varlen_cdb and varlen_cdb_len to hold a large user cdb > if needed. They start as empty. Allocation of buffer must > be done by user and held until request execution is done. > - Since there can be either a fix_length command up to 16 bytes > or a variable_length, larger then 16 bytes, commands but never > both, we hold the two types in a union to save space. The > presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb > mode. > - Please use added rq_{set,get}_varlen_cdb() to set every thing > up in a way that will not confuse drivers that do not support > varlen_cdb's. > - Note that this patch does not add any size to struct request > since the unsigned cmd_len is split here to 2 ushorts, which > is more then enough. My first observation is that the block stuff all looks a bit misnamed ... it's not about variable length commands it's about getting block to accept packet commands larger than BLK_MAX_CDB, be they SCSI OSD commands or ATA taskfiles. > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > --- > block/blk-core.c | 2 ++ > include/linux/blkdev.h | 27 +++++++++++++++++++++++++-- > 2 files changed, 27 insertions(+), 2 deletions(-) > > diff --git a/block/blk-core.c b/block/blk-core.c > index 2a438a9..70d32f7 100644 > --- a/block/blk-core.c > +++ b/block/blk-core.c > @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq) > rq->end_io = NULL; > rq->end_io_data = NULL; > rq->next_rq = NULL; > + rq->varlen_cdb_len = 0; > + rq->varlen_cdb = NULL; possibly s/varlen/large/ > } > > static void req_bio_endio(struct request *rq, struct bio *bio, > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > index 6f79d40..f829571 100644 > --- a/include/linux/blkdev.h > +++ b/include/linux/blkdev.h > @@ -213,8 +213,15 @@ struct request { > /* > * when request is used as a packet command carrier > */ > - unsigned int cmd_len; > - unsigned char cmd[BLK_MAX_CDB]; > + unsigned short cmd_len; > + unsigned short varlen_cdb_len; /* length of varlen_cdb buffer */ > + union { > + unsigned char cmd[BLK_MAX_CDB]; > + unsigned char *varlen_cdb;/* an optional variable-length cdb. > + * points to a user buffer that must > + * be valid until end of request > + */ again s/varlen/large/ > + }; > > unsigned int data_len; > unsigned int extra_len; /* length of alignment and padding */ > @@ -484,6 +491,22 @@ enum { > #define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC) > #define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META) > > +static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short cdb_len) > +{ > + rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */ > + rq->varlen_cdb_len = cdb_len; > + rq->varlen_cdb = cdb; > +} > + > +/* If ! a varlen_cdb than return NULL */ > +static inline u8 *rq_get_varlen_cdb(struct request *rq) > +{ > + if (!rq->cmd_len && rq->varlen_cdb_len) > + return rq->varlen_cdb; > + else > + return NULL; > +} These accessors look wrong ... I think what we want is rq_get_cdb and rq_set_cdb that handles both <= BLK_MAX_CDB by simply a memcpy and > BLK_MAX_CDB by setting up the large_cdb pointer. That way we can accessorize the whole lot and the drivers don't have to care about what BLK_MAX_CDB is set to (it simply becomes an internal convenience of block ... and possibly allows us to eliminate the request carries command data entirely). > static inline int blk_queue_full(struct request_queue *q, int rw) > { > if (rw == READ) James ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3] block layer varlen-cdb 2008-04-03 16:43 ` James Bottomley @ 2008-04-03 17:26 ` Benny Halevy 2008-04-03 18:32 ` [PATCH 2/3 ver2] block layer extended-cdb support Boaz Harrosh 1 sibling, 0 replies; 77+ messages in thread From: Benny Halevy @ 2008-04-03 17:26 UTC (permalink / raw) To: James Bottomley Cc: Boaz Harrosh, Jens Axboe, Christoph Hellwig, linux-scsi, Andrew Morton On Apr. 03, 2008, 19:43 +0300, James Bottomley <James.Bottomley@HansenPartnership.com> wrote: > On Tue, 2008-03-25 at 18:32 +0200, Boaz Harrosh wrote: >> - add varlen_cdb and varlen_cdb_len to hold a large user cdb >> if needed. They start as empty. Allocation of buffer must >> be done by user and held until request execution is done. >> - Since there can be either a fix_length command up to 16 bytes >> or a variable_length, larger then 16 bytes, commands but never >> both, we hold the two types in a union to save space. The >> presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb >> mode. >> - Please use added rq_{set,get}_varlen_cdb() to set every thing >> up in a way that will not confuse drivers that do not support >> varlen_cdb's. >> - Note that this patch does not add any size to struct request >> since the unsigned cmd_len is split here to 2 ushorts, which >> is more then enough. > > My first observation is that the block stuff all looks a bit > misnamed ... it's not about variable length commands it's about getting > block to accept packet commands larger than BLK_MAX_CDB, be they SCSI > OSD commands or ATA taskfiles. > >> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> >> --- >> block/blk-core.c | 2 ++ >> include/linux/blkdev.h | 27 +++++++++++++++++++++++++-- >> 2 files changed, 27 insertions(+), 2 deletions(-) >> >> diff --git a/block/blk-core.c b/block/blk-core.c >> index 2a438a9..70d32f7 100644 >> --- a/block/blk-core.c >> +++ b/block/blk-core.c >> @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq) >> rq->end_io = NULL; >> rq->end_io_data = NULL; >> rq->next_rq = NULL; >> + rq->varlen_cdb_len = 0; >> + rq->varlen_cdb = NULL; > > possibly s/varlen/large/ If we change any names, just please do not use "large". I'd prefer ext_cdb, where "ext" can stand for "extended" as well as "external" (this chimes well with iSCSI naming BTW). > >> } >> >> static void req_bio_endio(struct request *rq, struct bio *bio, >> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h >> index 6f79d40..f829571 100644 >> --- a/include/linux/blkdev.h >> +++ b/include/linux/blkdev.h >> @@ -213,8 +213,15 @@ struct request { >> /* >> * when request is used as a packet command carrier >> */ >> - unsigned int cmd_len; >> - unsigned char cmd[BLK_MAX_CDB]; >> + unsigned short cmd_len; >> + unsigned short varlen_cdb_len; /* length of varlen_cdb buffer */ >> + union { >> + unsigned char cmd[BLK_MAX_CDB]; >> + unsigned char *varlen_cdb;/* an optional variable-length cdb. >> + * points to a user buffer that must >> + * be valid until end of request >> + */ > > again s/varlen/large/ > >> + }; >> >> unsigned int data_len; >> unsigned int extra_len; /* length of alignment and padding */ >> @@ -484,6 +491,22 @@ enum { >> #define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC) >> #define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META) >> >> +static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short cdb_len) >> +{ >> + rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */ >> + rq->varlen_cdb_len = cdb_len; >> + rq->varlen_cdb = cdb; >> +} >> + >> +/* If ! a varlen_cdb than return NULL */ >> +static inline u8 *rq_get_varlen_cdb(struct request *rq) >> +{ >> + if (!rq->cmd_len && rq->varlen_cdb_len) >> + return rq->varlen_cdb; >> + else >> + return NULL; >> +} > > These accessors look wrong ... I think what we want is rq_get_cdb and > rq_set_cdb that handles both <= BLK_MAX_CDB by simply a memcpy and > > BLK_MAX_CDB by setting up the large_cdb pointer. That way we can > accessorize the whole lot and the drivers don't have to care about what > BLK_MAX_CDB is set to (it simply becomes an internal convenience of > block ... and possibly allows us to eliminate the request carries > command data entirely). That's seems like a terrific idea. Benny > >> static inline int blk_queue_full(struct request_queue *q, int rw) >> { >> if (rw == READ) > > James > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-03 16:43 ` James Bottomley 2008-04-03 17:26 ` Benny Halevy @ 2008-04-03 18:32 ` Boaz Harrosh 2008-04-04 11:46 ` Jens Axboe 1 sibling, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-03 18:32 UTC (permalink / raw) To: James Bottomley; +Cc: Jens Axboe, Christoph Hellwig, linux-scsi, Andrew Morton James Bottomley wrote: > On Tue, 2008-03-25 at 18:32 +0200, Boaz Harrosh wrote: >> - add varlen_cdb and varlen_cdb_len to hold a large user cdb >> if needed. They start as empty. Allocation of buffer must >> be done by user and held until request execution is done. >> - Since there can be either a fix_length command up to 16 bytes >> or a variable_length, larger then 16 bytes, commands but never >> both, we hold the two types in a union to save space. The >> presence of varlen_cdb_len and cmd_len==0 signals a varlen_cdb >> mode. >> - Please use added rq_{set,get}_varlen_cdb() to set every thing >> up in a way that will not confuse drivers that do not support >> varlen_cdb's. >> - Note that this patch does not add any size to struct request >> since the unsigned cmd_len is split here to 2 ushorts, which >> is more then enough. > > My first observation is that the block stuff all looks a bit > misnamed ... it's not about variable length commands it's about getting > block to accept packet commands larger than BLK_MAX_CDB, be they SCSI > OSD commands or ATA taskfiles. > >> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> >> --- >> block/blk-core.c | 2 ++ >> include/linux/blkdev.h | 27 +++++++++++++++++++++++++-- >> 2 files changed, 27 insertions(+), 2 deletions(-) >> >> diff --git a/block/blk-core.c b/block/blk-core.c >> index 2a438a9..70d32f7 100644 >> --- a/block/blk-core.c >> +++ b/block/blk-core.c >> @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq) >> rq->end_io = NULL; >> rq->end_io_data = NULL; >> rq->next_rq = NULL; >> + rq->varlen_cdb_len = 0; >> + rq->varlen_cdb = NULL; > > possibly s/varlen/large/ > >> } >> >> static void req_bio_endio(struct request *rq, struct bio *bio, >> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h >> index 6f79d40..f829571 100644 >> --- a/include/linux/blkdev.h >> +++ b/include/linux/blkdev.h >> @@ -213,8 +213,15 @@ struct request { >> /* >> * when request is used as a packet command carrier >> */ >> - unsigned int cmd_len; >> - unsigned char cmd[BLK_MAX_CDB]; >> + unsigned short cmd_len; >> + unsigned short varlen_cdb_len; /* length of varlen_cdb buffer */ >> + union { >> + unsigned char cmd[BLK_MAX_CDB]; >> + unsigned char *varlen_cdb;/* an optional variable-length cdb. >> + * points to a user buffer that must >> + * be valid until end of request >> + */ > > again s/varlen/large/ > >> + }; >> >> unsigned int data_len; >> unsigned int extra_len; /* length of alignment and padding */ >> @@ -484,6 +491,22 @@ enum { >> #define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC) >> #define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META) >> >> +static inline void rq_set_varlen_cdb(struct request *rq, u8 *cdb, short cdb_len) >> +{ >> + rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */ >> + rq->varlen_cdb_len = cdb_len; >> + rq->varlen_cdb = cdb; >> +} >> + >> +/* If ! a varlen_cdb than return NULL */ >> +static inline u8 *rq_get_varlen_cdb(struct request *rq) >> +{ >> + if (!rq->cmd_len && rq->varlen_cdb_len) >> + return rq->varlen_cdb; >> + else >> + return NULL; >> +} > > These accessors look wrong ... I think what we want is rq_get_cdb and > rq_set_cdb that handles both <= BLK_MAX_CDB by simply a memcpy and > > BLK_MAX_CDB by setting up the large_cdb pointer. That way we can > accessorize the whole lot and the drivers don't have to care about what > BLK_MAX_CDB is set to (it simply becomes an internal convenience of > block ... and possibly allows us to eliminate the request carries > command data entirely). > >> static inline int blk_queue_full(struct request_queue *q, int rw) >> { >> if (rw == READ) > > James > > Thanks James for your review. With taking Benny's comments into account also, perhaps this is what you meant (untested, for review, third patch is missing still) Boaz --- >From 1da591a5ef9697f37604721bfe437a2609bb8217 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh <bharrosh@panasas.com> Date: Wed, 31 Oct 2007 14:56:09 +0200 Subject: [PATCH] block layer extended-cdb support - add ext_cdb and ext_cdb_len to hold a large external cdb if needed. They start as empty. Allocation of buffer must be done by user and held until request execution is done. - Since there can be either a fix_length command up to 16 bytes or an external extended command but never both, we hold the two types in a union to save space. The presence of ext_cdb_len!=0 and cmd_len==0 signals an ext_cdb mode. - Use new rq_set_cdb() to set everything up in a way that will not confuse drivers that do not support extended cdb's. - Use rq_get_cdb()/rq_get_cdb_len() to retrieve command and length in a generic way. - Once all drivers and users convert to the new accessors the cmd[] 16 bytes buffer can be discarded. - Note that this patch does not add any size to struct request since the unsigned cmd_len is split here to 2 ushorts, which is more then enough. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- block/blk-core.c | 2 ++ include/linux/blkdev.h | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 2a438a9..cc9a790 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq) rq->end_io = NULL; rq->end_io_data = NULL; rq->next_rq = NULL; + rq->ext_cdb_len = 0; + rq->ext_cdb = NULL; } static void req_bio_endio(struct request *rq, struct bio *bio, diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 6f79d40..2f87c9d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -213,8 +213,15 @@ struct request { /* * when request is used as a packet command carrier */ - unsigned int cmd_len; - unsigned char cmd[BLK_MAX_CDB]; + unsigned short cmd_len; + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ + union { + unsigned char cmd[BLK_MAX_CDB]; + unsigned char *ext_cdb;/* an optional extended cdb. + * points to a user buffer that must + * be valid until end of request + */ + }; unsigned int data_len; unsigned int extra_len; /* length of alignment and padding */ @@ -484,6 +491,36 @@ enum { #define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC) #define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META) +static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) +{ + if (cdb_len <= BLK_MAX_CDB) { + memcpy(rq->cmd, cdb, cdb_len); + rq->cmd_len = cdb_len; + rq->ext_cdb_len = 0; + } + else { + rq->cmd_len = 0; /*Make sure legacy drivers don't get confused*/ + rq->ext_cdb_len = cdb_len; + rq->ext_cdb = cdb; + } +} + +static inline u8 *rq_get_cdb(struct request *rq) +{ + if (!rq->cmd_len && rq->ext_cdb_len) + return rq->ext_cdb; + else + return rq->cmd; +} + +static inline unsigned short rq_get_cdb_len(struct request *rq) +{ + if (!rq->cmd_len && rq->ext_cdb_len) + return rq->ext_cdb_len; + else + return rq->cmd_len; +} + static inline int blk_queue_full(struct request_queue *q, int rw) { if (rw == READ) -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-03 18:32 ` [PATCH 2/3 ver2] block layer extended-cdb support Boaz Harrosh @ 2008-04-04 11:46 ` Jens Axboe 2008-04-06 9:35 ` Boaz Harrosh 0 siblings, 1 reply; 77+ messages in thread From: Jens Axboe @ 2008-04-04 11:46 UTC (permalink / raw) To: Boaz Harrosh Cc: James Bottomley, Christoph Hellwig, linux-scsi, Andrew Morton On Thu, Apr 03 2008, Boaz Harrosh wrote: > static void req_bio_endio(struct request *rq, struct bio *bio, > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > index 6f79d40..2f87c9d 100644 > --- a/include/linux/blkdev.h > +++ b/include/linux/blkdev.h > @@ -213,8 +213,15 @@ struct request { > /* > * when request is used as a packet command carrier > */ > - unsigned int cmd_len; > - unsigned char cmd[BLK_MAX_CDB]; > + unsigned short cmd_len; > + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ > + union { > + unsigned char cmd[BLK_MAX_CDB]; > + unsigned char *ext_cdb;/* an optional extended cdb. > + * points to a user buffer that must > + * be valid until end of request > + */ > + }; Why not just something ala unsigned short cmd_len; unsigned char __cmd[BLK_MAX_CDB]; unsigned char *cmd; and then have rq_init() do rq->cmd = rq->__cmd; and just have a function for setting up a larger ->cmd and adjusting ->cmd_len in the process? Then rq_set_cdb() would be static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) { rq->cmd = cdb; rq->cmd_len = cdb_len; } and rq_get_cdb() plus rq_get_cdb_len() could just go away. -- Jens Axboe ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-04 11:46 ` Jens Axboe @ 2008-04-06 9:35 ` Boaz Harrosh 2008-04-06 11:05 ` Boaz Harrosh 2008-04-12 5:52 ` FUJITA Tomonori 0 siblings, 2 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-06 9:35 UTC (permalink / raw) To: Jens Axboe; +Cc: James Bottomley, Christoph Hellwig, linux-scsi, Andrew Morton On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > On Thu, Apr 03 2008, Boaz Harrosh wrote: >> static void req_bio_endio(struct request *rq, struct bio *bio, >> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h >> index 6f79d40..2f87c9d 100644 >> --- a/include/linux/blkdev.h >> +++ b/include/linux/blkdev.h >> @@ -213,8 +213,15 @@ struct request { >> /* >> * when request is used as a packet command carrier >> */ >> - unsigned int cmd_len; >> - unsigned char cmd[BLK_MAX_CDB]; >> + unsigned short cmd_len; >> + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ >> + union { >> + unsigned char cmd[BLK_MAX_CDB]; >> + unsigned char *ext_cdb;/* an optional extended cdb. >> + * points to a user buffer that must >> + * be valid until end of request >> + */ >> + }; > > Why not just something ala > > unsigned short cmd_len; > unsigned char __cmd[BLK_MAX_CDB]; > unsigned char *cmd; > > and then have rq_init() do > > rq->cmd = rq->__cmd; > > and just have a function for setting up a larger ->cmd and adjusting > ->cmd_len in the process? > > Then rq_set_cdb() would be > > static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) > { > rq->cmd = cdb; > rq->cmd_len = cdb_len; > } > > and rq_get_cdb() plus rq_get_cdb_len() could just go away. > Because this way it is dangerous if large commands are issued to legacy drivers. In scsi-land we have .cmd_len at host template that will govern if we are allow to issue larger commands to the driver. In block devices we do not have such a facility, and the danger is if such commands are issued through bsg or other means, even by malicious code. What you say is the ideal and it is what I've done for scsi, but for block devices we can not do that yet. With the way I did it here, Legacy drivers will see zero length command and will do the right thing, from what I've seen. Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-06 9:35 ` Boaz Harrosh @ 2008-04-06 11:05 ` Boaz Harrosh 2008-04-07 8:31 ` Jens Axboe 2008-04-12 5:52 ` FUJITA Tomonori 1 sibling, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-06 11:05 UTC (permalink / raw) To: Jens Axboe; +Cc: James Bottomley, Christoph Hellwig, linux-scsi, Andrew Morton On Sun, Apr 06 2008 at 12:35 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: > On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: >> On Thu, Apr 03 2008, Boaz Harrosh wrote: >>> static void req_bio_endio(struct request *rq, struct bio *bio, >>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h >>> index 6f79d40..2f87c9d 100644 >>> --- a/include/linux/blkdev.h >>> +++ b/include/linux/blkdev.h >>> @@ -213,8 +213,15 @@ struct request { >>> /* >>> * when request is used as a packet command carrier >>> */ >>> - unsigned int cmd_len; >>> - unsigned char cmd[BLK_MAX_CDB]; >>> + unsigned short cmd_len; >>> + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ >>> + union { >>> + unsigned char cmd[BLK_MAX_CDB]; >>> + unsigned char *ext_cdb;/* an optional extended cdb. >>> + * points to a user buffer that must >>> + * be valid until end of request >>> + */ >>> + }; >> Why not just something ala >> >> unsigned short cmd_len; >> unsigned char __cmd[BLK_MAX_CDB]; >> unsigned char *cmd; >> >> and then have rq_init() do >> >> rq->cmd = rq->__cmd; >> >> and just have a function for setting up a larger ->cmd and adjusting >> ->cmd_len in the process? >> >> Then rq_set_cdb() would be >> >> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) >> { >> rq->cmd = cdb; >> rq->cmd_len = cdb_len; >> } >> >> and rq_get_cdb() plus rq_get_cdb_len() could just go away. >> > > Because this way it is dangerous if large commands are issued to legacy > drivers. In scsi-land we have .cmd_len at host template that will govern if > we are allow to issue larger commands to the driver. In block devices we do > not have such a facility, and the danger is if such commands are issued through > bsg or other means, even by malicious code. What you say is the ideal and it > is what I've done for scsi, but for block devices we can not do that yet. > With the way I did it here, Legacy drivers will see zero length command and > will do the right thing, from what I've seen. > > Boaz > I forgot to say. With the proposed way, we are saving the space of the pointer. And the final outcome of eventually eliminating the buffer, is the same. Let me summarize. - support extended, arbitrary large commands by introducing the notion that cdb space can be pointed to not carried. - Eventually transition all block drivers and users to the new system, for all commands not just large ones. - Do so without introducing any extra cost or instability, but also let the transition be done gradually, and not at once, (hence more stability). I have thought about that long and hard, my first patch of the matter was 18 month ago. I still think this is the smoothest way to go, and not that ugly, really. Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-06 11:05 ` Boaz Harrosh @ 2008-04-07 8:31 ` Jens Axboe 0 siblings, 0 replies; 77+ messages in thread From: Jens Axboe @ 2008-04-07 8:31 UTC (permalink / raw) To: Boaz Harrosh Cc: James Bottomley, Christoph Hellwig, linux-scsi, Andrew Morton On Sun, Apr 06 2008, Boaz Harrosh wrote: > On Sun, Apr 06 2008 at 12:35 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: > > On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > >> On Thu, Apr 03 2008, Boaz Harrosh wrote: > >>> static void req_bio_endio(struct request *rq, struct bio *bio, > >>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > >>> index 6f79d40..2f87c9d 100644 > >>> --- a/include/linux/blkdev.h > >>> +++ b/include/linux/blkdev.h > >>> @@ -213,8 +213,15 @@ struct request { > >>> /* > >>> * when request is used as a packet command carrier > >>> */ > >>> - unsigned int cmd_len; > >>> - unsigned char cmd[BLK_MAX_CDB]; > >>> + unsigned short cmd_len; > >>> + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ > >>> + union { > >>> + unsigned char cmd[BLK_MAX_CDB]; > >>> + unsigned char *ext_cdb;/* an optional extended cdb. > >>> + * points to a user buffer that must > >>> + * be valid until end of request > >>> + */ > >>> + }; > >> Why not just something ala > >> > >> unsigned short cmd_len; > >> unsigned char __cmd[BLK_MAX_CDB]; > >> unsigned char *cmd; > >> > >> and then have rq_init() do > >> > >> rq->cmd = rq->__cmd; > >> > >> and just have a function for setting up a larger ->cmd and adjusting > >> ->cmd_len in the process? > >> > >> Then rq_set_cdb() would be > >> > >> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) > >> { > >> rq->cmd = cdb; > >> rq->cmd_len = cdb_len; > >> } > >> > >> and rq_get_cdb() plus rq_get_cdb_len() could just go away. > >> > > > > Because this way it is dangerous if large commands are issued to legacy > > drivers. In scsi-land we have .cmd_len at host template that will govern if > > we are allow to issue larger commands to the driver. In block devices we do > > not have such a facility, and the danger is if such commands are issued through > > bsg or other means, even by malicious code. What you say is the ideal and it > > is what I've done for scsi, but for block devices we can not do that yet. > > With the way I did it here, Legacy drivers will see zero length command and > > will do the right thing, from what I've seen. > > > > Boaz > > > > I forgot to say. > With the proposed way, we are saving the space of the pointer. And the final outcome > of eventually eliminating the buffer, is the same. > > Let me summarize. > - support extended, arbitrary large commands by introducing the notion that cdb space > can be pointed to not carried. > - Eventually transition all block drivers and users to the new system, for all commands > not just large ones. > - Do so without introducing any extra cost or instability, but also let the transition > be done gradually, and not at once, (hence more stability). > > I have thought about that long and hard, my first patch of the matter was 18 month ago. > I still think this is the smoothest way to go, and not that ugly, really. OK, thanks for giving it some thought. I don't like the initial way of doing this (I DO think it's ugly), but as long as there are plans to make it smoother along the way, it's ok with me. -- Jens Axboe ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-06 9:35 ` Boaz Harrosh 2008-04-06 11:05 ` Boaz Harrosh @ 2008-04-12 5:52 ` FUJITA Tomonori 2008-04-13 9:13 ` Boaz Harrosh 2008-04-13 14:07 ` [PATCH 2/3 ver2] block layer extended-cdb support James Bottomley 1 sibling, 2 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-12 5:52 UTC (permalink / raw) To: bharrosh; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm On Sun, 06 Apr 2008 12:35:04 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > > On Thu, Apr 03 2008, Boaz Harrosh wrote: > >> static void req_bio_endio(struct request *rq, struct bio *bio, > >> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > >> index 6f79d40..2f87c9d 100644 > >> --- a/include/linux/blkdev.h > >> +++ b/include/linux/blkdev.h > >> @@ -213,8 +213,15 @@ struct request { > >> /* > >> * when request is used as a packet command carrier > >> */ > >> - unsigned int cmd_len; > >> - unsigned char cmd[BLK_MAX_CDB]; > >> + unsigned short cmd_len; > >> + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ > >> + union { > >> + unsigned char cmd[BLK_MAX_CDB]; > >> + unsigned char *ext_cdb;/* an optional extended cdb. > >> + * points to a user buffer that must > >> + * be valid until end of request > >> + */ > >> + }; > > > > Why not just something ala > > > > unsigned short cmd_len; > > unsigned char __cmd[BLK_MAX_CDB]; > > unsigned char *cmd; > > > > and then have rq_init() do > > > > rq->cmd = rq->__cmd; > > > > and just have a function for setting up a larger ->cmd and adjusting > > ->cmd_len in the process? > > > > Then rq_set_cdb() would be > > > > static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) > > { > > rq->cmd = cdb; > > rq->cmd_len = cdb_len; > > } > > > > and rq_get_cdb() plus rq_get_cdb_len() could just go away. > > > > Because this way it is dangerous if large commands are issued to legacy > drivers. In scsi-land we have .cmd_len at host template that will govern if > we are allow to issue larger commands to the driver. In block devices we do > not have such a facility, and the danger is if such commands are issued through > bsg or other means, even by malicious code. What you say is the ideal and it > is what I've done for scsi, but for block devices we can not do that yet. > With the way I did it here, Legacy drivers will see zero length command and > will do the right thing, from what I've seen. What are exactly block devices? ub and ide? bsg are created only for scsi devices (and scsi objects like sas host) now. Are there other means to send commands except for ioctl? ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-12 5:52 ` FUJITA Tomonori @ 2008-04-13 9:13 ` Boaz Harrosh 2008-04-13 16:17 ` FUJITA Tomonori 2008-04-13 14:07 ` [PATCH 2/3 ver2] block layer extended-cdb support James Bottomley 1 sibling, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-13 9:13 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm On Sat, Apr 12 2008 at 8:52 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > On Sun, 06 Apr 2008 12:35:04 +0300 > Boaz Harrosh <bharrosh@panasas.com> wrote: > >> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: >>> On Thu, Apr 03 2008, Boaz Harrosh wrote: >>>> static void req_bio_endio(struct request *rq, struct bio *bio, >>>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h >>>> index 6f79d40..2f87c9d 100644 >>>> --- a/include/linux/blkdev.h >>>> +++ b/include/linux/blkdev.h >>>> @@ -213,8 +213,15 @@ struct request { >>>> /* >>>> * when request is used as a packet command carrier >>>> */ >>>> - unsigned int cmd_len; >>>> - unsigned char cmd[BLK_MAX_CDB]; >>>> + unsigned short cmd_len; >>>> + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ >>>> + union { >>>> + unsigned char cmd[BLK_MAX_CDB]; >>>> + unsigned char *ext_cdb;/* an optional extended cdb. >>>> + * points to a user buffer that must >>>> + * be valid until end of request >>>> + */ >>>> + }; >>> Why not just something ala >>> >>> unsigned short cmd_len; >>> unsigned char __cmd[BLK_MAX_CDB]; >>> unsigned char *cmd; >>> >>> and then have rq_init() do >>> >>> rq->cmd = rq->__cmd; >>> >>> and just have a function for setting up a larger ->cmd and adjusting >>> ->cmd_len in the process? >>> >>> Then rq_set_cdb() would be >>> >>> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) >>> { >>> rq->cmd = cdb; >>> rq->cmd_len = cdb_len; >>> } >>> >>> and rq_get_cdb() plus rq_get_cdb_len() could just go away. >>> >> Because this way it is dangerous if large commands are issued to legacy >> drivers. In scsi-land we have .cmd_len at host template that will govern if >> we are allow to issue larger commands to the driver. In block devices we do >> not have such a facility, and the danger is if such commands are issued through >> bsg or other means, even by malicious code. What you say is the ideal and it >> is what I've done for scsi, but for block devices we can not do that yet. >> With the way I did it here, Legacy drivers will see zero length command and >> will do the right thing, from what I've seen. > > What are exactly block devices? ub and ide? > > bsg are created only for scsi devices (and scsi objects like sas host) > now. Are there other means to send commands except for ioctl? I'm not 100% sure either way, so I would like to be safe. Any way, there is the size issue, this way we add *nothing* at all, so it looks preferable. The final outcome will be the same both ways. I would like if you reconsider the ugliness issue. I admit that at first I personally disliked it, but now that I look at it, I think it is cleaner, coding style, this way. Because the union points out the exclusiveness of the two systems, the striate way give the notion of two separate systems. Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-13 9:13 ` Boaz Harrosh @ 2008-04-13 16:17 ` FUJITA Tomonori 2008-04-13 16:50 ` Boaz Harrosh 2008-04-14 10:50 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori 0 siblings, 2 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-13 16:17 UTC (permalink / raw) To: bharrosh Cc: fujita.tomonori, jens.axboe, James.Bottomley, hch, linux-scsi, akpm On Sun, 13 Apr 2008 12:13:18 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > On Sat, Apr 12 2008 at 8:52 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > > On Sun, 06 Apr 2008 12:35:04 +0300 > > Boaz Harrosh <bharrosh@panasas.com> wrote: > > > >> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > >>> On Thu, Apr 03 2008, Boaz Harrosh wrote: > >>>> static void req_bio_endio(struct request *rq, struct bio *bio, > >>>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > >>>> index 6f79d40..2f87c9d 100644 > >>>> --- a/include/linux/blkdev.h > >>>> +++ b/include/linux/blkdev.h > >>>> @@ -213,8 +213,15 @@ struct request { > >>>> /* > >>>> * when request is used as a packet command carrier > >>>> */ > >>>> - unsigned int cmd_len; > >>>> - unsigned char cmd[BLK_MAX_CDB]; > >>>> + unsigned short cmd_len; > >>>> + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ > >>>> + union { > >>>> + unsigned char cmd[BLK_MAX_CDB]; > >>>> + unsigned char *ext_cdb;/* an optional extended cdb. > >>>> + * points to a user buffer that must > >>>> + * be valid until end of request > >>>> + */ > >>>> + }; > >>> Why not just something ala > >>> > >>> unsigned short cmd_len; > >>> unsigned char __cmd[BLK_MAX_CDB]; > >>> unsigned char *cmd; > >>> > >>> and then have rq_init() do > >>> > >>> rq->cmd = rq->__cmd; > >>> > >>> and just have a function for setting up a larger ->cmd and adjusting > >>> ->cmd_len in the process? > >>> > >>> Then rq_set_cdb() would be > >>> > >>> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) > >>> { > >>> rq->cmd = cdb; > >>> rq->cmd_len = cdb_len; > >>> } > >>> > >>> and rq_get_cdb() plus rq_get_cdb_len() could just go away. > >>> > >> Because this way it is dangerous if large commands are issued to legacy > >> drivers. In scsi-land we have .cmd_len at host template that will govern if > >> we are allow to issue larger commands to the driver. In block devices we do > >> not have such a facility, and the danger is if such commands are issued through > >> bsg or other means, even by malicious code. What you say is the ideal and it > >> is what I've done for scsi, but for block devices we can not do that yet. > >> With the way I did it here, Legacy drivers will see zero length command and > >> will do the right thing, from what I've seen. > > > > What are exactly block devices? ub and ide? > > > > bsg are created only for scsi devices (and scsi objects like sas host) > > now. Are there other means to send commands except for ioctl? > > I'm not 100% sure either way, so I would like to be safe. Any way, there > is the size issue, this way we add *nothing* at all, so it looks preferable. > The final outcome will be the same both ways. I think that a clean design is an important issue than the sizeof of struct request. > I would like if you reconsider the ugliness issue. I admit that at first I > personally disliked it, but now that I look at it, I think it is cleaner, > coding style, this way. Because the union points out the exclusiveness of > the two systems, the striate way give the notion of two separate systems. That's a ugly hack for me. Why do we have two separate systems to represent the command length? If the command length is smaller than 16 bytes, we use cmd_len. If the length is larger than 16 bytes, we use varlen_cdb_len? For me, as Jens proposed, having only cmd_len is the right way. And 'cdb' name is not appropriate for the block layer, I think. I agreed that changing the block layer and the scsi midlayer gradually is a safe option. Shortly, I'll send patches to clean up the hack on the top of your patchset. ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-13 16:17 ` FUJITA Tomonori @ 2008-04-13 16:50 ` Boaz Harrosh 2008-04-14 9:49 ` [PATCH 2/3 ver3] " Boaz Harrosh 2008-04-14 11:04 ` [PATCH 2/3 ver2] " FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori 1 sibling, 2 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-13 16:50 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > On Sun, 13 Apr 2008 12:13:18 +0300 > Boaz Harrosh <bharrosh@panasas.com> wrote: > >> On Sat, Apr 12 2008 at 8:52 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: >>> On Sun, 06 Apr 2008 12:35:04 +0300 >>> Boaz Harrosh <bharrosh@panasas.com> wrote: >>> >>>> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: >>>>> On Thu, Apr 03 2008, Boaz Harrosh wrote: >>>>>> static void req_bio_endio(struct request *rq, struct bio *bio, >>>>>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h >>>>>> index 6f79d40..2f87c9d 100644 >>>>>> --- a/include/linux/blkdev.h >>>>>> +++ b/include/linux/blkdev.h >>>>>> @@ -213,8 +213,15 @@ struct request { >>>>>> /* >>>>>> * when request is used as a packet command carrier >>>>>> */ >>>>>> - unsigned int cmd_len; >>>>>> - unsigned char cmd[BLK_MAX_CDB]; >>>>>> + unsigned short cmd_len; >>>>>> + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ >>>>>> + union { >>>>>> + unsigned char cmd[BLK_MAX_CDB]; >>>>>> + unsigned char *ext_cdb;/* an optional extended cdb. >>>>>> + * points to a user buffer that must >>>>>> + * be valid until end of request >>>>>> + */ >>>>>> + }; >>>>> Why not just something ala >>>>> >>>>> unsigned short cmd_len; >>>>> unsigned char __cmd[BLK_MAX_CDB]; >>>>> unsigned char *cmd; >>>>> >>>>> and then have rq_init() do >>>>> >>>>> rq->cmd = rq->__cmd; >>>>> >>>>> and just have a function for setting up a larger ->cmd and adjusting >>>>> ->cmd_len in the process? >>>>> >>>>> Then rq_set_cdb() would be >>>>> >>>>> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) >>>>> { >>>>> rq->cmd = cdb; >>>>> rq->cmd_len = cdb_len; >>>>> } >>>>> >>>>> and rq_get_cdb() plus rq_get_cdb_len() could just go away. >>>>> >>>> Because this way it is dangerous if large commands are issued to legacy >>>> drivers. In scsi-land we have .cmd_len at host template that will govern if >>>> we are allow to issue larger commands to the driver. In block devices we do >>>> not have such a facility, and the danger is if such commands are issued through >>>> bsg or other means, even by malicious code. What you say is the ideal and it >>>> is what I've done for scsi, but for block devices we can not do that yet. >>>> With the way I did it here, Legacy drivers will see zero length command and >>>> will do the right thing, from what I've seen. >>> What are exactly block devices? ub and ide? >>> >>> bsg are created only for scsi devices (and scsi objects like sas host) >>> now. Are there other means to send commands except for ioctl? >> I'm not 100% sure either way, so I would like to be safe. Any way, there >> is the size issue, this way we add *nothing* at all, so it looks preferable. >> The final outcome will be the same both ways. > > I think that a clean design is an important issue than the sizeof of > struct request. > > >> I would like if you reconsider the ugliness issue. I admit that at first I >> personally disliked it, but now that I look at it, I think it is cleaner, >> coding style, this way. Because the union points out the exclusiveness of >> the two systems, the striate way give the notion of two separate systems. > > That's a ugly hack for me. > > Why do we have two separate systems to represent the command length? > If the command length is smaller than 16 bytes, we use cmd_len. If the > length is larger than 16 bytes, we use varlen_cdb_len? > > For me, as Jens proposed, having only cmd_len is the right way. > > And 'cdb' name is not appropriate for the block layer, I think. > > I agreed that changing the block layer and the scsi midlayer gradually > is a safe option. Shortly, I'll send patches to clean up the hack on > the top of your patchset. > -- Sorry TOMO, I was sending the ver2 patchset and only saw your mail in the middle, so anyway you have the latest I have now. If it's ok with you I will squash your patches onto mine and add your sign-off-by. There is no use putting code in the tree that will be changed immediately after. Please note that I'm a bit afraid to put code that has both length as one if you are more confident then me, I will take your word for it. Thanks for helping out, as you can see I did it very safe, but with your help maybe it can finally go in. Thanks++ Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 2/3 ver3] block layer extended-cdb support 2008-04-13 16:50 ` Boaz Harrosh @ 2008-04-14 9:49 ` Boaz Harrosh 2008-04-14 11:04 ` FUJITA Tomonori 2008-04-14 11:04 ` [PATCH 2/3 ver2] " FUJITA Tomonori 1 sibling, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-14 9:49 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: > On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: >> On Sun, 13 Apr 2008 12:13:18 +0300 >> Boaz Harrosh <bharrosh@panasas.com> wrote: >> >> That's a ugly hack for me. >> >> Why do we have two separate systems to represent the command length? >> If the command length is smaller than 16 bytes, we use cmd_len. If the >> length is larger than 16 bytes, we use varlen_cdb_len? >> >> For me, as Jens proposed, having only cmd_len is the right way. >> >> And 'cdb' name is not appropriate for the block layer, I think. >> >> I agreed that changing the block layer and the scsi midlayer gradually >> is a safe option. Shortly, I'll send patches to clean up the hack on >> the top of your patchset. >> -- > > Sorry TOMO, I was sending the ver2 patchset and only saw your mail in > the middle, so anyway you have the latest I have now. > > If it's ok with you I will squash your patches onto mine and add your > sign-off-by. There is no use putting code in the tree that will be changed > immediately after. > > Please note that I'm a bit afraid to put code that has both length as one > if you are more confident then me, I will take your word for it. > > Thanks for helping out, as you can see I did it very safe, but with your > help maybe it can finally go in. Thanks++ > > Boaz > -- Maybe you mean something like below. I changed cdb => cmd and I use one cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB right there next to it. But if you don't like it then I don't mind to change the name, I think it was James idea. But please note!!! I think having one cmd_len is DANGEROUS. And it forces a full code audit to be sure, has with my approach we are much more safe. There, I said it. --- From: Boaz Harrosh <bharrosh@panasas.com> Date: Wed, 31 Oct 2007 14:56:09 +0200 Subject: [PATCH] block layer extended-command support - add ext_cmd to hold a large external cdb if needed. Allocation of buffer must be done by user and held until request execution is done. - Since there can be either a fix_length command up to 16 bytes or an external extended command but never both, we hold the two types in a union to save space. cmd_len > BLK_MAX_CDB signals an ext_cmd mode. - Use new rq_set_cmd() to set everything properly. - Use rq_get_cmd() to retrieve the command in a generic way. - Once all drivers and users convert to the new accessors the cmd[] 16 bytes buffer can be discarded. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- block/blk-core.c | 2 ++ include/linux/blkdev.h | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 2a438a9..a2bf07f 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq) rq->end_io = NULL; rq->end_io_data = NULL; rq->next_rq = NULL; + rq->cmd_len = 0; + rq->ext_cmd = NULL; } static void req_bio_endio(struct request *rq, struct bio *bio, diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 6f79d40..0c4f5f5 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -214,7 +214,13 @@ struct request { * when request is used as a packet command carrier */ unsigned int cmd_len; - unsigned char cmd[BLK_MAX_CDB]; + union { + unsigned char cmd[BLK_MAX_CDB]; + unsigned char *ext_cmd;/* an optional extended cdb. + * points to a user buffer that must + * be valid until end of request + */ + }; unsigned int data_len; unsigned int extra_len; /* length of alignment and padding */ @@ -484,6 +490,23 @@ enum { #define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC) #define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META) +static inline void rq_set_cmd(struct request *rq, u8 *cmd, short cmd_len) +{ + rq->cmd_len = cmd_len; + if (cmd_len <= BLK_MAX_CDB) + memcpy(rq->cmd, cmd, cmd_len); + else + rq->ext_cmd = cmd; +} + +static inline u8 *rq_get_cmd(struct request *rq) +{ + if (rq->cmd_len <= BLK_MAX_CDB) + return rq->cmd; + else + return rq->ext_cmd; +} + static inline int blk_queue_full(struct request_queue *q, int rw) { if (rw == READ) -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver3] block layer extended-cdb support 2008-04-14 9:49 ` [PATCH 2/3 ver3] " Boaz Harrosh @ 2008-04-14 11:04 ` FUJITA Tomonori 2008-04-14 11:28 ` Boaz Harrosh 0 siblings, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 11:04 UTC (permalink / raw) To: bharrosh Cc: fujita.tomonori, jens.axboe, James.Bottomley, hch, linux-scsi, akpm On Mon, 14 Apr 2008 12:49:49 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: > > On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > >> On Sun, 13 Apr 2008 12:13:18 +0300 > >> Boaz Harrosh <bharrosh@panasas.com> wrote: > >> > >> That's a ugly hack for me. > >> > >> Why do we have two separate systems to represent the command length? > >> If the command length is smaller than 16 bytes, we use cmd_len. If the > >> length is larger than 16 bytes, we use varlen_cdb_len? > >> > >> For me, as Jens proposed, having only cmd_len is the right way. > >> > >> And 'cdb' name is not appropriate for the block layer, I think. > >> > >> I agreed that changing the block layer and the scsi midlayer gradually > >> is a safe option. Shortly, I'll send patches to clean up the hack on > >> the top of your patchset. > >> -- > > > > Sorry TOMO, I was sending the ver2 patchset and only saw your mail in > > the middle, so anyway you have the latest I have now. > > > > If it's ok with you I will squash your patches onto mine and add your > > sign-off-by. There is no use putting code in the tree that will be changed > > immediately after. > > > > Please note that I'm a bit afraid to put code that has both length as one > > if you are more confident then me, I will take your word for it. > > > > Thanks for helping out, as you can see I did it very safe, but with your > > help maybe it can finally go in. Thanks++ > > > > Boaz > > -- > Maybe you mean something like below. I changed cdb => cmd and I use one > cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB > right there next to it. But if you don't like it then I don't mind to > change the name, I think it was James idea. I don't. I've been talking mainly about how to represent the length of command. About 'cdb' name, I thought that there is a better name than BLK_MAX_CDB. But it's up to Jens. > But please note!!! > I think having one cmd_len is DANGEROUS. And it forces a full code audit > to be sure, has with my approach we are much more safe. There, I said it. Could you be more specific? So far, you have not explained how it can be dangerous. ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver3] block layer extended-cdb support 2008-04-14 11:04 ` FUJITA Tomonori @ 2008-04-14 11:28 ` Boaz Harrosh 2008-04-14 12:08 ` FUJITA Tomonori 0 siblings, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-14 11:28 UTC (permalink / raw) To: FUJITA Tomonori Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm, Pete Wyckoff On Mon, Apr 14 2008 at 14:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > On Mon, 14 Apr 2008 12:49:49 +0300 > Boaz Harrosh <bharrosh@panasas.com> wrote: > >> On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: >>> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: >>>> On Sun, 13 Apr 2008 12:13:18 +0300 >>>> Boaz Harrosh <bharrosh@panasas.com> wrote: >>>> >>>> That's a ugly hack for me. >>>> >>>> Why do we have two separate systems to represent the command length? >>>> If the command length is smaller than 16 bytes, we use cmd_len. If the >>>> length is larger than 16 bytes, we use varlen_cdb_len? >>>> >>>> For me, as Jens proposed, having only cmd_len is the right way. >>>> >>>> And 'cdb' name is not appropriate for the block layer, I think. >>>> >>>> I agreed that changing the block layer and the scsi midlayer gradually >>>> is a safe option. Shortly, I'll send patches to clean up the hack on >>>> the top of your patchset. >>>> -- >>> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in >>> the middle, so anyway you have the latest I have now. >>> >>> If it's ok with you I will squash your patches onto mine and add your >>> sign-off-by. There is no use putting code in the tree that will be changed >>> immediately after. >>> >>> Please note that I'm a bit afraid to put code that has both length as one >>> if you are more confident then me, I will take your word for it. >>> >>> Thanks for helping out, as you can see I did it very safe, but with your >>> help maybe it can finally go in. Thanks++ >>> >>> Boaz >>> -- >> Maybe you mean something like below. I changed cdb => cmd and I use one >> cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB >> right there next to it. But if you don't like it then I don't mind to >> change the name, I think it was James idea. > > I don't. I've been talking mainly about how to represent the length of > command. > > About 'cdb' name, I thought that there is a better name than > BLK_MAX_CDB. But it's up to Jens. > > >> But please note!!! >> I think having one cmd_len is DANGEROUS. And it forces a full code audit >> to be sure, has with my approach we are much more safe. There, I said it. > > Could you be more specific? So far, you have not explained how it can > be dangerous. There is a pending patch by Pete, and our main goal, is to push OSD commands through bsg. All over the kernel there are cooked up char-devices, like in gdth, that do vendor specific management commands. All these, and future, special-command can go from user-mode through bsg in a common way. Via support of vendor specific and extended commands. All the new scsi defined commands that are bigger then 16 are not going to be sent through sg, but through bsg right? So we do want to use this facility from kernel and from user-land but we need some protection. In scsi LLDs we have .max_cmnd but block devices don't have that. So either you need to restrict what can be done, or play it safe like I did. Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver3] block layer extended-cdb support 2008-04-14 11:28 ` Boaz Harrosh @ 2008-04-14 12:08 ` FUJITA Tomonori 2008-04-14 12:22 ` Boaz Harrosh 0 siblings, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 12:08 UTC (permalink / raw) To: bharrosh Cc: fujita.tomonori, jens.axboe, James.Bottomley, hch, linux-scsi, akpm, pw On Mon, 14 Apr 2008 14:28:45 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > On Mon, Apr 14 2008 at 14:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > > On Mon, 14 Apr 2008 12:49:49 +0300 > > Boaz Harrosh <bharrosh@panasas.com> wrote: > > > >> On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: > >>> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > >>>> On Sun, 13 Apr 2008 12:13:18 +0300 > >>>> Boaz Harrosh <bharrosh@panasas.com> wrote: > >>>> > >>>> That's a ugly hack for me. > >>>> > >>>> Why do we have two separate systems to represent the command length? > >>>> If the command length is smaller than 16 bytes, we use cmd_len. If the > >>>> length is larger than 16 bytes, we use varlen_cdb_len? > >>>> > >>>> For me, as Jens proposed, having only cmd_len is the right way. > >>>> > >>>> And 'cdb' name is not appropriate for the block layer, I think. > >>>> > >>>> I agreed that changing the block layer and the scsi midlayer gradually > >>>> is a safe option. Shortly, I'll send patches to clean up the hack on > >>>> the top of your patchset. > >>>> -- > >>> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in > >>> the middle, so anyway you have the latest I have now. > >>> > >>> If it's ok with you I will squash your patches onto mine and add your > >>> sign-off-by. There is no use putting code in the tree that will be changed > >>> immediately after. > >>> > >>> Please note that I'm a bit afraid to put code that has both length as one > >>> if you are more confident then me, I will take your word for it. > >>> > >>> Thanks for helping out, as you can see I did it very safe, but with your > >>> help maybe it can finally go in. Thanks++ > >>> > >>> Boaz > >>> -- > >> Maybe you mean something like below. I changed cdb => cmd and I use one > >> cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB > >> right there next to it. But if you don't like it then I don't mind to > >> change the name, I think it was James idea. > > > > I don't. I've been talking mainly about how to represent the length of > > command. > > > > About 'cdb' name, I thought that there is a better name than > > BLK_MAX_CDB. But it's up to Jens. > > > > > >> But please note!!! > >> I think having one cmd_len is DANGEROUS. And it forces a full code audit > >> to be sure, has with my approach we are much more safe. There, I said it. > > > > Could you be more specific? So far, you have not explained how it can > > be dangerous. > > There is a pending patch by Pete, and our main goal, is to push OSD commands > through bsg. All over the kernel there are cooked up char-devices, like in > gdth, that do vendor specific management commands. All these, and future, > special-command can go from user-mode through bsg in a common way. Via support > of vendor specific and extended commands. All the new scsi defined commands > that are bigger then 16 are not going to be sent through sg, but through > bsg right? So we do want to use this facility from kernel and from user-land > but we need some protection. In scsi LLDs we have .max_cmnd but block devices > don't have that. So either you need to restrict what can be done, or play it safe > like I did. If we creates bsg devices for block devices, of course, we need to a mechanism to govern the length of commands. But why do you want to create bsg devices for block devices? If block devices want large commands for some reasons, their bsg hook functions need to handle the length of commands anyway. There is no reason that the block layer has two values to represent one item, the length of command. If we want to govern the command length in a common place, then I think that it would be better to add the limit to request queue. And again, what are your block devices? What do they want bsg for? ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver3] block layer extended-cdb support 2008-04-14 12:08 ` FUJITA Tomonori @ 2008-04-14 12:22 ` Boaz Harrosh 0 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-14 12:22 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: jens.axboe, James.Bottomley, hch, linux-scsi, akpm, pw On Mon, Apr 14 2008 at 15:08 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > On Mon, 14 Apr 2008 14:28:45 +0300 > Boaz Harrosh <bharrosh@panasas.com> wrote: > >> On Mon, Apr 14 2008 at 14:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: >>> On Mon, 14 Apr 2008 12:49:49 +0300 >>> Boaz Harrosh <bharrosh@panasas.com> wrote: >>> >>>> On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: >>>>> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: >>>>>> On Sun, 13 Apr 2008 12:13:18 +0300 >>>>>> Boaz Harrosh <bharrosh@panasas.com> wrote: >>>>>> >>>>>> That's a ugly hack for me. >>>>>> >>>>>> Why do we have two separate systems to represent the command length? >>>>>> If the command length is smaller than 16 bytes, we use cmd_len. If the >>>>>> length is larger than 16 bytes, we use varlen_cdb_len? >>>>>> >>>>>> For me, as Jens proposed, having only cmd_len is the right way. >>>>>> >>>>>> And 'cdb' name is not appropriate for the block layer, I think. >>>>>> >>>>>> I agreed that changing the block layer and the scsi midlayer gradually >>>>>> is a safe option. Shortly, I'll send patches to clean up the hack on >>>>>> the top of your patchset. >>>>>> -- >>>>> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in >>>>> the middle, so anyway you have the latest I have now. >>>>> >>>>> If it's ok with you I will squash your patches onto mine and add your >>>>> sign-off-by. There is no use putting code in the tree that will be changed >>>>> immediately after. >>>>> >>>>> Please note that I'm a bit afraid to put code that has both length as one >>>>> if you are more confident then me, I will take your word for it. >>>>> >>>>> Thanks for helping out, as you can see I did it very safe, but with your >>>>> help maybe it can finally go in. Thanks++ >>>>> >>>>> Boaz >>>>> -- >>>> Maybe you mean something like below. I changed cdb => cmd and I use one >>>> cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB >>>> right there next to it. But if you don't like it then I don't mind to >>>> change the name, I think it was James idea. >>> I don't. I've been talking mainly about how to represent the length of >>> command. >>> >>> About 'cdb' name, I thought that there is a better name than >>> BLK_MAX_CDB. But it's up to Jens. >>> >>> >>>> But please note!!! >>>> I think having one cmd_len is DANGEROUS. And it forces a full code audit >>>> to be sure, has with my approach we are much more safe. There, I said it. >>> Could you be more specific? So far, you have not explained how it can >>> be dangerous. >> There is a pending patch by Pete, and our main goal, is to push OSD commands >> through bsg. All over the kernel there are cooked up char-devices, like in >> gdth, that do vendor specific management commands. All these, and future, >> special-command can go from user-mode through bsg in a common way. Via support >> of vendor specific and extended commands. All the new scsi defined commands >> that are bigger then 16 are not going to be sent through sg, but through >> bsg right? So we do want to use this facility from kernel and from user-land >> but we need some protection. In scsi LLDs we have .max_cmnd but block devices >> don't have that. So either you need to restrict what can be done, or play it safe >> like I did. > > If we creates bsg devices for block devices, of course, we need to a > mechanism to govern the length of commands. > > But why do you want to create bsg devices for block devices? If block > devices want large commands for some reasons, their bsg hook functions > need to handle the length of commands anyway. There is no reason that > the block layer has two values to represent one item, the length of > command. > > If we want to govern the command length in a common place, then I > think that it would be better to add the limit to request queue. > > And again, what are your block devices? What do they want bsg for? > -- I don't have any block devices personally. I just thought that the diff between sg a bsg is that bsg will support any block device, so I guess I was wrong, bsg is a user-to-scsi bridge just like sg is. I thought bsg registers on every request_queue, how does bsg filter which devices to export and which not? What about the union, don't we care about the space saved? Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-13 16:50 ` Boaz Harrosh 2008-04-14 9:49 ` [PATCH 2/3 ver3] " Boaz Harrosh @ 2008-04-14 11:04 ` FUJITA Tomonori 1 sibling, 0 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 11:04 UTC (permalink / raw) To: bharrosh Cc: fujita.tomonori, jens.axboe, James.Bottomley, hch, linux-scsi, akpm On Sun, 13 Apr 2008 19:50:26 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > > On Sun, 13 Apr 2008 12:13:18 +0300 > > Boaz Harrosh <bharrosh@panasas.com> wrote: > > > >> On Sat, Apr 12 2008 at 8:52 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > >>> On Sun, 06 Apr 2008 12:35:04 +0300 > >>> Boaz Harrosh <bharrosh@panasas.com> wrote: > >>> > >>>> On Fri, Apr 04 2008 at 14:46 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > >>>>> On Thu, Apr 03 2008, Boaz Harrosh wrote: > >>>>>> static void req_bio_endio(struct request *rq, struct bio *bio, > >>>>>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > >>>>>> index 6f79d40..2f87c9d 100644 > >>>>>> --- a/include/linux/blkdev.h > >>>>>> +++ b/include/linux/blkdev.h > >>>>>> @@ -213,8 +213,15 @@ struct request { > >>>>>> /* > >>>>>> * when request is used as a packet command carrier > >>>>>> */ > >>>>>> - unsigned int cmd_len; > >>>>>> - unsigned char cmd[BLK_MAX_CDB]; > >>>>>> + unsigned short cmd_len; > >>>>>> + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ > >>>>>> + union { > >>>>>> + unsigned char cmd[BLK_MAX_CDB]; > >>>>>> + unsigned char *ext_cdb;/* an optional extended cdb. > >>>>>> + * points to a user buffer that must > >>>>>> + * be valid until end of request > >>>>>> + */ > >>>>>> + }; > >>>>> Why not just something ala > >>>>> > >>>>> unsigned short cmd_len; > >>>>> unsigned char __cmd[BLK_MAX_CDB]; > >>>>> unsigned char *cmd; > >>>>> > >>>>> and then have rq_init() do > >>>>> > >>>>> rq->cmd = rq->__cmd; > >>>>> > >>>>> and just have a function for setting up a larger ->cmd and adjusting > >>>>> ->cmd_len in the process? > >>>>> > >>>>> Then rq_set_cdb() would be > >>>>> > >>>>> static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) > >>>>> { > >>>>> rq->cmd = cdb; > >>>>> rq->cmd_len = cdb_len; > >>>>> } > >>>>> > >>>>> and rq_get_cdb() plus rq_get_cdb_len() could just go away. > >>>>> > >>>> Because this way it is dangerous if large commands are issued to legacy > >>>> drivers. In scsi-land we have .cmd_len at host template that will govern if > >>>> we are allow to issue larger commands to the driver. In block devices we do > >>>> not have such a facility, and the danger is if such commands are issued through > >>>> bsg or other means, even by malicious code. What you say is the ideal and it > >>>> is what I've done for scsi, but for block devices we can not do that yet. > >>>> With the way I did it here, Legacy drivers will see zero length command and > >>>> will do the right thing, from what I've seen. > >>> What are exactly block devices? ub and ide? > >>> > >>> bsg are created only for scsi devices (and scsi objects like sas host) > >>> now. Are there other means to send commands except for ioctl? > >> I'm not 100% sure either way, so I would like to be safe. Any way, there > >> is the size issue, this way we add *nothing* at all, so it looks preferable. > >> The final outcome will be the same both ways. > > > > I think that a clean design is an important issue than the sizeof of > > struct request. > > > > > >> I would like if you reconsider the ugliness issue. I admit that at first I > >> personally disliked it, but now that I look at it, I think it is cleaner, > >> coding style, this way. Because the union points out the exclusiveness of > >> the two systems, the striate way give the notion of two separate systems. > > > > That's a ugly hack for me. > > > > Why do we have two separate systems to represent the command length? > > If the command length is smaller than 16 bytes, we use cmd_len. If the > > length is larger than 16 bytes, we use varlen_cdb_len? > > > > For me, as Jens proposed, having only cmd_len is the right way. > > > > And 'cdb' name is not appropriate for the block layer, I think. > > > > I agreed that changing the block layer and the scsi midlayer gradually > > is a safe option. Shortly, I'll send patches to clean up the hack on > > the top of your patchset. > > -- > > Sorry TOMO, I was sending the ver2 patchset and only saw your mail in > the middle, so anyway you have the latest I have now. > > If it's ok with you I will squash your patches onto mine and add your > sign-off-by. There is no use putting code in the tree that will be changed > immediately after. There is no mergeable stuff between yours and my patchset. I've just sent four patches. The first three patches are not related your patchset (they are cleanups for changing rq->cmd from the static array to a pointer). The fourth patch is a substitute for your second patch. Nothing are common between them. > Please note that I'm a bit afraid to put code that has both length as one > if you are more confident then me, I will take your word for it. > > Thanks for helping out, as you can see I did it very safe, but with your > help maybe it can finally go in. Thanks++ > > Boaz > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 0/4] add large command support to the block layer 2008-04-13 16:17 ` FUJITA Tomonori 2008-04-13 16:50 ` Boaz Harrosh @ 2008-04-14 10:50 ` FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori ` (3 more replies) 1 sibling, 4 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw) To: linux-scsi Cc: bharrosh, Jens Axboe, Bartlomiej Zolnierkiewicz, James Bottomley, Alasdair G Kergon, Geert Uytterhoeven, FUJITA Tomonori This patchset adds large command support to the block layer. We rarely handle large commands. So for optimization, a struct request still has a static array for a command. rq_init sets rq->cmd pointer to the static array. In short, rq_init() does rq->cmd = rq->__cmd; So we can access to rq->cmd and rq->cmd_len as before. Boaz argues that having single cmd_len is dangerous: > Because this way it is dangerous if large commands are issued to legacy > drivers. In scsi-land we have .cmd_len at host template that will govern if > we are allow to issue larger commands to the driver. In block devices we do > not have such a facility, and the danger is if such commands are issued through > bsg or other means, even by malicious code. What you say is the ideal and it I don't see how it is dangerous. We don't send large commands to block devices via bsg. We can send large commands to block devices via only SG_IO. SG_IO (block/scsi_ioctl.c) forbids us sending commands large than 16 bytes, BLK_MAX_CDB. So how can we send large commands to block devices? The first, second, and third patches are safe cleanups (a preparation for changing rq->cmd from the static array to a pointer). They don't conflict with Boaz's patchset. Even if we choose Boaz's approach now, we'll move to the approach to have one command length in struct request in the long term. So they can be applied now. The forth patch adds large command support. It's a substitute for Boaz's second patch. It's pretty simple except for one hack for ide-io. It's necessary since the ide subsystem allocates struct request without using blk_get_request. In the long term, it would better to convert it to use blk_get_request properly. ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook 2008-04-14 10:50 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori @ 2008-04-14 10:50 ` FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 2/4] block: no need to initialize rq->cmd with blk_get_request FUJITA Tomonori 2008-04-14 11:21 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori ` (2 subsequent siblings) 3 siblings, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw) To: linux-scsi Cc: bharrosh, FUJITA Tomonori, Geert Uytterhoeven, James Bottomley, Jens Axboe The block layer initializes rq->cmd (queue_flush calls rq_init) so prepare_flush_fn hooks don't need to do that. This is a preparation for changing rq->cmd from the static array to a pointer. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Jens Axboe <jens.axboe@oracle.com> --- drivers/block/ps3disk.c | 1 - drivers/scsi/sd.c | 1 - 2 files changed, 0 insertions(+), 2 deletions(-) diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 7483f94..9c32b75 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -406,7 +406,6 @@ static void ps3disk_prepare_flush(struct request_queue *q, struct request *req) dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); - memset(req->cmd, 0, sizeof(req->cmd)); req->cmd_type = REQ_TYPE_FLUSH; } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 5fe7aae..338566a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -850,7 +850,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp) static void sd_prepare_flush(struct request_queue *q, struct request *rq) { - memset(rq->cmd, 0, sizeof(rq->cmd)); rq->cmd_type = REQ_TYPE_BLOCK_PC; rq->timeout = SD_TIMEOUT; rq->cmd[0] = SYNCHRONIZE_CACHE; -- 1.5.4.2 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH 2/4] block: no need to initialize rq->cmd with blk_get_request 2008-04-14 10:50 ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori @ 2008-04-14 10:50 ` FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 3/4] block: replace sizeof(rq->cmd) with BLK_MAX_CDB FUJITA Tomonori 0 siblings, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw) To: linux-scsi Cc: James Bottomley, bharrosh, FUJITA Tomonori, dm-devel, Jens Axboe, Alasdair G Kergon blk_get_request initializes rq->cmd (rq_init does) so the users don't need to do that. This is a preparation for changing rq->cmd from the static array to a pointer. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Alasdair G Kergon <agk@redhat.com> Cc: Jens Axboe <jens.axboe@oracle.com> --- block/scsi_ioctl.c | 3 --- drivers/block/pktcdvd.c | 2 -- drivers/cdrom/cdrom.c | 1 - drivers/md/dm-emc.c | 2 -- drivers/md/dm-mpath-hp-sw.c | 1 - drivers/md/dm-mpath-rdac.c | 1 - 6 files changed, 0 insertions(+), 10 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a2c3a93..ffa3720 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -217,8 +217,6 @@ EXPORT_SYMBOL_GPL(blk_verify_command); static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, struct sg_io_hdr *hdr, int has_write_perm) { - memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ - if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) return -EFAULT; if (blk_verify_command(rq->cmd, has_write_perm)) @@ -531,7 +529,6 @@ static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk, rq->data_len = 0; rq->extra_len = 0; rq->timeout = BLK_DEFAULT_SG_TIMEOUT; - memset(rq->cmd, 0, sizeof(rq->cmd)); rq->cmd[0] = cmd; rq->cmd[4] = data; rq->cmd_len = 6; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 18feb1c..3b806c9 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -776,8 +776,6 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * rq->cmd_len = COMMAND_SIZE(cgc->cmd[0]); memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE); - if (sizeof(rq->cmd) > CDROM_PACKET_SIZE) - memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE); rq->timeout = 60*HZ; rq->cmd_type = REQ_TYPE_BLOCK_PC; diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index ac38290..69f26eb 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2194,7 +2194,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, if (ret) break; - memset(rq->cmd, 0, sizeof(rq->cmd)); rq->cmd[0] = GPCMD_READ_CD; rq->cmd[1] = 1 << 2; rq->cmd[2] = (lba >> 24) & 0xff; diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index 6b91b9a..3ea5ad4 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c @@ -110,8 +110,6 @@ static struct request *get_failover_req(struct emc_handler *h, memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); rq->sense_len = 0; - memset(&rq->cmd, 0, BLK_MAX_CDB); - rq->timeout = EMC_FAILOVER_TIMEOUT; rq->cmd_type = REQ_TYPE_BLOCK_PC; rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE; diff --git a/drivers/md/dm-mpath-hp-sw.c b/drivers/md/dm-mpath-hp-sw.c index 204bf42..b63a0ab 100644 --- a/drivers/md/dm-mpath-hp-sw.c +++ b/drivers/md/dm-mpath-hp-sw.c @@ -137,7 +137,6 @@ static struct request *hp_sw_get_request(struct dm_path *path) req->sense = h->sense; memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE); - memset(&req->cmd, 0, BLK_MAX_CDB); req->cmd[0] = START_STOP; req->cmd[4] = 1; req->cmd_len = COMMAND_SIZE(req->cmd[0]); diff --git a/drivers/md/dm-mpath-rdac.c b/drivers/md/dm-mpath-rdac.c index e04eb5c..95e7773 100644 --- a/drivers/md/dm-mpath-rdac.c +++ b/drivers/md/dm-mpath-rdac.c @@ -284,7 +284,6 @@ static struct request *get_rdac_req(struct rdac_handler *h, return NULL; } - memset(&rq->cmd, 0, BLK_MAX_CDB); rq->sense = h->sense; memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); rq->sense_len = 0; -- 1.5.4.2 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH 3/4] block: replace sizeof(rq->cmd) with BLK_MAX_CDB 2008-04-14 10:50 ` [PATCH 2/4] block: no need to initialize rq->cmd with blk_get_request FUJITA Tomonori @ 2008-04-14 10:50 ` FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 4/4] block: add large command support FUJITA Tomonori 0 siblings, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw) To: linux-scsi Cc: bharrosh, FUJITA Tomonori, Bartlomiej Zolnierkiewicz, Jens Axboe, linux-ide This is a preparation for changing rq->cmd from the static array to a pointer. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Cc: Jens Axboe <jens.axboe@oracle.com> --- block/blk-core.c | 4 ++-- drivers/ide/ide-cd.c | 4 ++-- drivers/ide/ide-cd_verbose.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 2a438a9..6669238 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -132,7 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) rq->errors = 0; rq->ref_count = 1; rq->cmd_len = 0; - memset(rq->cmd, 0, sizeof(rq->cmd)); + memset(rq->cmd, 0, BLK_MAX_CDB); rq->data_len = 0; rq->extra_len = 0; rq->sense_len = 0; @@ -194,7 +194,7 @@ void blk_dump_rq_flags(struct request *rq, char *msg) if (blk_pc_request(rq)) { printk(KERN_INFO " cdb: "); - for (bit = 0; bit < sizeof(rq->cmd); bit++) + for (bit = 0; bit < BLK_MAX_CDB; bit++) printk("%02x ", rq->cmd[bit]); printk("\n"); } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index f8cea94..db29bde 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -879,7 +879,7 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive) sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS); - memset(rq->cmd, 0, sizeof(rq->cmd)); + memset(rq->cmd, 0, BLK_MAX_CDB); rq->cmd[0] = GPCMD_SEEK; put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]); @@ -1812,7 +1812,7 @@ static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) long block = (long)rq->hard_sector / (hard_sect >> 9); unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9); - memset(rq->cmd, 0, sizeof(rq->cmd)); + memset(rq->cmd, 0, BLK_MAX_CDB); if (rq_data_dir(rq) == READ) rq->cmd[0] = GPCMD_READ_10; diff --git a/drivers/ide/ide-cd_verbose.c b/drivers/ide/ide-cd_verbose.c index 6ed7ca0..6490a2d 100644 --- a/drivers/ide/ide-cd_verbose.c +++ b/drivers/ide/ide-cd_verbose.c @@ -326,7 +326,7 @@ void ide_cd_log_error(const char *name, struct request *failed_command, printk(KERN_ERR " The failed \"%s\" packet command " "was: \n \"", s); - for (i = 0; i < sizeof(failed_command->cmd); i++) + for (i = 0; i < BLK_MAX_CDB; i++) printk(KERN_CONT "%02x ", failed_command->cmd[i]); printk(KERN_CONT "\"\n"); } -- 1.5.4.2 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH 4/4] block: add large command support 2008-04-14 10:50 ` [PATCH 3/4] block: replace sizeof(rq->cmd) with BLK_MAX_CDB FUJITA Tomonori @ 2008-04-14 10:50 ` FUJITA Tomonori 2008-04-14 11:29 ` Jens Axboe ` (2 more replies) 0 siblings, 3 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 10:50 UTC (permalink / raw) To: linux-scsi; +Cc: bharrosh, FUJITA Tomonori, Jens Axboe, linux-ide This patch changes rq->cmd from the static array to a pointer to support large commands. We rarely handle large commands. So for optimization, a struct request still has a static array for a command. rq_init sets rq->cmd pointer to the static array. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: Jens Axboe <jens.axboe@oracle.com> --- block/blk-core.c | 1 + drivers/ide/ide-io.c | 1 + include/linux/blkdev.h | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 6669238..6f0968f 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) rq->errors = 0; rq->ref_count = 1; rq->cmd_len = 0; + rq->cmd = rq->__cmd; memset(rq->cmd, 0, BLK_MAX_CDB); rq->data_len = 0; rq->extra_len = 0; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 7153796..bac5ea1 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) { memset(rq, 0, sizeof(*rq)); rq->ref_count = 1; + rq->cmd = rq->__cmd; } EXPORT_SYMBOL(ide_init_drive_cmd); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index b3a58ad..5710ae4 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -215,8 +215,9 @@ struct request { /* * when request is used as a packet command carrier */ - unsigned int cmd_len; - unsigned char cmd[BLK_MAX_CDB]; + unsigned short cmd_len; + unsigned char __cmd[BLK_MAX_CDB]; + unsigned char *cmd; unsigned int data_len; unsigned int extra_len; /* length of alignment and padding */ @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p) page_cache_release(p.v); } +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd, + unsigned short cmd_len) +{ + rq->cmd = cmd; + rq->cmd_len = cmd_len; +} + struct work_struct; int kblockd_schedule_work(struct work_struct *work); void kblockd_flush_work(struct work_struct *work); -- 1.5.4.2 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-14 10:50 ` [PATCH 4/4] block: add large command support FUJITA Tomonori @ 2008-04-14 11:29 ` Jens Axboe 2008-04-14 12:08 ` FUJITA Tomonori 2008-04-15 22:50 ` Bartlomiej Zolnierkiewicz 2008-04-14 14:41 ` Pete Wyckoff 2008-04-15 7:29 ` Jens Axboe 2 siblings, 2 replies; 77+ messages in thread From: Jens Axboe @ 2008-04-14 11:29 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: linux-scsi, bharrosh, linux-ide On Mon, Apr 14 2008, FUJITA Tomonori wrote: > This patch changes rq->cmd from the static array to a pointer to > support large commands. > > We rarely handle large commands. So for optimization, a struct request > still has a static array for a command. rq_init sets rq->cmd pointer > to the static array. > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > Cc: Jens Axboe <jens.axboe@oracle.com> > --- > block/blk-core.c | 1 + > drivers/ide/ide-io.c | 1 + > include/linux/blkdev.h | 12 ++++++++++-- > 3 files changed, 12 insertions(+), 2 deletions(-) > > diff --git a/block/blk-core.c b/block/blk-core.c > index 6669238..6f0968f 100644 > --- a/block/blk-core.c > +++ b/block/blk-core.c > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > rq->errors = 0; > rq->ref_count = 1; > rq->cmd_len = 0; > + rq->cmd = rq->__cmd; > memset(rq->cmd, 0, BLK_MAX_CDB); > rq->data_len = 0; > rq->extra_len = 0; > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > index 7153796..bac5ea1 100644 > --- a/drivers/ide/ide-io.c > +++ b/drivers/ide/ide-io.c > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > { > memset(rq, 0, sizeof(*rq)); > rq->ref_count = 1; > + rq->cmd = rq->__cmd; > } > > EXPORT_SYMBOL(ide_init_drive_cmd); > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > index b3a58ad..5710ae4 100644 > --- a/include/linux/blkdev.h > +++ b/include/linux/blkdev.h > @@ -215,8 +215,9 @@ struct request { > /* > * when request is used as a packet command carrier > */ > - unsigned int cmd_len; > - unsigned char cmd[BLK_MAX_CDB]; > + unsigned short cmd_len; > + unsigned char __cmd[BLK_MAX_CDB]; > + unsigned char *cmd; > > unsigned int data_len; > unsigned int extra_len; /* length of alignment and padding */ > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p) > page_cache_release(p.v); > } > > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd, > + unsigned short cmd_len) > +{ > + rq->cmd = cmd; > + rq->cmd_len = cmd_len; > +} > + This is 100% identical to what I suggested be done instead, so of course I agree with this. -- Jens Axboe ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-14 11:29 ` Jens Axboe @ 2008-04-14 12:08 ` FUJITA Tomonori 2008-04-15 22:50 ` Bartlomiej Zolnierkiewicz 1 sibling, 0 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 12:08 UTC (permalink / raw) To: jens.axboe; +Cc: fujita.tomonori, linux-scsi, bharrosh, linux-ide On Mon, 14 Apr 2008 13:29:20 +0200 Jens Axboe <jens.axboe@oracle.com> wrote: > On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > This patch changes rq->cmd from the static array to a pointer to > > support large commands. > > > > We rarely handle large commands. So for optimization, a struct request > > still has a static array for a command. rq_init sets rq->cmd pointer > > to the static array. > > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > Cc: Jens Axboe <jens.axboe@oracle.com> > > --- > > block/blk-core.c | 1 + > > drivers/ide/ide-io.c | 1 + > > include/linux/blkdev.h | 12 ++++++++++-- > > 3 files changed, 12 insertions(+), 2 deletions(-) > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > index 6669238..6f0968f 100644 > > --- a/block/blk-core.c > > +++ b/block/blk-core.c > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > rq->errors = 0; > > rq->ref_count = 1; > > rq->cmd_len = 0; > > + rq->cmd = rq->__cmd; > > memset(rq->cmd, 0, BLK_MAX_CDB); > > rq->data_len = 0; > > rq->extra_len = 0; > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > index 7153796..bac5ea1 100644 > > --- a/drivers/ide/ide-io.c > > +++ b/drivers/ide/ide-io.c > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > { > > memset(rq, 0, sizeof(*rq)); > > rq->ref_count = 1; > > + rq->cmd = rq->__cmd; > > } > > > > EXPORT_SYMBOL(ide_init_drive_cmd); > > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > > index b3a58ad..5710ae4 100644 > > --- a/include/linux/blkdev.h > > +++ b/include/linux/blkdev.h > > @@ -215,8 +215,9 @@ struct request { > > /* > > * when request is used as a packet command carrier > > */ > > - unsigned int cmd_len; > > - unsigned char cmd[BLK_MAX_CDB]; > > + unsigned short cmd_len; > > + unsigned char __cmd[BLK_MAX_CDB]; > > + unsigned char *cmd; > > > > unsigned int data_len; > > unsigned int extra_len; /* length of alignment and padding */ > > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p) > > page_cache_release(p.v); > > } > > > > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd, > > + unsigned short cmd_len) > > +{ > > + rq->cmd = cmd; > > + rq->cmd_len = cmd_len; > > +} > > + > > This is 100% identical to what I suggested be done instead, so of course > I agree with this. Yeah, I think that it's the most straightforward. We have one value to represent one item, the length of command. We can access to rq->cmd and rq->cmd_len as before. I don't see how it's is dangerous to have a single value to represent the length of command though changing rq->cmd from the static array to a pointer to support large commands is tricky. It's possible that I overlooked something that uses the block layer in an uncommon way as ide does. ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-14 11:29 ` Jens Axboe 2008-04-14 12:08 ` FUJITA Tomonori @ 2008-04-15 22:50 ` Bartlomiej Zolnierkiewicz 2008-04-15 22:57 ` FUJITA Tomonori 1 sibling, 1 reply; 77+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2008-04-15 22:50 UTC (permalink / raw) To: Jens Axboe Cc: FUJITA Tomonori, linux-scsi, bharrosh, linux-ide, Andrew Morton Hi, On Monday 14 April 2008, Jens Axboe wrote: > On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > This patch changes rq->cmd from the static array to a pointer to > > support large commands. > > > > We rarely handle large commands. So for optimization, a struct request > > still has a static array for a command. rq_init sets rq->cmd pointer > > to the static array. > > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > Cc: Jens Axboe <jens.axboe@oracle.com> > > --- > > block/blk-core.c | 1 + > > drivers/ide/ide-io.c | 1 + > > include/linux/blkdev.h | 12 ++++++++++-- > > 3 files changed, 12 insertions(+), 2 deletions(-) > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > index 6669238..6f0968f 100644 > > --- a/block/blk-core.c > > +++ b/block/blk-core.c > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > rq->errors = 0; > > rq->ref_count = 1; > > rq->cmd_len = 0; > > + rq->cmd = rq->__cmd; > > memset(rq->cmd, 0, BLK_MAX_CDB); > > rq->data_len = 0; > > rq->extra_len = 0; > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > index 7153796..bac5ea1 100644 > > --- a/drivers/ide/ide-io.c > > +++ b/drivers/ide/ide-io.c > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > { > > memset(rq, 0, sizeof(*rq)); > > rq->ref_count = 1; > > + rq->cmd = rq->__cmd; > > } Tomo, some more changes are needed: Please think about all _static_/dynamic allocations of 'struct request' used together with REQ_TYPE_SPECIAL etc., i.e. static void idetape_init_rq(struct request *rq, u8 cmd) [ rq can be from privately allocated driver's "stack" so no rq_init() ] { memset(rq, 0, sizeof(*rq)); rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd[0] = cmd; } in ide-tape.c or REQ_TYPE_SENSE in ide-cd.c: static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, struct request *failed_command) { struct cdrom_info *info = drive->driver_data; struct request *rq = &info->request_sense_request; if (sense == NULL) sense = &info->sense_data; /* stuff the sense request in front of our current request */ ide_cd_init_rq(drive, rq); rq->data = sense; rq->cmd[0] = GPCMD_REQUEST_SENSE; rq->cmd[4] = rq->data_len = 18; rq->cmd_type = REQ_TYPE_SENSE; /* NOTE! Save the failed command in "rq->buffer" */ rq->buffer = (void *) failed_command; (void) ide_do_drive_cmd(drive, rq, ide_preempt); } > > EXPORT_SYMBOL(ide_init_drive_cmd); > > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > > index b3a58ad..5710ae4 100644 > > --- a/include/linux/blkdev.h > > +++ b/include/linux/blkdev.h > > @@ -215,8 +215,9 @@ struct request { > > /* > > * when request is used as a packet command carrier > > */ > > - unsigned int cmd_len; > > - unsigned char cmd[BLK_MAX_CDB]; > > + unsigned short cmd_len; > > + unsigned char __cmd[BLK_MAX_CDB]; > > + unsigned char *cmd; The source issue lies here: rq->cmd _silently_ becomes something else and unconverted code will happily compile without even a _single_ warning (+ memory corruption / oops later). This is _guaranteed_ to cause problems: - overlooked code (like the IDE code above, with the current approach you have to _manually_ audit all code and still _can't_ be sure about the result) - unmerged code from other trees (i.e., I _have_ WIP patches mapping REQ_TYPE_TASKFILE requests onto rq->cmd) - out of tree code (in theory we don't care but in this specific case there is no reason to break things silently) Please just add new field instead (cost should be negligable and if we're concerned about it I see no problem with using unnamed union like it was done by Boaz). [ Probably it is also worth to add new length field instead of re-using ->cmd_len, just to stay on the safe side (+ for better consistency). ] > > unsigned int data_len; > > unsigned int extra_len; /* length of alignment and padding */ > > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p) > > page_cache_release(p.v); > > } > > > > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd, > > + unsigned short cmd_len) > > +{ > > + rq->cmd = cmd; > > + rq->cmd_len = cmd_len; > > +} > > + > > This is 100% identical to what I suggested be done instead, so of course > I agree with this. Jens, I see that you've applied this patch to block tree - please revert it for now, it needs to be re-designed. Thanks, Bart ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-15 22:50 ` Bartlomiej Zolnierkiewicz @ 2008-04-15 22:57 ` FUJITA Tomonori 2008-04-16 0:22 ` Bartlomiej Zolnierkiewicz 2008-04-16 8:33 ` Jens Axboe 0 siblings, 2 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-15 22:57 UTC (permalink / raw) To: bzolnier; +Cc: jens.axboe, fujita.tomonori, linux-scsi, bharrosh, linux-ide, akpm On Wed, 16 Apr 2008 00:50:54 +0200 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > Hi, > > On Monday 14 April 2008, Jens Axboe wrote: > > On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > > This patch changes rq->cmd from the static array to a pointer to > > > support large commands. > > > > > > We rarely handle large commands. So for optimization, a struct request > > > still has a static array for a command. rq_init sets rq->cmd pointer > > > to the static array. > > > > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > > Cc: Jens Axboe <jens.axboe@oracle.com> > > > --- > > > block/blk-core.c | 1 + > > > drivers/ide/ide-io.c | 1 + > > > include/linux/blkdev.h | 12 ++++++++++-- > > > 3 files changed, 12 insertions(+), 2 deletions(-) > > > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > > index 6669238..6f0968f 100644 > > > --- a/block/blk-core.c > > > +++ b/block/blk-core.c > > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > > rq->errors = 0; > > > rq->ref_count = 1; > > > rq->cmd_len = 0; > > > + rq->cmd = rq->__cmd; > > > memset(rq->cmd, 0, BLK_MAX_CDB); > > > rq->data_len = 0; > > > rq->extra_len = 0; > > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > > index 7153796..bac5ea1 100644 > > > --- a/drivers/ide/ide-io.c > > > +++ b/drivers/ide/ide-io.c > > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > > { > > > memset(rq, 0, sizeof(*rq)); > > > rq->ref_count = 1; > > > + rq->cmd = rq->__cmd; > > > } > > Tomo, some more changes are needed: > > Please think about all _static_/dynamic allocations of 'struct request' > used together with REQ_TYPE_SPECIAL etc., i.e. I think that using struct request allocated statically is wrong from the perspective of the block layer design, that is, you always need to use blk_get_request. I think that except ide, everyone does. I try to convert ide to use blk_get_request properly if you want. > static void idetape_init_rq(struct request *rq, u8 cmd) > > [ rq can be from privately allocated driver's "stack" so no rq_init() ] > > { > memset(rq, 0, sizeof(*rq)); > rq->cmd_type = REQ_TYPE_SPECIAL; > rq->cmd[0] = cmd; > } > > in ide-tape.c or REQ_TYPE_SENSE in ide-cd.c: Thanks, I overlooked this. As I did for ide_init_drive_cmd, we need: + rq->cmd = rq->__cmd; > static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, > struct request *failed_command) > { > struct cdrom_info *info = drive->driver_data; > struct request *rq = &info->request_sense_request; > > if (sense == NULL) > sense = &info->sense_data; > > /* stuff the sense request in front of our current request */ > ide_cd_init_rq(drive, rq); > > rq->data = sense; > rq->cmd[0] = GPCMD_REQUEST_SENSE; > rq->cmd[4] = rq->data_len = 18; > > rq->cmd_type = REQ_TYPE_SENSE; > > /* NOTE! Save the failed command in "rq->buffer" */ > rq->buffer = (void *) failed_command; > > (void) ide_do_drive_cmd(drive, rq, ide_preempt); > } This should work since I put the above hack to ide_init_drive_cmd (I tested the patchset with an ide cdrom drive). > > > EXPORT_SYMBOL(ide_init_drive_cmd); > > > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > > > index b3a58ad..5710ae4 100644 > > > --- a/include/linux/blkdev.h > > > +++ b/include/linux/blkdev.h > > > @@ -215,8 +215,9 @@ struct request { > > > /* > > > * when request is used as a packet command carrier > > > */ > > > - unsigned int cmd_len; > > > - unsigned char cmd[BLK_MAX_CDB]; > > > + unsigned short cmd_len; > > > + unsigned char __cmd[BLK_MAX_CDB]; > > > + unsigned char *cmd; > > The source issue lies here: > > rq->cmd _silently_ becomes something else and unconverted code will happily > compile without even a _single_ warning (+ memory corruption / oops later). > > This is _guaranteed_ to cause problems: > > - overlooked code (like the IDE code above, with the current approach > you have to _manually_ audit all code and still _can't_ be sure about > the result) As far as I know, only ide does that. > - unmerged code from other trees (i.e., I _have_ WIP patches mapping > REQ_TYPE_TASKFILE requests onto rq->cmd) > > - out of tree code (in theory we don't care but in this specific > case there is no reason to break things silently) Again, I think that we can say that we need to use the block layer properly, struct request always needs to be allocated via blk_get_request. > Please just add new field instead (cost should be negligable and if > we're concerned about it I see no problem with using unnamed union like > it was done by Boaz). > > [ Probably it is also worth to add new length field instead of re-using > ->cmd_len, just to stay on the safe side (+ for better consistency). ] As we discussed, we don't like that hack: http://marc.info/?t=120724777800003&r=1&w=2 > > > unsigned int data_len; > > > unsigned int extra_len; /* length of alignment and padding */ > > > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p) > > > page_cache_release(p.v); > > > } > > > > > > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd, > > > + unsigned short cmd_len) > > > +{ > > > + rq->cmd = cmd; > > > + rq->cmd_len = cmd_len; > > > +} > > > + > > > > This is 100% identical to what I suggested be done instead, so of course > > I agree with this. > > Jens, I see that you've applied this patch to block tree > - please revert it for now, it needs to be re-designed. > > Thanks, > Bart > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-15 22:57 ` FUJITA Tomonori @ 2008-04-16 0:22 ` Bartlomiej Zolnierkiewicz 2008-04-16 8:33 ` Jens Axboe 1 sibling, 0 replies; 77+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2008-04-16 0:22 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: jens.axboe, linux-scsi, bharrosh, linux-ide, akpm On Wednesday 16 April 2008, FUJITA Tomonori wrote: > On Wed, 16 Apr 2008 00:50:54 +0200 > Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > > > > Hi, > > > > On Monday 14 April 2008, Jens Axboe wrote: > > > On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > > > This patch changes rq->cmd from the static array to a pointer to > > > > support large commands. > > > > > > > > We rarely handle large commands. So for optimization, a struct request > > > > still has a static array for a command. rq_init sets rq->cmd pointer > > > > to the static array. > > > > > > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > > > Cc: Jens Axboe <jens.axboe@oracle.com> > > > > --- > > > > block/blk-core.c | 1 + > > > > drivers/ide/ide-io.c | 1 + > > > > include/linux/blkdev.h | 12 ++++++++++-- > > > > 3 files changed, 12 insertions(+), 2 deletions(-) > > > > > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > > > index 6669238..6f0968f 100644 > > > > --- a/block/blk-core.c > > > > +++ b/block/blk-core.c > > > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > > > rq->errors = 0; > > > > rq->ref_count = 1; > > > > rq->cmd_len = 0; > > > > + rq->cmd = rq->__cmd; > > > > memset(rq->cmd, 0, BLK_MAX_CDB); > > > > rq->data_len = 0; > > > > rq->extra_len = 0; > > > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > > > index 7153796..bac5ea1 100644 > > > > --- a/drivers/ide/ide-io.c > > > > +++ b/drivers/ide/ide-io.c > > > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > > > { > > > > memset(rq, 0, sizeof(*rq)); > > > > rq->ref_count = 1; > > > > + rq->cmd = rq->__cmd; > > > > } > > > > Tomo, some more changes are needed: > > > > Please think about all _static_/dynamic allocations of 'struct request' > > used together with REQ_TYPE_SPECIAL etc., i.e. > > I think that using struct request allocated statically is wrong from > the perspective of the block layer design, that is, you always need to > use blk_get_request. I think that except ide, everyone does. There still are some others like: - scsi/scsi_error.c::scsi_reset_provider() - paride/pd.c::pd_special_command() but yeah, IDE has the most users left. > I try to convert ide to use blk_get_request properly if you want. I would love to see the patches. > > static void idetape_init_rq(struct request *rq, u8 cmd) > > > > [ rq can be from privately allocated driver's "stack" so no rq_init() ] > > > > { > > memset(rq, 0, sizeof(*rq)); > > rq->cmd_type = REQ_TYPE_SPECIAL; > > rq->cmd[0] = cmd; > > } > > > > in ide-tape.c or REQ_TYPE_SENSE in ide-cd.c: > > Thanks, I overlooked this. As I did for ide_init_drive_cmd, we need: > > > + rq->cmd = rq->__cmd; > > > > static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, > > struct request *failed_command) > > { > > struct cdrom_info *info = drive->driver_data; > > struct request *rq = &info->request_sense_request; > > > > if (sense == NULL) > > sense = &info->sense_data; > > > > /* stuff the sense request in front of our current request */ > > ide_cd_init_rq(drive, rq); > > > > rq->data = sense; > > rq->cmd[0] = GPCMD_REQUEST_SENSE; > > rq->cmd[4] = rq->data_len = 18; > > > > rq->cmd_type = REQ_TYPE_SENSE; > > > > /* NOTE! Save the failed command in "rq->buffer" */ > > rq->buffer = (void *) failed_command; > > > > (void) ide_do_drive_cmd(drive, rq, ide_preempt); > > } > > This should work since I put the above hack to ide_init_drive_cmd (I > tested the patchset with an ide cdrom drive). Indeed, it is called by ide_cd_init_rq() (I blame 2AM). > > > > EXPORT_SYMBOL(ide_init_drive_cmd); > > > > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > > > > index b3a58ad..5710ae4 100644 > > > > --- a/include/linux/blkdev.h > > > > +++ b/include/linux/blkdev.h > > > > @@ -215,8 +215,9 @@ struct request { > > > > /* > > > > * when request is used as a packet command carrier > > > > */ > > > > - unsigned int cmd_len; > > > > - unsigned char cmd[BLK_MAX_CDB]; > > > > + unsigned short cmd_len; > > > > + unsigned char __cmd[BLK_MAX_CDB]; > > > > + unsigned char *cmd; > > > > The source issue lies here: > > > > rq->cmd _silently_ becomes something else and unconverted code will happily > > compile without even a _single_ warning (+ memory corruption / oops later). > > > > This is _guaranteed_ to cause problems: > > > > - overlooked code (like the IDE code above, with the current approach > > you have to _manually_ audit all code and still _can't_ be sure about > > the result) > > As far as I know, only ide does that. Well, if there are others you'll learn about them the hard-way... ;-) [ The thing is that you can avoid answering this question completely with the "ugly" approach. ] > > - unmerged code from other trees (i.e., I _have_ WIP patches mapping > > REQ_TYPE_TASKFILE requests onto rq->cmd) > > > > - out of tree code (in theory we don't care but in this specific > > case there is no reason to break things silently) > > Again, I think that we can say that we need to use the block layer > properly, struct request always needs to be allocated via > blk_get_request. Hmm, in this case some code asserting that only blk_bet_request() requests allowed in the block layer would be useful. > > Please just add new field instead (cost should be negligable and if > > we're concerned about it I see no problem with using unnamed union like > > it was done by Boaz). > > > > [ Probably it is also worth to add new length field instead of re-using > > ->cmd_len, just to stay on the safe side (+ for better consistency). ] > > As we discussed, we don't like that hack: > > http://marc.info/?t=120724777800003&r=1&w=2 If you audit+fixup IDE I'm also fine with non-"hack" solution. Thanks, Bart ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-15 22:57 ` FUJITA Tomonori 2008-04-16 0:22 ` Bartlomiej Zolnierkiewicz @ 2008-04-16 8:33 ` Jens Axboe 2008-04-16 9:08 ` Boaz Harrosh 2008-04-17 4:02 ` FUJITA Tomonori 1 sibling, 2 replies; 77+ messages in thread From: Jens Axboe @ 2008-04-16 8:33 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: bzolnier, linux-scsi, bharrosh, linux-ide, akpm On Wed, Apr 16 2008, FUJITA Tomonori wrote: > On Wed, 16 Apr 2008 00:50:54 +0200 > Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > > > > Hi, > > > > On Monday 14 April 2008, Jens Axboe wrote: > > > On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > > > This patch changes rq->cmd from the static array to a pointer to > > > > support large commands. > > > > > > > > We rarely handle large commands. So for optimization, a struct request > > > > still has a static array for a command. rq_init sets rq->cmd pointer > > > > to the static array. > > > > > > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > > > Cc: Jens Axboe <jens.axboe@oracle.com> > > > > --- > > > > block/blk-core.c | 1 + > > > > drivers/ide/ide-io.c | 1 + > > > > include/linux/blkdev.h | 12 ++++++++++-- > > > > 3 files changed, 12 insertions(+), 2 deletions(-) > > > > > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > > > index 6669238..6f0968f 100644 > > > > --- a/block/blk-core.c > > > > +++ b/block/blk-core.c > > > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > > > rq->errors = 0; > > > > rq->ref_count = 1; > > > > rq->cmd_len = 0; > > > > + rq->cmd = rq->__cmd; > > > > memset(rq->cmd, 0, BLK_MAX_CDB); > > > > rq->data_len = 0; > > > > rq->extra_len = 0; > > > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > > > index 7153796..bac5ea1 100644 > > > > --- a/drivers/ide/ide-io.c > > > > +++ b/drivers/ide/ide-io.c > > > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > > > { > > > > memset(rq, 0, sizeof(*rq)); > > > > rq->ref_count = 1; > > > > + rq->cmd = rq->__cmd; > > > > } > > > > Tomo, some more changes are needed: > > > > Please think about all _static_/dynamic allocations of 'struct request' > > used together with REQ_TYPE_SPECIAL etc., i.e. > > I think that using struct request allocated statically is wrong from > the perspective of the block layer design, that is, you always need to > use blk_get_request. I think that except ide, everyone does. > > I try to convert ide to use blk_get_request properly if you want. That would be best, but the on-stack allocation has the benefit that it'll always work. So until we can completely get rid of that, lets just make it a hard rule that ANY rq allocation MUST call rq_init(). It's a lot saner than doing a memset() anyway. -- Jens Axboe ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-16 8:33 ` Jens Axboe @ 2008-04-16 9:08 ` Boaz Harrosh 2008-04-16 9:42 ` Jens Axboe 2008-04-17 3:59 ` FUJITA Tomonori 2008-04-17 4:02 ` FUJITA Tomonori 1 sibling, 2 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-16 9:08 UTC (permalink / raw) To: Jens Axboe; +Cc: FUJITA Tomonori, bzolnier, linux-scsi, linux-ide, akpm On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > On Wed, Apr 16 2008, FUJITA Tomonori wrote: >> On Wed, 16 Apr 2008 00:50:54 +0200 >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: >> >>> Hi, >>> >>> On Monday 14 April 2008, Jens Axboe wrote: >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote: >>>>> This patch changes rq->cmd from the static array to a pointer to >>>>> support large commands. >>>>> >>>>> We rarely handle large commands. So for optimization, a struct request >>>>> still has a static array for a command. rq_init sets rq->cmd pointer >>>>> to the static array. >>>>> >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> >>>>> Cc: Jens Axboe <jens.axboe@oracle.com> >>>>> --- >>>>> block/blk-core.c | 1 + >>>>> drivers/ide/ide-io.c | 1 + >>>>> include/linux/blkdev.h | 12 ++++++++++-- >>>>> 3 files changed, 12 insertions(+), 2 deletions(-) >>>>> >>>>> diff --git a/block/blk-core.c b/block/blk-core.c >>>>> index 6669238..6f0968f 100644 >>>>> --- a/block/blk-core.c >>>>> +++ b/block/blk-core.c >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) >>>>> rq->errors = 0; >>>>> rq->ref_count = 1; >>>>> rq->cmd_len = 0; >>>>> + rq->cmd = rq->__cmd; >>>>> memset(rq->cmd, 0, BLK_MAX_CDB); >>>>> rq->data_len = 0; >>>>> rq->extra_len = 0; >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c >>>>> index 7153796..bac5ea1 100644 >>>>> --- a/drivers/ide/ide-io.c >>>>> +++ b/drivers/ide/ide-io.c >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) >>>>> { >>>>> memset(rq, 0, sizeof(*rq)); >>>>> rq->ref_count = 1; >>>>> + rq->cmd = rq->__cmd; >>>>> } >>> Tomo, some more changes are needed: >>> >>> Please think about all _static_/dynamic allocations of 'struct request' >>> used together with REQ_TYPE_SPECIAL etc., i.e. >> I think that using struct request allocated statically is wrong from >> the perspective of the block layer design, that is, you always need to >> use blk_get_request. I think that except ide, everyone does. >> >> I try to convert ide to use blk_get_request properly if you want. > > That would be best, but the on-stack allocation has the benefit that > it'll always work. So until we can completely get rid of that, lets just > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a > lot saner than doing a memset() anyway. > Just a patch that I had for ages since the bad old request bidi times, perhaps is also good today. (rebased to for-2.6.26 branch) --- From: Boaz Harrosh <bharrosh@panasas.com> Date: Wed, 16 Apr 2008 12:05:33 +0300 Subject: [PATCH] Initialize all members of struct request in rq_init Before, every member added/removed from struct request would entitle a change to rq_init, for initialization. Now all members are default to zero and only the none zero members are specifically initialized. Users that need requests on the stack or pre-allocated, must call rq_init() before use. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- block/blk-core.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 6f0968f..3f4c563 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info); */ void rq_init(struct request_queue *q, struct request *rq) { + memset(rq, 0, sizeof(*rq)); INIT_LIST_HEAD(&rq->queuelist); INIT_LIST_HEAD(&rq->donelist); rq->q = q; rq->sector = rq->hard_sector = (sector_t) -1; - rq->nr_sectors = rq->hard_nr_sectors = 0; - rq->current_nr_sectors = rq->hard_cur_sectors = 0; - rq->bio = rq->biotail = NULL; INIT_HLIST_NODE(&rq->hash); RB_CLEAR_NODE(&rq->rb_node); - rq->rq_disk = NULL; - rq->nr_phys_segments = 0; - rq->nr_hw_segments = 0; - rq->ioprio = 0; - rq->special = NULL; - rq->buffer = NULL; rq->tag = -1; - rq->errors = 0; rq->ref_count = 1; - rq->cmd_len = 0; rq->cmd = rq->__cmd; - memset(rq->cmd, 0, BLK_MAX_CDB); - rq->data_len = 0; - rq->extra_len = 0; - rq->sense_len = 0; - rq->data = NULL; - rq->sense = NULL; - rq->end_io = NULL; - rq->end_io_data = NULL; - rq->next_rq = NULL; } +EXPORT_SYMBOL(rq_init); static void req_bio_endio(struct request *rq, struct bio *bio, unsigned int nbytes, int error) -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-16 9:08 ` Boaz Harrosh @ 2008-04-16 9:42 ` Jens Axboe 2008-04-16 22:28 ` Bartlomiej Zolnierkiewicz 2008-04-17 3:59 ` FUJITA Tomonori 1 sibling, 1 reply; 77+ messages in thread From: Jens Axboe @ 2008-04-16 9:42 UTC (permalink / raw) To: Boaz Harrosh; +Cc: FUJITA Tomonori, bzolnier, linux-scsi, linux-ide, akpm On Wed, Apr 16 2008, Boaz Harrosh wrote: > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > > On Wed, Apr 16 2008, FUJITA Tomonori wrote: > >> On Wed, 16 Apr 2008 00:50:54 +0200 > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > >> > >>> Hi, > >>> > >>> On Monday 14 April 2008, Jens Axboe wrote: > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote: > >>>>> This patch changes rq->cmd from the static array to a pointer to > >>>>> support large commands. > >>>>> > >>>>> We rarely handle large commands. So for optimization, a struct request > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer > >>>>> to the static array. > >>>>> > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com> > >>>>> --- > >>>>> block/blk-core.c | 1 + > >>>>> drivers/ide/ide-io.c | 1 + > >>>>> include/linux/blkdev.h | 12 ++++++++++-- > >>>>> 3 files changed, 12 insertions(+), 2 deletions(-) > >>>>> > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c > >>>>> index 6669238..6f0968f 100644 > >>>>> --- a/block/blk-core.c > >>>>> +++ b/block/blk-core.c > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > >>>>> rq->errors = 0; > >>>>> rq->ref_count = 1; > >>>>> rq->cmd_len = 0; > >>>>> + rq->cmd = rq->__cmd; > >>>>> memset(rq->cmd, 0, BLK_MAX_CDB); > >>>>> rq->data_len = 0; > >>>>> rq->extra_len = 0; > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > >>>>> index 7153796..bac5ea1 100644 > >>>>> --- a/drivers/ide/ide-io.c > >>>>> +++ b/drivers/ide/ide-io.c > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > >>>>> { > >>>>> memset(rq, 0, sizeof(*rq)); > >>>>> rq->ref_count = 1; > >>>>> + rq->cmd = rq->__cmd; > >>>>> } > >>> Tomo, some more changes are needed: > >>> > >>> Please think about all _static_/dynamic allocations of 'struct request' > >>> used together with REQ_TYPE_SPECIAL etc., i.e. > >> I think that using struct request allocated statically is wrong from > >> the perspective of the block layer design, that is, you always need to > >> use blk_get_request. I think that except ide, everyone does. > >> > >> I try to convert ide to use blk_get_request properly if you want. > > > > That would be best, but the on-stack allocation has the benefit that > > it'll always work. So until we can completely get rid of that, lets just > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a > > lot saner than doing a memset() anyway. > > > > Just a patch that I had for ages since the bad old request bidi times, > perhaps is also good today. (rebased to for-2.6.26 branch) > --- > From: Boaz Harrosh <bharrosh@panasas.com> > Date: Wed, 16 Apr 2008 12:05:33 +0300 > Subject: [PATCH] Initialize all members of struct request in rq_init > > Before, every member added/removed from struct request would entitle a change > to rq_init, for initialization. Now all members are default to zero and only > the none zero members are specifically initialized. > > Users that need requests on the stack or pre-allocated, must call rq_init() > before use. > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > --- > block/blk-core.c | 22 ++-------------------- > 1 files changed, 2 insertions(+), 20 deletions(-) > > diff --git a/block/blk-core.c b/block/blk-core.c > index 6f0968f..3f4c563 100644 > --- a/block/blk-core.c > +++ b/block/blk-core.c > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info); > */ > void rq_init(struct request_queue *q, struct request *rq) > { > + memset(rq, 0, sizeof(*rq)); > INIT_LIST_HEAD(&rq->queuelist); > INIT_LIST_HEAD(&rq->donelist); > rq->q = q; > rq->sector = rq->hard_sector = (sector_t) -1; > - rq->nr_sectors = rq->hard_nr_sectors = 0; > - rq->current_nr_sectors = rq->hard_cur_sectors = 0; > - rq->bio = rq->biotail = NULL; > INIT_HLIST_NODE(&rq->hash); > RB_CLEAR_NODE(&rq->rb_node); > - rq->rq_disk = NULL; > - rq->nr_phys_segments = 0; > - rq->nr_hw_segments = 0; > - rq->ioprio = 0; > - rq->special = NULL; > - rq->buffer = NULL; > rq->tag = -1; > - rq->errors = 0; > rq->ref_count = 1; > - rq->cmd_len = 0; > rq->cmd = rq->__cmd; > - memset(rq->cmd, 0, BLK_MAX_CDB); > - rq->data_len = 0; > - rq->extra_len = 0; > - rq->sense_len = 0; > - rq->data = NULL; > - rq->sense = NULL; > - rq->end_io = NULL; > - rq->end_io_data = NULL; > - rq->next_rq = NULL; > } > +EXPORT_SYMBOL(rq_init); > > static void req_bio_endio(struct request *rq, struct bio *bio, > unsigned int nbytes, int error) > -- > 1.5.3.3 > Totally agree, if we expand rq_init() to all users (including on stack), this must be included as well. -- Jens Axboe ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-16 9:42 ` Jens Axboe @ 2008-04-16 22:28 ` Bartlomiej Zolnierkiewicz 0 siblings, 0 replies; 77+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2008-04-16 22:28 UTC (permalink / raw) To: Jens Axboe; +Cc: Boaz Harrosh, FUJITA Tomonori, linux-scsi, linux-ide, akpm On Wednesday 16 April 2008, Jens Axboe wrote: > On Wed, Apr 16 2008, Boaz Harrosh wrote: > > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > > > On Wed, Apr 16 2008, FUJITA Tomonori wrote: > > >> On Wed, 16 Apr 2008 00:50:54 +0200 > > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > >> > > >>> Hi, > > >>> > > >>> On Monday 14 April 2008, Jens Axboe wrote: > > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > >>>>> This patch changes rq->cmd from the static array to a pointer to > > >>>>> support large commands. > > >>>>> > > >>>>> We rarely handle large commands. So for optimization, a struct request > > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer > > >>>>> to the static array. > > >>>>> > > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com> > > >>>>> --- > > >>>>> block/blk-core.c | 1 + > > >>>>> drivers/ide/ide-io.c | 1 + > > >>>>> include/linux/blkdev.h | 12 ++++++++++-- > > >>>>> 3 files changed, 12 insertions(+), 2 deletions(-) > > >>>>> > > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c > > >>>>> index 6669238..6f0968f 100644 > > >>>>> --- a/block/blk-core.c > > >>>>> +++ b/block/blk-core.c > > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > >>>>> rq->errors = 0; > > >>>>> rq->ref_count = 1; > > >>>>> rq->cmd_len = 0; > > >>>>> + rq->cmd = rq->__cmd; > > >>>>> memset(rq->cmd, 0, BLK_MAX_CDB); > > >>>>> rq->data_len = 0; > > >>>>> rq->extra_len = 0; > > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > >>>>> index 7153796..bac5ea1 100644 > > >>>>> --- a/drivers/ide/ide-io.c > > >>>>> +++ b/drivers/ide/ide-io.c > > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > >>>>> { > > >>>>> memset(rq, 0, sizeof(*rq)); > > >>>>> rq->ref_count = 1; > > >>>>> + rq->cmd = rq->__cmd; > > >>>>> } > > >>> Tomo, some more changes are needed: > > >>> > > >>> Please think about all _static_/dynamic allocations of 'struct request' > > >>> used together with REQ_TYPE_SPECIAL etc., i.e. > > >> I think that using struct request allocated statically is wrong from > > >> the perspective of the block layer design, that is, you always need to > > >> use blk_get_request. I think that except ide, everyone does. > > >> > > >> I try to convert ide to use blk_get_request properly if you want. > > > > > > That would be best, but the on-stack allocation has the benefit that > > > it'll always work. So until we can completely get rid of that, lets just > > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a > > > lot saner than doing a memset() anyway. Sounds OK to me. > > Just a patch that I had for ages since the bad old request bidi times, > > perhaps is also good today. (rebased to for-2.6.26 branch) > > --- > > From: Boaz Harrosh <bharrosh@panasas.com> > > Date: Wed, 16 Apr 2008 12:05:33 +0300 > > Subject: [PATCH] Initialize all members of struct request in rq_init > > > > Before, every member added/removed from struct request would entitle a change > > to rq_init, for initialization. Now all members are default to zero and only > > the none zero members are specifically initialized. > > > > Users that need requests on the stack or pre-allocated, must call rq_init() > > before use. > > > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > > --- > > block/blk-core.c | 22 ++-------------------- > > 1 files changed, 2 insertions(+), 20 deletions(-) > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > index 6f0968f..3f4c563 100644 > > --- a/block/blk-core.c > > +++ b/block/blk-core.c > > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info); > > */ > > void rq_init(struct request_queue *q, struct request *rq) > > { > > + memset(rq, 0, sizeof(*rq)); > > INIT_LIST_HEAD(&rq->queuelist); > > INIT_LIST_HEAD(&rq->donelist); > > rq->q = q; > > rq->sector = rq->hard_sector = (sector_t) -1; > > - rq->nr_sectors = rq->hard_nr_sectors = 0; > > - rq->current_nr_sectors = rq->hard_cur_sectors = 0; > > - rq->bio = rq->biotail = NULL; > > INIT_HLIST_NODE(&rq->hash); > > RB_CLEAR_NODE(&rq->rb_node); > > - rq->rq_disk = NULL; > > - rq->nr_phys_segments = 0; > > - rq->nr_hw_segments = 0; > > - rq->ioprio = 0; > > - rq->special = NULL; > > - rq->buffer = NULL; > > rq->tag = -1; > > - rq->errors = 0; > > rq->ref_count = 1; > > - rq->cmd_len = 0; > > rq->cmd = rq->__cmd; > > - memset(rq->cmd, 0, BLK_MAX_CDB); > > - rq->data_len = 0; > > - rq->extra_len = 0; > > - rq->sense_len = 0; > > - rq->data = NULL; > > - rq->sense = NULL; > > - rq->end_io = NULL; > > - rq->end_io_data = NULL; > > - rq->next_rq = NULL; > > } > > +EXPORT_SYMBOL(rq_init); > > > > static void req_bio_endio(struct request *rq, struct bio *bio, > > unsigned int nbytes, int error) > > -- > > 1.5.3.3 > > > > Totally agree, if we expand rq_init() to all users (including on stack), > this must be included as well. Completely, totally and fully agreed... Thanks, Bart ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-16 9:08 ` Boaz Harrosh 2008-04-16 9:42 ` Jens Axboe @ 2008-04-17 3:59 ` FUJITA Tomonori 2008-04-17 7:07 ` Jens Axboe 1 sibling, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-17 3:59 UTC (permalink / raw) To: bharrosh; +Cc: jens.axboe, fujita.tomonori, bzolnier, linux-scsi, linux-ide, akpm On Wed, 16 Apr 2008 12:08:25 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > > On Wed, Apr 16 2008, FUJITA Tomonori wrote: > >> On Wed, 16 Apr 2008 00:50:54 +0200 > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > >> > >>> Hi, > >>> > >>> On Monday 14 April 2008, Jens Axboe wrote: > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote: > >>>>> This patch changes rq->cmd from the static array to a pointer to > >>>>> support large commands. > >>>>> > >>>>> We rarely handle large commands. So for optimization, a struct request > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer > >>>>> to the static array. > >>>>> > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com> > >>>>> --- > >>>>> block/blk-core.c | 1 + > >>>>> drivers/ide/ide-io.c | 1 + > >>>>> include/linux/blkdev.h | 12 ++++++++++-- > >>>>> 3 files changed, 12 insertions(+), 2 deletions(-) > >>>>> > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c > >>>>> index 6669238..6f0968f 100644 > >>>>> --- a/block/blk-core.c > >>>>> +++ b/block/blk-core.c > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > >>>>> rq->errors = 0; > >>>>> rq->ref_count = 1; > >>>>> rq->cmd_len = 0; > >>>>> + rq->cmd = rq->__cmd; > >>>>> memset(rq->cmd, 0, BLK_MAX_CDB); > >>>>> rq->data_len = 0; > >>>>> rq->extra_len = 0; > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > >>>>> index 7153796..bac5ea1 100644 > >>>>> --- a/drivers/ide/ide-io.c > >>>>> +++ b/drivers/ide/ide-io.c > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > >>>>> { > >>>>> memset(rq, 0, sizeof(*rq)); > >>>>> rq->ref_count = 1; > >>>>> + rq->cmd = rq->__cmd; > >>>>> } > >>> Tomo, some more changes are needed: > >>> > >>> Please think about all _static_/dynamic allocations of 'struct request' > >>> used together with REQ_TYPE_SPECIAL etc., i.e. > >> I think that using struct request allocated statically is wrong from > >> the perspective of the block layer design, that is, you always need to > >> use blk_get_request. I think that except ide, everyone does. > >> > >> I try to convert ide to use blk_get_request properly if you want. > > > > That would be best, but the on-stack allocation has the benefit that > > it'll always work. So until we can completely get rid of that, lets just > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a > > lot saner than doing a memset() anyway. > > > > Just a patch that I had for ages since the bad old request bidi times, > perhaps is also good today. (rebased to for-2.6.26 branch) > --- > From: Boaz Harrosh <bharrosh@panasas.com> > Date: Wed, 16 Apr 2008 12:05:33 +0300 > Subject: [PATCH] Initialize all members of struct request in rq_init > > Before, every member added/removed from struct request would entitle a change > to rq_init, for initialization. Now all members are default to zero and only > the none zero members are specifically initialized. > > Users that need requests on the stack or pre-allocated, must call rq_init() > before use. > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > --- > block/blk-core.c | 22 ++-------------------- > 1 files changed, 2 insertions(+), 20 deletions(-) > > diff --git a/block/blk-core.c b/block/blk-core.c > index 6f0968f..3f4c563 100644 > --- a/block/blk-core.c > +++ b/block/blk-core.c > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info); > */ > void rq_init(struct request_queue *q, struct request *rq) > { > + memset(rq, 0, sizeof(*rq)); Hmm, rq_init comment says: /* * We can't just memset() the structure, since the allocation path * already stored some information in the request. */ I think that we can't initialize rq->cmd_flags here. > INIT_LIST_HEAD(&rq->queuelist); > INIT_LIST_HEAD(&rq->donelist); > rq->q = q; > rq->sector = rq->hard_sector = (sector_t) -1; > - rq->nr_sectors = rq->hard_nr_sectors = 0; > - rq->current_nr_sectors = rq->hard_cur_sectors = 0; > - rq->bio = rq->biotail = NULL; > INIT_HLIST_NODE(&rq->hash); > RB_CLEAR_NODE(&rq->rb_node); > - rq->rq_disk = NULL; > - rq->nr_phys_segments = 0; > - rq->nr_hw_segments = 0; > - rq->ioprio = 0; > - rq->special = NULL; > - rq->buffer = NULL; > rq->tag = -1; > - rq->errors = 0; > rq->ref_count = 1; > - rq->cmd_len = 0; > rq->cmd = rq->__cmd; > - memset(rq->cmd, 0, BLK_MAX_CDB); > - rq->data_len = 0; > - rq->extra_len = 0; > - rq->sense_len = 0; > - rq->data = NULL; > - rq->sense = NULL; > - rq->end_io = NULL; > - rq->end_io_data = NULL; > - rq->next_rq = NULL; > } > +EXPORT_SYMBOL(rq_init); > > static void req_bio_endio(struct request *rq, struct bio *bio, > unsigned int nbytes, int error) > -- > 1.5.3.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-17 3:59 ` FUJITA Tomonori @ 2008-04-17 7:07 ` Jens Axboe 2008-04-17 11:55 ` Bartlomiej Zolnierkiewicz 2008-04-17 12:07 ` FUJITA Tomonori 0 siblings, 2 replies; 77+ messages in thread From: Jens Axboe @ 2008-04-17 7:07 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: bharrosh, bzolnier, linux-scsi, linux-ide, akpm On Thu, Apr 17 2008, FUJITA Tomonori wrote: > On Wed, 16 Apr 2008 12:08:25 +0300 > Boaz Harrosh <bharrosh@panasas.com> wrote: > > > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > > > On Wed, Apr 16 2008, FUJITA Tomonori wrote: > > >> On Wed, 16 Apr 2008 00:50:54 +0200 > > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > >> > > >>> Hi, > > >>> > > >>> On Monday 14 April 2008, Jens Axboe wrote: > > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > >>>>> This patch changes rq->cmd from the static array to a pointer to > > >>>>> support large commands. > > >>>>> > > >>>>> We rarely handle large commands. So for optimization, a struct request > > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer > > >>>>> to the static array. > > >>>>> > > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com> > > >>>>> --- > > >>>>> block/blk-core.c | 1 + > > >>>>> drivers/ide/ide-io.c | 1 + > > >>>>> include/linux/blkdev.h | 12 ++++++++++-- > > >>>>> 3 files changed, 12 insertions(+), 2 deletions(-) > > >>>>> > > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c > > >>>>> index 6669238..6f0968f 100644 > > >>>>> --- a/block/blk-core.c > > >>>>> +++ b/block/blk-core.c > > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > >>>>> rq->errors = 0; > > >>>>> rq->ref_count = 1; > > >>>>> rq->cmd_len = 0; > > >>>>> + rq->cmd = rq->__cmd; > > >>>>> memset(rq->cmd, 0, BLK_MAX_CDB); > > >>>>> rq->data_len = 0; > > >>>>> rq->extra_len = 0; > > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > >>>>> index 7153796..bac5ea1 100644 > > >>>>> --- a/drivers/ide/ide-io.c > > >>>>> +++ b/drivers/ide/ide-io.c > > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > >>>>> { > > >>>>> memset(rq, 0, sizeof(*rq)); > > >>>>> rq->ref_count = 1; > > >>>>> + rq->cmd = rq->__cmd; > > >>>>> } > > >>> Tomo, some more changes are needed: > > >>> > > >>> Please think about all _static_/dynamic allocations of 'struct request' > > >>> used together with REQ_TYPE_SPECIAL etc., i.e. > > >> I think that using struct request allocated statically is wrong from > > >> the perspective of the block layer design, that is, you always need to > > >> use blk_get_request. I think that except ide, everyone does. > > >> > > >> I try to convert ide to use blk_get_request properly if you want. > > > > > > That would be best, but the on-stack allocation has the benefit that > > > it'll always work. So until we can completely get rid of that, lets just > > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a > > > lot saner than doing a memset() anyway. > > > > > > > Just a patch that I had for ages since the bad old request bidi times, > > perhaps is also good today. (rebased to for-2.6.26 branch) > > --- > > From: Boaz Harrosh <bharrosh@panasas.com> > > Date: Wed, 16 Apr 2008 12:05:33 +0300 > > Subject: [PATCH] Initialize all members of struct request in rq_init > > > > Before, every member added/removed from struct request would entitle a change > > to rq_init, for initialization. Now all members are default to zero and only > > the none zero members are specifically initialized. > > > > Users that need requests on the stack or pre-allocated, must call rq_init() > > before use. > > > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > > --- > > block/blk-core.c | 22 ++-------------------- > > 1 files changed, 2 insertions(+), 20 deletions(-) > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > index 6f0968f..3f4c563 100644 > > --- a/block/blk-core.c > > +++ b/block/blk-core.c > > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info); > > */ > > void rq_init(struct request_queue *q, struct request *rq) > > { > > + memset(rq, 0, sizeof(*rq)); > > Hmm, rq_init comment says: > > /* > * We can't just memset() the structure, since the allocation path > * already stored some information in the request. > */ > > I think that we can't initialize rq->cmd_flags here. That is correct, the patch wont work as-is. The principle of clearing every member except block internal is sound and should be applied, though. -- Jens Axboe ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-17 7:07 ` Jens Axboe @ 2008-04-17 11:55 ` Bartlomiej Zolnierkiewicz 2008-04-17 11:58 ` Bartlomiej Zolnierkiewicz 2008-04-17 12:07 ` FUJITA Tomonori 1 sibling, 1 reply; 77+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2008-04-17 11:55 UTC (permalink / raw) To: Jens Axboe; +Cc: FUJITA Tomonori, bharrosh, linux-scsi, linux-ide, akpm On Thu, Apr 17, 2008 at 9:07 AM, Jens Axboe <jens.axboe@oracle.com> wrote: > > On Thu, Apr 17 2008, FUJITA Tomonori wrote: > > On Wed, 16 Apr 2008 12:08:25 +0300 > > Boaz Harrosh <bharrosh@panasas.com> wrote: > > > > > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > > > > On Wed, Apr 16 2008, FUJITA Tomonori wrote: > > > >> On Wed, 16 Apr 2008 00:50:54 +0200 > > > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > > >> > > > >>> Hi, > > > >>> > > > >>> On Monday 14 April 2008, Jens Axboe wrote: > > > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > > >>>>> This patch changes rq->cmd from the static array to a pointer to > > > >>>>> support large commands. > > > >>>>> > > > >>>>> We rarely handle large commands. So for optimization, a struct request > > > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer > > > >>>>> to the static array. > > > >>>>> > > > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com> > > > >>>>> --- > > > >>>>> block/blk-core.c | 1 + > > > >>>>> drivers/ide/ide-io.c | 1 + > > > >>>>> include/linux/blkdev.h | 12 ++++++++++-- > > > >>>>> 3 files changed, 12 insertions(+), 2 deletions(-) > > > >>>>> > > > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c > > > >>>>> index 6669238..6f0968f 100644 > > > >>>>> --- a/block/blk-core.c > > > >>>>> +++ b/block/blk-core.c > > > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > > >>>>> rq->errors = 0; > > > >>>>> rq->ref_count = 1; > > > >>>>> rq->cmd_len = 0; > > > >>>>> + rq->cmd = rq->__cmd; > > > >>>>> memset(rq->cmd, 0, BLK_MAX_CDB); > > > >>>>> rq->data_len = 0; > > > >>>>> rq->extra_len = 0; > > > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > > >>>>> index 7153796..bac5ea1 100644 > > > >>>>> --- a/drivers/ide/ide-io.c > > > >>>>> +++ b/drivers/ide/ide-io.c > > > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > > >>>>> { > > > >>>>> memset(rq, 0, sizeof(*rq)); > > > >>>>> rq->ref_count = 1; > > > >>>>> + rq->cmd = rq->__cmd; > > > >>>>> } > > > >>> Tomo, some more changes are needed: > > > >>> > > > >>> Please think about all _static_/dynamic allocations of 'struct request' > > > >>> used together with REQ_TYPE_SPECIAL etc., i.e. > > > >> I think that using struct request allocated statically is wrong from > > > >> the perspective of the block layer design, that is, you always need to > > > >> use blk_get_request. I think that except ide, everyone does. > > > >> > > > >> I try to convert ide to use blk_get_request properly if you want. > > > > > > > > That would be best, but the on-stack allocation has the benefit that > > > > it'll always work. So until we can completely get rid of that, lets just > > > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a > > > > lot saner than doing a memset() anyway. > > > > > > > > > > Just a patch that I had for ages since the bad old request bidi times, > > > perhaps is also good today. (rebased to for-2.6.26 branch) > > > --- > > > From: Boaz Harrosh <bharrosh@panasas.com> > > > Date: Wed, 16 Apr 2008 12:05:33 +0300 > > > Subject: [PATCH] Initialize all members of struct request in rq_init > > > > > > Before, every member added/removed from struct request would entitle a change > > > to rq_init, for initialization. Now all members are default to zero and only > > > the none zero members are specifically initialized. > > > > > > Users that need requests on the stack or pre-allocated, must call rq_init() > > > before use. > > > > > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > > > --- > > > block/blk-core.c | 22 ++-------------------- > > > 1 files changed, 2 insertions(+), 20 deletions(-) > > > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > > index 6f0968f..3f4c563 100644 > > > --- a/block/blk-core.c > > > +++ b/block/blk-core.c > > > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info); > > > */ > > > void rq_init(struct request_queue *q, struct request *rq) > > > { > > > + memset(rq, 0, sizeof(*rq)); > > > > Hmm, rq_init comment says: > > > > /* > > * We can't just memset() the structure, since the allocation path > > * already stored some information in the request. > > */ > > > > I think that we can't initialize rq->cmd_flags here. > > That is correct, the patch wont work as-is. The principle of clearing > every member except block internal is sound and should be applied, > though. While we're at it we may fix it as well (preferably in another pre-patch): - move setting rq->cmd_flags from blk_alloc_request() to the callers (this is only get_request() ATM) - re-order setting rq->cmd_flags vs calling rq_init() in get_request(), queue_lfush() and start_ordered() Thanks, Bart ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-17 11:55 ` Bartlomiej Zolnierkiewicz @ 2008-04-17 11:58 ` Bartlomiej Zolnierkiewicz 0 siblings, 0 replies; 77+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2008-04-17 11:58 UTC (permalink / raw) To: Jens Axboe; +Cc: FUJITA Tomonori, bharrosh, linux-scsi, linux-ide, akpm On Thu, Apr 17, 2008 at 1:55 PM, Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > On Thu, Apr 17, 2008 at 9:07 AM, Jens Axboe <jens.axboe@oracle.com> wrote: > > > > On Thu, Apr 17 2008, FUJITA Tomonori wrote: > > > On Wed, 16 Apr 2008 12:08:25 +0300 > > > Boaz Harrosh <bharrosh@panasas.com> wrote: > > > > > > > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > > > > > On Wed, Apr 16 2008, FUJITA Tomonori wrote: > > > > >> On Wed, 16 Apr 2008 00:50:54 +0200 > > > > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > > > >> > > > > >>> Hi, > > > > >>> > > > > >>> On Monday 14 April 2008, Jens Axboe wrote: > > > > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > > > >>>>> This patch changes rq->cmd from the static array to a pointer to > > > > >>>>> support large commands. > > > > >>>>> > > > > >>>>> We rarely handle large commands. So for optimization, a struct request > > > > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer > > > > >>>>> to the static array. > > > > >>>>> > > > > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > > > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com> > > > > >>>>> --- > > > > >>>>> block/blk-core.c | 1 + > > > > >>>>> drivers/ide/ide-io.c | 1 + > > > > >>>>> include/linux/blkdev.h | 12 ++++++++++-- > > > > >>>>> 3 files changed, 12 insertions(+), 2 deletions(-) > > > > >>>>> > > > > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c > > > > >>>>> index 6669238..6f0968f 100644 > > > > >>>>> --- a/block/blk-core.c > > > > >>>>> +++ b/block/blk-core.c > > > > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > > > >>>>> rq->errors = 0; > > > > >>>>> rq->ref_count = 1; > > > > >>>>> rq->cmd_len = 0; > > > > >>>>> + rq->cmd = rq->__cmd; > > > > >>>>> memset(rq->cmd, 0, BLK_MAX_CDB); > > > > >>>>> rq->data_len = 0; > > > > >>>>> rq->extra_len = 0; > > > > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > > > >>>>> index 7153796..bac5ea1 100644 > > > > >>>>> --- a/drivers/ide/ide-io.c > > > > >>>>> +++ b/drivers/ide/ide-io.c > > > > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > > > >>>>> { > > > > >>>>> memset(rq, 0, sizeof(*rq)); > > > > >>>>> rq->ref_count = 1; > > > > >>>>> + rq->cmd = rq->__cmd; > > > > >>>>> } > > > > >>> Tomo, some more changes are needed: > > > > >>> > > > > >>> Please think about all _static_/dynamic allocations of 'struct request' > > > > >>> used together with REQ_TYPE_SPECIAL etc., i.e. > > > > >> I think that using struct request allocated statically is wrong from > > > > >> the perspective of the block layer design, that is, you always need to > > > > >> use blk_get_request. I think that except ide, everyone does. > > > > >> > > > > >> I try to convert ide to use blk_get_request properly if you want. > > > > > > > > > > That would be best, but the on-stack allocation has the benefit that > > > > > it'll always work. So until we can completely get rid of that, lets just > > > > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a > > > > > lot saner than doing a memset() anyway. > > > > > > > > > > > > > Just a patch that I had for ages since the bad old request bidi times, > > > > perhaps is also good today. (rebased to for-2.6.26 branch) > > > > --- > > > > From: Boaz Harrosh <bharrosh@panasas.com> > > > > Date: Wed, 16 Apr 2008 12:05:33 +0300 > > > > Subject: [PATCH] Initialize all members of struct request in rq_init > > > > > > > > Before, every member added/removed from struct request would entitle a change > > > > to rq_init, for initialization. Now all members are default to zero and only > > > > the none zero members are specifically initialized. > > > > > > > > Users that need requests on the stack or pre-allocated, must call rq_init() > > > > before use. > > > > > > > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > > > > --- > > > > block/blk-core.c | 22 ++-------------------- > > > > 1 files changed, 2 insertions(+), 20 deletions(-) > > > > > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > > > index 6f0968f..3f4c563 100644 > > > > --- a/block/blk-core.c > > > > +++ b/block/blk-core.c > > > > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info); > > > > */ > > > > void rq_init(struct request_queue *q, struct request *rq) > > > > { > > > > + memset(rq, 0, sizeof(*rq)); > > > > > > Hmm, rq_init comment says: > > > > > > /* > > > * We can't just memset() the structure, since the allocation path > > > * already stored some information in the request. > > > */ > > > > > > I think that we can't initialize rq->cmd_flags here. > > > > That is correct, the patch wont work as-is. The principle of clearing > > every member except block internal is sound and should be applied, > > though. > > While we're at it we may fix it as well (preferably in another pre-patch): > > - move setting rq->cmd_flags from blk_alloc_request() to the callers > (this is only get_request() ATM) ditto for elv_set_request() call > - re-order setting rq->cmd_flags vs calling rq_init() in get_request(), > queue_lfush() and start_ordered() ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-17 7:07 ` Jens Axboe 2008-04-17 11:55 ` Bartlomiej Zolnierkiewicz @ 2008-04-17 12:07 ` FUJITA Tomonori 1 sibling, 0 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-17 12:07 UTC (permalink / raw) To: jens.axboe Cc: fujita.tomonori, bharrosh, bzolnier, linux-scsi, linux-ide, akpm, James.Bottomley On Thu, 17 Apr 2008 09:07:05 +0200 Jens Axboe <jens.axboe@oracle.com> wrote: > On Thu, Apr 17 2008, FUJITA Tomonori wrote: > > On Wed, 16 Apr 2008 12:08:25 +0300 > > Boaz Harrosh <bharrosh@panasas.com> wrote: > > > > > On Wed, Apr 16 2008 at 11:33 +0300, Jens Axboe <jens.axboe@oracle.com> wrote: > > > > On Wed, Apr 16 2008, FUJITA Tomonori wrote: > > > >> On Wed, 16 Apr 2008 00:50:54 +0200 > > > >> Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > > >> > > > >>> Hi, > > > >>> > > > >>> On Monday 14 April 2008, Jens Axboe wrote: > > > >>>> On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > > >>>>> This patch changes rq->cmd from the static array to a pointer to > > > >>>>> support large commands. > > > >>>>> > > > >>>>> We rarely handle large commands. So for optimization, a struct request > > > >>>>> still has a static array for a command. rq_init sets rq->cmd pointer > > > >>>>> to the static array. > > > >>>>> > > > >>>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > > >>>>> Cc: Jens Axboe <jens.axboe@oracle.com> > > > >>>>> --- > > > >>>>> block/blk-core.c | 1 + > > > >>>>> drivers/ide/ide-io.c | 1 + > > > >>>>> include/linux/blkdev.h | 12 ++++++++++-- > > > >>>>> 3 files changed, 12 insertions(+), 2 deletions(-) > > > >>>>> > > > >>>>> diff --git a/block/blk-core.c b/block/blk-core.c > > > >>>>> index 6669238..6f0968f 100644 > > > >>>>> --- a/block/blk-core.c > > > >>>>> +++ b/block/blk-core.c > > > >>>>> @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > > >>>>> rq->errors = 0; > > > >>>>> rq->ref_count = 1; > > > >>>>> rq->cmd_len = 0; > > > >>>>> + rq->cmd = rq->__cmd; > > > >>>>> memset(rq->cmd, 0, BLK_MAX_CDB); > > > >>>>> rq->data_len = 0; > > > >>>>> rq->extra_len = 0; > > > >>>>> diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > > >>>>> index 7153796..bac5ea1 100644 > > > >>>>> --- a/drivers/ide/ide-io.c > > > >>>>> +++ b/drivers/ide/ide-io.c > > > >>>>> @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > > >>>>> { > > > >>>>> memset(rq, 0, sizeof(*rq)); > > > >>>>> rq->ref_count = 1; > > > >>>>> + rq->cmd = rq->__cmd; > > > >>>>> } > > > >>> Tomo, some more changes are needed: > > > >>> > > > >>> Please think about all _static_/dynamic allocations of 'struct request' > > > >>> used together with REQ_TYPE_SPECIAL etc., i.e. > > > >> I think that using struct request allocated statically is wrong from > > > >> the perspective of the block layer design, that is, you always need to > > > >> use blk_get_request. I think that except ide, everyone does. > > > >> > > > >> I try to convert ide to use blk_get_request properly if you want. > > > > > > > > That would be best, but the on-stack allocation has the benefit that > > > > it'll always work. So until we can completely get rid of that, lets just > > > > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a > > > > lot saner than doing a memset() anyway. > > > > > > > > > > Just a patch that I had for ages since the bad old request bidi times, > > > perhaps is also good today. (rebased to for-2.6.26 branch) > > > --- > > > From: Boaz Harrosh <bharrosh@panasas.com> > > > Date: Wed, 16 Apr 2008 12:05:33 +0300 > > > Subject: [PATCH] Initialize all members of struct request in rq_init > > > > > > Before, every member added/removed from struct request would entitle a change > > > to rq_init, for initialization. Now all members are default to zero and only > > > the none zero members are specifically initialized. > > > > > > Users that need requests on the stack or pre-allocated, must call rq_init() > > > before use. > > > > > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > > > --- > > > block/blk-core.c | 22 ++-------------------- > > > 1 files changed, 2 insertions(+), 20 deletions(-) > > > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > > index 6f0968f..3f4c563 100644 > > > --- a/block/blk-core.c > > > +++ b/block/blk-core.c > > > @@ -113,36 +113,18 @@ EXPORT_SYMBOL(blk_get_backing_dev_info); > > > */ > > > void rq_init(struct request_queue *q, struct request *rq) > > > { > > > + memset(rq, 0, sizeof(*rq)); > > > > Hmm, rq_init comment says: > > > > /* > > * We can't just memset() the structure, since the allocation path > > * already stored some information in the request. > > */ > > > > I think that we can't initialize rq->cmd_flags here. > > That is correct, the patch wont work as-is. The principle of clearing > every member except block internal is sound and should be applied, > though. 1) calls rq_init() and initializes rq->cmd_flags manually. 2) adds a new helper function to just memset() against rq. 3) modifies the block layer so that rq_init() can memset() against rq. 4) uses blk_get_request I think that the second option would be the best for now but I don't have a good name for such function. The third or fourth option looks preferable for me in the long term (probably, for 2.6.27). Here's a patch to initialize rq->cmd by hand. I think that it's ok for now. drivers/scsi_errro.c doesn't need this hack now (since it doesn't use struct request) but pending Boaz's extended cdbs patch needs this hack since it removes scmd->cmnd array and uses rq->cmd. === From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Subject: [PATCH] block: initialize the cmd pointer in struct request struct request that is not allocated via blk_get_request needs to set up the cmd pointer. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Jens Axboe <jens.axboe@oracle.com> --- drivers/block/nbd.c | 3 +++ drivers/block/paride/pd.c | 1 + drivers/ide/ide-tape.c | 1 + drivers/ide/ide-taskfile.c | 3 +-- drivers/ide/ide.c | 2 ++ drivers/scsi/scsi_error.c | 1 + 6 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 60cc543..ebc653d 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -534,6 +534,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file, dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n", lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg); + memset(&sreq, 0, sizeof(sreq)); + sreq.cmd = sreq.__cmd; + switch (cmd) { case NBD_DISCONNECT: printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name); diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index df819f8..e82a669 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -717,6 +717,7 @@ static int pd_special_command(struct pd_unit *disk, int err = 0; memset(&rq, 0, sizeof(rq)); + rq.cmd = rq.__cmd; rq.errors = 0; rq.rq_disk = disk->gd; rq.ref_count = 1; diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 0598ecf..d9c0267 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -946,6 +946,7 @@ static void idetape_create_request_sense_cmd(idetape_pc_t *pc) static void idetape_init_rq(struct request *rq, u8 cmd) { memset(rq, 0, sizeof(*rq)); + rq->cmd = rq->__cmd; rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd[0] = cmd; } diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 4c86a8d..1c30a57 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -529,8 +529,7 @@ int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect) { struct request rq; - memset(&rq, 0, sizeof(rq)); - rq.ref_count = 1; + ide_init_drive_cmd(&rq); rq.cmd_type = REQ_TYPE_ATA_TASKFILE; rq.buffer = buf; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index fc69fe2..96aaec2 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -881,6 +881,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg) ide_acpi_get_timing(hwif); memset(&rq, 0, sizeof(rq)); + rq.cmd = rq.__cmd; memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); rq.cmd_type = REQ_TYPE_PM_SUSPEND; @@ -919,6 +920,7 @@ static int generic_ide_resume(struct device *dev) ide_acpi_exec_tfs(drive); memset(&rq, 0, sizeof(rq)); + rq.cmd = rq.__cmd; memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); rq.cmd_type = REQ_TYPE_PM_RESUME; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 045a086..020b678 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1690,6 +1690,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag) unsigned long flags; int rtn; + req.cmd = req.__cmd; scmd->request = &req; memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); -- 1.5.4.2 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-16 8:33 ` Jens Axboe 2008-04-16 9:08 ` Boaz Harrosh @ 2008-04-17 4:02 ` FUJITA Tomonori 1 sibling, 0 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-17 4:02 UTC (permalink / raw) To: jens.axboe Cc: fujita.tomonori, bzolnier, linux-scsi, bharrosh, linux-ide, akpm On Wed, 16 Apr 2008 10:33:06 +0200 Jens Axboe <jens.axboe@oracle.com> wrote: > On Wed, Apr 16 2008, FUJITA Tomonori wrote: > > On Wed, 16 Apr 2008 00:50:54 +0200 > > Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > > > > > > > > Hi, > > > > > > On Monday 14 April 2008, Jens Axboe wrote: > > > > On Mon, Apr 14 2008, FUJITA Tomonori wrote: > > > > > This patch changes rq->cmd from the static array to a pointer to > > > > > support large commands. > > > > > > > > > > We rarely handle large commands. So for optimization, a struct request > > > > > still has a static array for a command. rq_init sets rq->cmd pointer > > > > > to the static array. > > > > > > > > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > > > > Cc: Jens Axboe <jens.axboe@oracle.com> > > > > > --- > > > > > block/blk-core.c | 1 + > > > > > drivers/ide/ide-io.c | 1 + > > > > > include/linux/blkdev.h | 12 ++++++++++-- > > > > > 3 files changed, 12 insertions(+), 2 deletions(-) > > > > > > > > > > diff --git a/block/blk-core.c b/block/blk-core.c > > > > > index 6669238..6f0968f 100644 > > > > > --- a/block/blk-core.c > > > > > +++ b/block/blk-core.c > > > > > @@ -132,6 +132,7 @@ void rq_init(struct request_queue *q, struct request *rq) > > > > > rq->errors = 0; > > > > > rq->ref_count = 1; > > > > > rq->cmd_len = 0; > > > > > + rq->cmd = rq->__cmd; > > > > > memset(rq->cmd, 0, BLK_MAX_CDB); > > > > > rq->data_len = 0; > > > > > rq->extra_len = 0; > > > > > diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c > > > > > index 7153796..bac5ea1 100644 > > > > > --- a/drivers/ide/ide-io.c > > > > > +++ b/drivers/ide/ide-io.c > > > > > @@ -1595,6 +1595,7 @@ void ide_init_drive_cmd (struct request *rq) > > > > > { > > > > > memset(rq, 0, sizeof(*rq)); > > > > > rq->ref_count = 1; > > > > > + rq->cmd = rq->__cmd; > > > > > } > > > > > > Tomo, some more changes are needed: > > > > > > Please think about all _static_/dynamic allocations of 'struct request' > > > used together with REQ_TYPE_SPECIAL etc., i.e. > > > > I think that using struct request allocated statically is wrong from > > the perspective of the block layer design, that is, you always need to > > use blk_get_request. I think that except ide, everyone does. > > > > I try to convert ide to use blk_get_request properly if you want. > > That would be best, but the on-stack allocation has the benefit that > it'll always work. So until we can completely get rid of that, lets just > make it a hard rule that ANY rq allocation MUST call rq_init(). It's a > lot saner than doing a memset() anyway. I'm fine with that. There is one minor issue. rq_init doesn't initialize rq->cmd_flags so the callers need to do it for themselves (If they don't, probably they hit BUG_ON in blk_queue_end_tag). ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-14 10:50 ` [PATCH 4/4] block: add large command support FUJITA Tomonori 2008-04-14 11:29 ` Jens Axboe @ 2008-04-14 14:41 ` Pete Wyckoff 2008-04-14 22:33 ` FUJITA Tomonori 2008-04-15 7:45 ` Boaz Harrosh 2008-04-15 7:29 ` Jens Axboe 2 siblings, 2 replies; 77+ messages in thread From: Pete Wyckoff @ 2008-04-14 14:41 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: linux-scsi, bharrosh, Jens Axboe, linux-ide fujita.tomonori@lab.ntt.co.jp wrote on Mon, 14 Apr 2008 19:50 +0900: > This patch changes rq->cmd from the static array to a pointer to > support large commands. > > We rarely handle large commands. So for optimization, a struct request > still has a static array for a command. rq_init sets rq->cmd pointer > to the static array. > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > Cc: Jens Axboe <jens.axboe@oracle.com> [..] > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > index b3a58ad..5710ae4 100644 > --- a/include/linux/blkdev.h > +++ b/include/linux/blkdev.h > @@ -215,8 +215,9 @@ struct request { > /* > * when request is used as a packet command carrier > */ > - unsigned int cmd_len; > - unsigned char cmd[BLK_MAX_CDB]; > + unsigned short cmd_len; > + unsigned char __cmd[BLK_MAX_CDB]; > + unsigned char *cmd; > > unsigned int data_len; > unsigned int extra_len; /* length of alignment and padding */ > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p) > page_cache_release(p.v); > } > > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd, > + unsigned short cmd_len) > +{ > + rq->cmd = cmd; > + rq->cmd_len = cmd_len; > +} Here's one way this will be used, in a patched bsg that understands large commands. Complication is the need to copy and hold onto the big command across the duration of the request. Submit time is fairly clean: /* buf, len from user request */ rq = blk_get_request(..); rq->cmd_len = len; if (len > BLK_MAX_CDB) { rq->cmd = kmalloc(len); if (rq->cmd == NULL) goto out; } copy_from_user(rq->cmd, buf, len); Completion time needs to know when to free rq->cmd: if (rq->cmd_len > BLK_MAX_CDB) kfree(rq->cmd); blk_put_request(rq); Could use (rq->cmd != rq->__cmd) instead, but nothing had better ever touch rq->cmd_len. I don't think the helper rq_set_cmd() will be very useful, as the caller (bsg) must think about allocation of the command buffer if it is big. One option would be to handle allocation/freeing of the big command in rq_set_... functions, but I don't think you want to constrain the interface like that. Boaz's concern about big rq->cmd_len still worries me, although I think this approach is better and worth solving bugs in drivers as they arise. It only matters in the case that someone adds, say, a bsg interface to all block devices though. The queuecommand of ub shows a good example of how this will break. In sum, this is a cleaner approach, and a bit easier for callers with long commands to deal with. And you could get rid of the trivial helper. -- Pete ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-14 14:41 ` Pete Wyckoff @ 2008-04-14 22:33 ` FUJITA Tomonori 2008-04-15 13:44 ` Pete Wyckoff 2008-04-15 7:45 ` Boaz Harrosh 1 sibling, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 22:33 UTC (permalink / raw) To: pw; +Cc: fujita.tomonori, linux-scsi, bharrosh, jens.axboe, linux-ide On Mon, 14 Apr 2008 10:41:54 -0400 Pete Wyckoff <pw@osc.edu> wrote: > fujita.tomonori@lab.ntt.co.jp wrote on Mon, 14 Apr 2008 19:50 +0900: > > This patch changes rq->cmd from the static array to a pointer to > > support large commands. > > > > We rarely handle large commands. So for optimization, a struct request > > still has a static array for a command. rq_init sets rq->cmd pointer > > to the static array. > > > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > > Cc: Jens Axboe <jens.axboe@oracle.com> > [..] > > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > > index b3a58ad..5710ae4 100644 > > --- a/include/linux/blkdev.h > > +++ b/include/linux/blkdev.h > > @@ -215,8 +215,9 @@ struct request { > > /* > > * when request is used as a packet command carrier > > */ > > - unsigned int cmd_len; > > - unsigned char cmd[BLK_MAX_CDB]; > > + unsigned short cmd_len; > > + unsigned char __cmd[BLK_MAX_CDB]; > > + unsigned char *cmd; > > > > unsigned int data_len; > > unsigned int extra_len; /* length of alignment and padding */ > > @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p) > > page_cache_release(p.v); > > } > > > > +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd, > > + unsigned short cmd_len) > > +{ > > + rq->cmd = cmd; > > + rq->cmd_len = cmd_len; > > +} > > Here's one way this will be used, in a patched bsg that understands > large commands. Complication is the need to copy and hold onto the > big command across the duration of the request. > > Submit time is fairly clean: > > /* buf, len from user request */ > rq = blk_get_request(..); > rq->cmd_len = len; > if (len > BLK_MAX_CDB) { > rq->cmd = kmalloc(len); > if (rq->cmd == NULL) > goto out; > } > copy_from_user(rq->cmd, buf, len); > > Completion time needs to know when to free rq->cmd: > > if (rq->cmd_len > BLK_MAX_CDB) > kfree(rq->cmd); > blk_put_request(rq); > > Could use (rq->cmd != rq->__cmd) instead, but nothing had better > ever touch rq->cmd_len. > > I don't think the helper rq_set_cmd() will be very useful, as the > caller (bsg) must think about allocation of the command buffer if it > is big. Yeah, I think so. If you need large command support, you need to know how to handle it for now. Now only bsg supports large commands. So I guess that nobody complains about the current interface. > One option would be to handle allocation/freeing of the big command > in rq_set_... functions, but I don't think you want to constrain the > interface like that. Or, you can change blk_get_request to take the command length argument. But I don't think that such is the right approach. > Boaz's concern about big rq->cmd_len still worries me, although I > think this approach is better and worth solving bugs in drivers as > they arise. It only matters in the case that someone adds, say, a > bsg interface to all block devices though. The queuecommand of ub > shows a good example of how this will break. Yes, a bsg hook will need to handle large commands. I don't see any problem about it. All a hook needs to do is just looking at the legnth and dropping or executing the command. And of course, we are unlikely to add a bsg device to all the block devices. As I said, if we want to govern the command length in a common place, we can have the limit of the command length in request queues. It's clear than an implicit checking with two lengths, cmd_len and ext_cdb_len. I thought about adding the code to check the command length in UB. But I thought that we were unlikely to create bsg devices for ub. Common people use USB_STORAGE rather than UB, I guess. > In sum, this is a cleaner approach, and a bit easier for callers > with long commands to deal with. And you could get rid of the > trivial helper. Yeah, it's a cleaner design, that's main point, I think. BTW, have you had a chance to try the bsg patches to fix the problems that you reported? I think that Mike and I analyzed the problem correctly and the patches works for me, but it would be nice if you can confirm that they also work for you. Thanks, ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-14 22:33 ` FUJITA Tomonori @ 2008-04-15 13:44 ` Pete Wyckoff 0 siblings, 0 replies; 77+ messages in thread From: Pete Wyckoff @ 2008-04-15 13:44 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: linux-scsi, bharrosh, jens.axboe, linux-ide fujita.tomonori@lab.ntt.co.jp wrote on Tue, 15 Apr 2008 07:33 +0900: > BTW, have you had a chance to try the bsg patches to fix the problems > that you reported? I think that Mike and I analyzed the problem > correctly and the patches works for me, but it would be nice if you > can confirm that they also work for you. It's on my TODO list. Machines were down and papers are due. But I hope you can push the patches as bug fixes anyway. -- Pete ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-14 14:41 ` Pete Wyckoff 2008-04-14 22:33 ` FUJITA Tomonori @ 2008-04-15 7:45 ` Boaz Harrosh 2008-04-15 10:05 ` FUJITA Tomonori 1 sibling, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-15 7:45 UTC (permalink / raw) To: Pete Wyckoff; +Cc: FUJITA Tomonori, linux-scsi, Jens Axboe, linux-ide On Mon, Apr 14 2008 at 17:41 +0300, Pete Wyckoff <pw@osc.edu> wrote: > fujita.tomonori@lab.ntt.co.jp wrote on Mon, 14 Apr 2008 19:50 +0900: >> This patch changes rq->cmd from the static array to a pointer to >> support large commands. >> >> We rarely handle large commands. So for optimization, a struct request >> still has a static array for a command. rq_init sets rq->cmd pointer >> to the static array. >> >> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> >> Cc: Jens Axboe <jens.axboe@oracle.com> > [..] >> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h >> index b3a58ad..5710ae4 100644 >> --- a/include/linux/blkdev.h >> +++ b/include/linux/blkdev.h >> @@ -215,8 +215,9 @@ struct request { >> /* >> * when request is used as a packet command carrier >> */ >> - unsigned int cmd_len; >> - unsigned char cmd[BLK_MAX_CDB]; >> + unsigned short cmd_len; >> + unsigned char __cmd[BLK_MAX_CDB]; >> + unsigned char *cmd; >> >> unsigned int data_len; >> unsigned int extra_len; /* length of alignment and padding */ >> @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p) >> page_cache_release(p.v); >> } >> >> +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd, >> + unsigned short cmd_len) >> +{ >> + rq->cmd = cmd; >> + rq->cmd_len = cmd_len; >> +} > > Here's one way this will be used, in a patched bsg that understands > large commands. Complication is the need to copy and hold onto the > big command across the duration of the request. > > Submit time is fairly clean: > > /* buf, len from user request */ > rq = blk_get_request(..); > rq->cmd_len = len; > if (len > BLK_MAX_CDB) { > rq->cmd = kmalloc(len); > if (rq->cmd == NULL) > goto out; > } > copy_from_user(rq->cmd, buf, len); > > Completion time needs to know when to free rq->cmd: > > if (rq->cmd_len > BLK_MAX_CDB) > kfree(rq->cmd); > blk_put_request(rq); > > Could use (rq->cmd != rq->__cmd) instead, but nothing had better > ever touch rq->cmd_len. > Don't do any of that please. The 16 bytes buffer at request is eventually going away. Just always allocate and call rq_set_cmd(). This way we are free to change in the future, and users code need not change. And better then kmalloc the space for the command, is if you have a structure that governs your request, just allocate a SCSI_MAX_VARLEN_CDB_SIZE (260) bytes array at your structure and always use that. > I don't think the helper rq_set_cmd() will be very useful, as the > caller (bsg) must think about allocation of the command buffer if it > is big. > > One option would be to handle allocation/freeing of the big command > in rq_set_... functions, but I don't think you want to constrain the > interface like that. > > Boaz's concern about big rq->cmd_len still worries me, although I > think this approach is better and worth solving bugs in drivers as > they arise. It only matters in the case that someone adds, say, a > bsg interface to all block devices though. The queuecommand of ub > shows a good example of how this will break. > > In sum, this is a cleaner approach, and a bit easier for callers > with long commands to deal with. And you could get rid of the > trivial helper. > Don't. Please use the set helper it will give us future compatibility. > -- Pete > -- Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-15 7:45 ` Boaz Harrosh @ 2008-04-15 10:05 ` FUJITA Tomonori 0 siblings, 0 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-15 10:05 UTC (permalink / raw) To: bharrosh; +Cc: pw, fujita.tomonori, linux-scsi, jens.axboe, linux-ide On Tue, 15 Apr 2008 10:45:52 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > On Mon, Apr 14 2008 at 17:41 +0300, Pete Wyckoff <pw@osc.edu> wrote: > > fujita.tomonori@lab.ntt.co.jp wrote on Mon, 14 Apr 2008 19:50 +0900: > >> This patch changes rq->cmd from the static array to a pointer to > >> support large commands. > >> > >> We rarely handle large commands. So for optimization, a struct request > >> still has a static array for a command. rq_init sets rq->cmd pointer > >> to the static array. > >> > >> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> > >> Cc: Jens Axboe <jens.axboe@oracle.com> > > [..] > >> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > >> index b3a58ad..5710ae4 100644 > >> --- a/include/linux/blkdev.h > >> +++ b/include/linux/blkdev.h > >> @@ -215,8 +215,9 @@ struct request { > >> /* > >> * when request is used as a packet command carrier > >> */ > >> - unsigned int cmd_len; > >> - unsigned char cmd[BLK_MAX_CDB]; > >> + unsigned short cmd_len; > >> + unsigned char __cmd[BLK_MAX_CDB]; > >> + unsigned char *cmd; > >> > >> unsigned int data_len; > >> unsigned int extra_len; /* length of alignment and padding */ > >> @@ -812,6 +813,13 @@ static inline void put_dev_sector(Sector p) > >> page_cache_release(p.v); > >> } > >> > >> +static inline void rq_set_cmd(struct request *rq, unsigned char *cmd, > >> + unsigned short cmd_len) > >> +{ > >> + rq->cmd = cmd; > >> + rq->cmd_len = cmd_len; > >> +} > > > > Here's one way this will be used, in a patched bsg that understands > > large commands. Complication is the need to copy and hold onto the > > big command across the duration of the request. > > > > Submit time is fairly clean: > > > > /* buf, len from user request */ > > rq = blk_get_request(..); > > rq->cmd_len = len; > > if (len > BLK_MAX_CDB) { > > rq->cmd = kmalloc(len); > > if (rq->cmd == NULL) > > goto out; > > } > > copy_from_user(rq->cmd, buf, len); > > > > Completion time needs to know when to free rq->cmd: > > > > if (rq->cmd_len > BLK_MAX_CDB) > > kfree(rq->cmd); > > blk_put_request(rq); > > > > Could use (rq->cmd != rq->__cmd) instead, but nothing had better > > ever touch rq->cmd_len. > > > > Don't do any of that please. The 16 bytes buffer at request is eventually > going away. Just always allocate and call rq_set_cmd(). This way we are > free to change in the future, and users code need not change. Hmm, it's clean for bsg, but we nearly always allocates 16 bytes dynamically. That's wasteful. Probably, we would loose some performance as we did for sense buffer. > And better then kmalloc the space for the command, is if you have > a structure that governs your request, just allocate a > SCSI_MAX_VARLEN_CDB_SIZE (260) bytes array at your structure and always > use that. I don't put 260 bytes into bsg_command structure. I don't see why bsg needs to be tuned up for OSD or for SCSI commands. ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] block: add large command support 2008-04-14 10:50 ` [PATCH 4/4] block: add large command support FUJITA Tomonori 2008-04-14 11:29 ` Jens Axboe 2008-04-14 14:41 ` Pete Wyckoff @ 2008-04-15 7:29 ` Jens Axboe 2 siblings, 0 replies; 77+ messages in thread From: Jens Axboe @ 2008-04-15 7:29 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: linux-scsi, bharrosh, linux-ide On Mon, Apr 14 2008, FUJITA Tomonori wrote: > This patch changes rq->cmd from the static array to a pointer to > support large commands. > > We rarely handle large commands. So for optimization, a struct request > still has a static array for a command. rq_init sets rq->cmd pointer > to the static array. I applied 1-4, thanks. -- Jens Axboe ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 0/4] add large command support to the block layer 2008-04-14 10:50 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori @ 2008-04-14 11:21 ` FUJITA Tomonori 2008-04-14 11:38 ` Boaz Harrosh 2008-04-15 12:24 ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh 3 siblings, 0 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 11:21 UTC (permalink / raw) To: jens.axboe Cc: linux-scsi, bharrosh, bzolnier, James.Bottomley, agk, Geert.Uytterhoeven, fujita.tomonori On Mon, 14 Apr 2008 19:50:33 +0900 FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > This patchset adds large command support to the block layer. Forgot to add: the patchset are against for for-2.6.26 branch in Jens' block tree. ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 0/4] add large command support to the block layer 2008-04-14 10:50 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori 2008-04-14 11:21 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori @ 2008-04-14 11:38 ` Boaz Harrosh 2008-04-14 12:36 ` Boaz Harrosh 2008-04-15 12:24 ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh 3 siblings, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-14 11:38 UTC (permalink / raw) To: FUJITA Tomonori Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz, James Bottomley, Alasdair G Kergon, Geert Uytterhoeven On Mon, Apr 14 2008 at 13:50 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > This patchset adds large command support to the block layer. > > We rarely handle large commands. So for optimization, a struct request > still has a static array for a command. rq_init sets rq->cmd pointer > to the static array. In short, rq_init() does > > rq->cmd = rq->__cmd; > > So we can access to rq->cmd and rq->cmd_len as before. > > Boaz argues that having single cmd_len is dangerous: > >> Because this way it is dangerous if large commands are issued to legacy >> drivers. In scsi-land we have .cmd_len at host template that will govern if >> we are allow to issue larger commands to the driver. In block devices we do >> not have such a facility, and the danger is if such commands are issued through >> bsg or other means, even by malicious code. What you say is the ideal and it > > I don't see how it is dangerous. We don't send large commands to block > devices via bsg. We can send large commands to block devices via only > SG_IO. SG_IO (block/scsi_ioctl.c) forbids us sending commands large > than 16 bytes, BLK_MAX_CDB. So how can we send large commands to block > devices? > > The first, second, and third patches are safe cleanups (a preparation > for changing rq->cmd from the static array to a pointer). They don't > conflict with Boaz's patchset. Even if we choose Boaz's approach now, > we'll move to the approach to have one command length in struct > request in the long term. So they can be applied now. > > The forth patch adds large command support. It's a substitute for > Boaz's second patch. It's pretty simple except for one hack for > ide-io. It's necessary since the ide subsystem allocates struct > request without using blk_get_request. In the long term, it would > better to convert it to use blk_get_request properly. > > I still think that my last patch with one cmd_len and the Union is nicer and more simple. And does not waist the extra pointer that is never ever used but by me. (And does not need 3 preparation patches) Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 0/4] add large command support to the block layer 2008-04-14 11:38 ` Boaz Harrosh @ 2008-04-14 12:36 ` Boaz Harrosh 2008-04-14 13:06 ` FUJITA Tomonori 0 siblings, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-14 12:36 UTC (permalink / raw) To: FUJITA Tomonori Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz, James Bottomley, Alasdair G Kergon, Geert Uytterhoeven On Mon, Apr 14 2008 at 14:38 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: > On Mon, Apr 14 2008 at 13:50 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: >> This patchset adds large command support to the block layer. >> >> We rarely handle large commands. So for optimization, a struct request >> still has a static array for a command. rq_init sets rq->cmd pointer >> to the static array. In short, rq_init() does >> >> rq->cmd = rq->__cmd; >> >> So we can access to rq->cmd and rq->cmd_len as before. >> >> Boaz argues that having single cmd_len is dangerous: >> >>> Because this way it is dangerous if large commands are issued to legacy >>> drivers. In scsi-land we have .cmd_len at host template that will govern if >>> we are allow to issue larger commands to the driver. In block devices we do >>> not have such a facility, and the danger is if such commands are issued through >>> bsg or other means, even by malicious code. What you say is the ideal and it >> I don't see how it is dangerous. We don't send large commands to block >> devices via bsg. We can send large commands to block devices via only >> SG_IO. SG_IO (block/scsi_ioctl.c) forbids us sending commands large >> than 16 bytes, BLK_MAX_CDB. So how can we send large commands to block >> devices? >> >> The first, second, and third patches are safe cleanups (a preparation >> for changing rq->cmd from the static array to a pointer). They don't >> conflict with Boaz's patchset. Even if we choose Boaz's approach now, >> we'll move to the approach to have one command length in struct >> request in the long term. So they can be applied now. >> >> The forth patch adds large command support. It's a substitute for >> Boaz's second patch. It's pretty simple except for one hack for >> ide-io. It's necessary since the ide subsystem allocates struct >> request without using blk_get_request. In the long term, it would >> better to convert it to use blk_get_request properly. >> >> > > I still think that my last patch with one cmd_len and the Union is > nicer and more simple. And does not waist the extra pointer that is > never ever used but by me. (And does not need 3 preparation patches) > > Boaz > Tomo hi. Please don't miss understand me. ACK-by: Boaz Harrosh <bharrosh@panasas.com> I really don't mind, it is fine by me and it does what I want. So thanks yes please push this through, and I'll rebase my two patches to yours. Thanks Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 0/4] add large command support to the block layer 2008-04-14 12:36 ` Boaz Harrosh @ 2008-04-14 13:06 ` FUJITA Tomonori 0 siblings, 0 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-14 13:06 UTC (permalink / raw) To: bharrosh Cc: fujita.tomonori, linux-scsi, jens.axboe, bzolnier, James.Bottomley, agk, Geert.Uytterhoeven On Mon, 14 Apr 2008 15:22:21 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > On Mon, Apr 14 2008 at 15:08 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > > On Mon, 14 Apr 2008 14:28:45 +0300 > > Boaz Harrosh <bharrosh@panasas.com> wrote: > > > >> On Mon, Apr 14 2008 at 14:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > >>> On Mon, 14 Apr 2008 12:49:49 +0300 > >>> Boaz Harrosh <bharrosh@panasas.com> wrote: > >>> > >>>> On Sun, Apr 13 2008 at 19:50 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: > >>>>> On Sun, Apr 13 2008 at 19:17 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > >>>>>> On Sun, 13 Apr 2008 12:13:18 +0300 > >>>>>> Boaz Harrosh <bharrosh@panasas.com> wrote: > >>>>>> > >>>>>> That's a ugly hack for me. > >>>>>> > >>>>>> Why do we have two separate systems to represent the command length? > >>>>>> If the command length is smaller than 16 bytes, we use cmd_len. If the > >>>>>> length is larger than 16 bytes, we use varlen_cdb_len? > >>>>>> > >>>>>> For me, as Jens proposed, having only cmd_len is the right way. > >>>>>> > >>>>>> And 'cdb' name is not appropriate for the block layer, I think. > >>>>>> > >>>>>> I agreed that changing the block layer and the scsi midlayer gradually > >>>>>> is a safe option. Shortly, I'll send patches to clean up the hack on > >>>>>> the top of your patchset. > >>>>>> -- > >>>>> Sorry TOMO, I was sending the ver2 patchset and only saw your mail in > >>>>> the middle, so anyway you have the latest I have now. > >>>>> > >>>>> If it's ok with you I will squash your patches onto mine and add your > >>>>> sign-off-by. There is no use putting code in the tree that will be changed > >>>>> immediately after. > >>>>> > >>>>> Please note that I'm a bit afraid to put code that has both length as one > >>>>> if you are more confident then me, I will take your word for it. > >>>>> > >>>>> Thanks for helping out, as you can see I did it very safe, but with your > >>>>> help maybe it can finally go in. Thanks++ > >>>>> > >>>>> Boaz > >>>>> -- > >>>> Maybe you mean something like below. I changed cdb => cmd and I use one > >>>> cmd_len. I think that "cdb" was a good name. Note that we have BLK_MAX_CDB > >>>> right there next to it. But if you don't like it then I don't mind to > >>>> change the name, I think it was James idea. > >>> I don't. I've been talking mainly about how to represent the length of > >>> command. > >>> > >>> About 'cdb' name, I thought that there is a better name than > >>> BLK_MAX_CDB. But it's up to Jens. > >>> > >>> > >>>> But please note!!! > >>>> I think having one cmd_len is DANGEROUS. And it forces a full code audit > >>>> to be sure, has with my approach we are much more safe. There, I said it. > >>> Could you be more specific? So far, you have not explained how it can > >>> be dangerous. > >> There is a pending patch by Pete, and our main goal, is to push OSD commands > >> through bsg. All over the kernel there are cooked up char-devices, like in > >> gdth, that do vendor specific management commands. All these, and future, > >> special-command can go from user-mode through bsg in a common way. Via support > >> of vendor specific and extended commands. All the new scsi defined commands > >> that are bigger then 16 are not going to be sent through sg, but through > >> bsg right? So we do want to use this facility from kernel and from user-land > >> but we need some protection. In scsi LLDs we have .max_cmnd but block devices > >> don't have that. So either you need to restrict what can be done, or play it safe > >> like I did. > > > > If we creates bsg devices for block devices, of course, we need to a > > mechanism to govern the length of commands. > > > > But why do you want to create bsg devices for block devices? If block > > devices want large commands for some reasons, their bsg hook functions > > need to handle the length of commands anyway. There is no reason that > > the block layer has two values to represent one item, the length of > > command. > > > > If we want to govern the command length in a common place, then I > > think that it would be better to add the limit to request queue. > > > > And again, what are your block devices? What do they want bsg for? > > -- > > I don't have any block devices personally. I just thought that the diff > between sg a bsg is that bsg will support any block device, so I guess > I was wrong, bsg is a user-to-scsi bridge just like sg is. I thought > bsg registers on every request_queue, how does bsg filter which devices > to export and which not? bsg is not a user-to-scsi bridge just like sg is. You can create bsg devices for any request queue but we don't create bsg devices for every request queue in kernel. When you create a bsg device, you need your hook funciton to perform a request via the bsg device. The hook function needs to handle large commands if necessary. If you are interested in how bsg works for non scsi devices, see scsi_transport_sas.c. It creates bsg devices for sas objects to handle SMP requests. > What about the union, don't we care about the space saved? I think that the approach to use a cmd pointer is clearer. But it's up to Jens. ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 0/3] scsi: variable-length CDBs support 2008-04-14 10:50 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori ` (2 preceding siblings ...) 2008-04-14 11:38 ` Boaz Harrosh @ 2008-04-15 12:24 ` Boaz Harrosh 2008-04-15 12:30 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh ` (2 more replies) 3 siblings, 3 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-15 12:24 UTC (permalink / raw) To: FUJITA Tomonori Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz, James Bottomley, Alasdair G Kergon, Geert Uytterhoeven Based on TOMO's block patches for supporting large commands These patches will enable support for variable-length, extended, and vendor specific CDBs. It should now cover the entire range of the SCSI standard. These patches are independent of TOMO's patches to the block layer, because the block layer API for drivers did not change. So all I did was make sure nothing will break when large commands start coming. They are based on scsi-misc and could go in as is. I have tested my OSD setup with scsi-misc + for-2.6.26 branch from Jens + these patches and it all works fine. So I'm happy. [1/3] Let scsi_cmnd->cmnd use request->cmd buffer Here I let scsi_cmnd->cmnd point to the space allocated by request->cmd, instead of copying the data. The scsi_cmnd->cmd_len is guaranteed to contain the right length of the command. I have tried to go over every single place in the kernel that uses scsi_cmnd->cmnd and make sure it looks sane. Surprisingly to me, that was not at all bad. I hope I did not miss anything. I've tested on an x86_64 machine booting from a sata disk and ran the iscsi regression tests as well as my bidi and varlen tests on top of the complete patchset and all tests passed. [2/3] scsi: varlen extended and vendor-specific cdbs Adds support for variable length, extended, and vendor-specific cdbs at the scsi mid-layer. [3/3] iscsi_tcp: Enable large commands One liner for iscsi_tcp. Mike please ACK this patch Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer 2008-04-15 12:24 ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh @ 2008-04-15 12:30 ` Boaz Harrosh 2008-04-15 12:34 ` [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh 2008-04-15 12:37 ` [PATCH 3/3] iscsi_tcp: Enable large commands Boaz Harrosh 2 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-15 12:30 UTC (permalink / raw) To: FUJITA Tomonori, James Bottomley Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz, Alasdair G Kergon, Geert Uytterhoeven - struct scsi_cmnd had a 16 bytes command buffer of its own. This is an unnecessary duplication and copy of request's cmd. It is probably left overs from the time that scsi_cmnd could function without a request attached. So clean that up. - Once above is done, few places, apart from scsi-ml, needed adjustments due to changing the data type of scsi_cmnd->cmnd. - Lots of drivers still use MAX_COMMAND_SIZE. So I have left that #define but equate it to BLK_MAX_CDB. The way I see it and is reflected in the patch below is. MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB as per the SCSI standard and is not related to the implementation. BLK_MAX_CDB. - The allocated space at the request level - I have audit all ISA drivers and made sure none use ->cmnd in a DMA Operation. Same audit was done by Andi Kleen. (*)fixed-length here means commands that their size can be determined by their opcode and the CDB does not carry a length specifier, (unlike the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly true and the SCSI standard also defines extended commands and vendor specific commands that can be bigger than 16 bytes. The kernel will support these using the same infrastructure used for VARLEN CDB's. So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml supports without specifying a cmd_len by ULD's Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- drivers/firewire/fw-sbp2.c | 2 +- drivers/s390/scsi/zfcp_dbf.c | 2 +- drivers/s390/scsi/zfcp_fsf.c | 2 +- drivers/scsi/53c700.c | 6 +++--- drivers/scsi/a100u2w.c | 2 +- drivers/scsi/gdth.c | 2 +- drivers/scsi/hptiop.c | 6 +++--- drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- drivers/scsi/initio.c | 2 +- drivers/scsi/qla1280.c | 4 ++-- drivers/scsi/scsi_error.c | 14 ++++++++------ drivers/scsi/scsi_lib.c | 5 +++-- drivers/scsi/scsi_tgt_lib.c | 2 ++ drivers/usb/storage/isd200.c | 2 ++ include/scsi/scsi_cmnd.h | 21 +++++++++++++++++++-- include/scsi/scsi_eh.h | 4 ++-- 16 files changed, 51 insertions(+), 27 deletions(-) diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 62b4e47..2260e56 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -1492,7 +1492,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) memset(orb->request.command_block, 0, sizeof(orb->request.command_block)); - memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); + memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len); orb->base.callback = complete_command_orb; orb->base.request_bus = diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 85ba4cc..1bec0b2 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -1057,7 +1057,7 @@ static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level, rec->scsi_result = scsi_cmnd->result; rec->scsi_cmnd = (unsigned long)scsi_cmnd; rec->scsi_serial = scsi_cmnd->serial_number; - memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd, + memcpy(rec->scsi_opcode, scsi_cmnd->cmnd, min((int)scsi_cmnd->cmd_len, ZFCP_DBF_SCSI_OPCODE)); rec->scsi_retries = scsi_cmnd->retries; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index b7aa969..ea46881 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4024,7 +4024,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n", scpnt->result); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, - (void *) &scpnt->cmnd, scpnt->cmd_len); + scpnt->cmnd, scpnt->cmd_len); ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n", fcp_rsp_iu->fcp_sns_len); diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index f4c4fe9..f5a9add 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, (struct NCR_700_command_slot *)SCp->host_scribble; dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); + MAX_COMMAND_SIZE, DMA_TO_DEVICE); if (slot->flags == NCR_700_FLAG_AUTOSENSE) { char *cmnd = NCR_700_get_sense_cmnd(SCp->device); #ifdef NCR_700_DEBUG @@ -1004,7 +1004,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, * here */ NCR_700_unmap(hostdata, SCp, slot); dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), + MAX_COMMAND_SIZE, DMA_TO_DEVICE); cmnd[0] = REQUEST_SENSE; @@ -1901,7 +1901,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) } slot->resume_offset = 0; slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); + MAX_COMMAND_SIZE, DMA_TO_DEVICE); NCR_700_start_command(SCp); return 0; } diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 792b2e8..ced3eeb 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -895,7 +895,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru } else { scb->tag_msg = 0; /* No tag support */ } - memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len); + memcpy(scb->cdb, cmd->cmnd, scb->cdb_len); } /** diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index c6d6e7c..8e2e964 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -465,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, scp->request = (struct request *)&wait; scp->timeout_per_command = timeout*HZ; scp->cmd_len = 12; - memcpy(scp->cmnd, cmnd, 12); + scp->cmnd = cmnd; cmndinfo.priority = IOCTL_PRI; cmndinfo.internal_cmd_str = gdtcmd; cmndinfo.internal_command = 1; diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index beecda9..a24c5e3 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -763,9 +763,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, scp, host->host_no, scp->device->channel, scp->device->id, scp->device->lun, - *((u32 *)&scp->cmnd), - *((u32 *)&scp->cmnd + 1), - *((u32 *)&scp->cmnd + 2), + ((u32 *)scp->cmnd)[0], + ((u32 *)scp->cmnd)[1], + ((u32 *)scp->cmnd)[2], _req->index, _req->req_virt); scp->result = 0; diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 78d46a9..df9b865 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -738,7 +738,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, srp_cmd = &evt_struct->iu.srp.cmd; memset(srp_cmd, 0x00, SRP_MAX_IU_LEN); srp_cmd->opcode = SRP_CMD; - memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd)); + memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb)); srp_cmd->lun = ((u64) lun) << 48; if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index dbae3fd..e3f7397 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c cblk->hastat = 0; cblk->tastat = 0; /* Command the command */ - memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len); + memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len); /* Set up tags */ if (cmnd->device->tagged_supported) { /* Tag Support */ diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 68c0d09..b53420b 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -2863,7 +2863,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Load SCSI command packet. */ pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd)); /* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ /* Set transfer direction. */ @@ -3132,7 +3132,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Load SCSI command packet. */ pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd)); /*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ /* Set transfer direction. */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 221f31e..8b5748a 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -626,7 +626,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) * @scmd: SCSI command structure to hijack * @ses: structure to save restore information * @cmnd: CDB to send. Can be NULL if no new cmnd is needed - * @cmnd_size: size in bytes of @cmnd + * @cmnd_size: size in bytes of @cmnd (must be <= BLK_MAX_CDB) * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) * * This function is used to save a scsi command information before re-execution @@ -648,12 +648,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, * command. */ ses->cmd_len = scmd->cmd_len; - memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd)); + ses->cmnd = scmd->cmnd; ses->data_direction = scmd->sc_data_direction; ses->sdb = scmd->sdb; ses->next_rq = scmd->request->next_rq; ses->result = scmd->result; + scmd->cmnd = ses->eh_cmnd; + memset(scmd->cmnd, 0, BLK_MAX_CDB); memset(&scmd->sdb, 0, sizeof(scmd->sdb)); scmd->request->next_rq = NULL; @@ -665,14 +667,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, scmd->sdb.table.sgl = &ses->sense_sgl; scmd->sc_data_direction = DMA_FROM_DEVICE; scmd->sdb.table.nents = 1; - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); scmd->cmnd[0] = REQUEST_SENSE; scmd->cmnd[4] = scmd->sdb.length; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } else { scmd->sc_data_direction = DMA_NONE; if (cmnd) { - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); + BUG_ON(cmnd_size > BLK_MAX_CDB); memcpy(scmd->cmnd, cmnd, cmnd_size); scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } @@ -705,7 +706,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) * Restore original data */ scmd->cmd_len = ses->cmd_len; - memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd)); + scmd->cmnd = ses->cmnd; scmd->sc_data_direction = ses->data_direction; scmd->sdb = ses->sdb; scmd->request->next_rq = ses->next_rq; @@ -1774,7 +1775,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scmd->request = &req; memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); - memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd)); + scmd->cmnd = req.cmd; + memset(scmd->cmnd, 0, BLK_MAX_CDB); scmd->scsi_done = scsi_reset_provider_done_command; memset(&scmd->sdb, 0, sizeof(scmd->sdb)); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 67f412b..325270b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1090,6 +1090,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, cmd->tag = req->tag; cmd->request = req; + cmd->cmnd = req->cmd; + return cmd; } @@ -1127,8 +1129,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) req->buffer = NULL; } - BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); - memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); cmd->cmd_len = req->cmd_len; if (!req->data_len) cmd->sc_data_direction = DMA_NONE; @@ -1165,6 +1165,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) if (unlikely(!cmd)) return BLKPREP_DEFER; + memset(cmd->cmnd, 0, BLK_MAX_CDB); return scsi_init_io(cmd, GFP_ATOMIC); } EXPORT_SYMBOL(scsi_setup_fs_cmnd); diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index a0f308b..8c92ef3 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -107,6 +107,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, cmd->jiffies_at_alloc = jiffies; cmd->request = rq; + cmd->cmnd = rq->cmd; + rq->special = cmd; rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd_flags |= REQ_TYPE_BLOCK_PC; diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 971d13d..3addcd8 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -292,6 +292,7 @@ struct isd200_info { /* maximum number of LUNs supported */ unsigned char MaxLUNs; + unsigned char cmnd[BLK_MAX_CDB]; struct scsi_cmnd srb; struct scatterlist sg; }; @@ -450,6 +451,7 @@ static int isd200_action( struct us_data *us, int action, memset(&ata, 0, sizeof(ata)); memset(&srb_dev, 0, sizeof(srb_dev)); + srb->cmnd = info->cmnd; srb->device = &srb_dev; ++srb->serial_number; diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 8d20e60..dea73e5 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -7,10 +7,28 @@ #include <linux/types.h> #include <linux/timer.h> #include <linux/scatterlist.h> +#include <linux/blkdev.h> struct Scsi_Host; struct scsi_device; +/* + * MAX_COMMAND_SIZE is: + * The longest fixed-length SCSI CDB as per the SCSI standard. + * fixed-length means: commands that their size can be determined + * by their opcode and the CDB does not carry a length specifier, (unlike + * the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly + * true and the SCSI standard also defines extended commands and + * vendor specific commands that can be bigger than 16 bytes. The kernel + * will support these using the same infrastructure used for VARLEN CDB's. + * So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml + * supports without specifying a cmd_len by ULD's + */ +#define MAX_COMMAND_SIZE 16 +#if (MAX_COMMAND_SIZE > BLK_MAX_CDB) +# error MAX_COMMAND_SIZE can not be smaller than BLK_MAX_CDB +#endif + struct scsi_data_buffer { struct sg_table table; unsigned length; @@ -64,8 +82,7 @@ struct scsi_cmnd { enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ -#define MAX_COMMAND_SIZE 16 - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char *cmnd; struct timer_list eh_timeout; /* Used to time out the command. */ diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index d3a133b..2a9add2 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -75,11 +75,11 @@ struct scsi_eh_save { int result; enum dma_data_direction data_direction; unsigned char cmd_len; - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char *cmnd; struct scsi_data_buffer sdb; struct request *next_rq; - /* new command support */ + unsigned char eh_cmnd[BLK_MAX_CDB]; struct scatterlist sense_sgl; }; -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs 2008-04-15 12:24 ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh 2008-04-15 12:30 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh @ 2008-04-15 12:34 ` Boaz Harrosh 2008-04-16 2:09 ` FUJITA Tomonori 2008-04-15 12:37 ` [PATCH 3/3] iscsi_tcp: Enable large commands Boaz Harrosh 2 siblings, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-15 12:34 UTC (permalink / raw) To: FUJITA Tomonori, James Bottomley Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz, Alasdair G Kergon, Geert Uytterhoeven Add support for variable-length, extended, and vendor specific CDBs to scsi-ml. It is now possible for initiators and ULD's to issue these types of commands. LLDs need not change much. All they need is to raise the .max_cmd_len to the longest command they support (see iscsi patch). - clean-up some code paths that did not expect commands to be larger than 16, and change cmd_len members' type to short as char is not enough. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> --- block/scsi_ioctl.c | 5 ++--- drivers/scsi/constants.c | 10 +++------- drivers/scsi/scsi.c | 22 +++++++++++----------- drivers/scsi/scsi_lib.c | 8 ++++++-- include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- include/scsi/scsi_cmnd.h | 2 +- include/scsi/scsi_host.h | 8 +++----- 7 files changed, 59 insertions(+), 36 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a2c3a93..aaf07e4 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -33,13 +33,12 @@ #include <scsi/scsi_cmnd.h> /* Command group 3 is reserved and should never be used. */ -const unsigned char scsi_command_size[8] = +const unsigned char scsi_command_size_tbl[8] = { 6, 10, 10, 12, 16, 12, 10, 10 }; - -EXPORT_SYMBOL(scsi_command_size); +EXPORT_SYMBOL(scsi_command_size_tbl); #include <scsi/sg.h> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 403a7f2..9785d73 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -28,7 +28,6 @@ #define SERVICE_ACTION_OUT_12 0xa9 #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f -#define VARIABLE_LENGTH_CMD 0x7f @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short variable length command, " "len=%d ext_len=%d", len, cdb_len); @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short opcode=0x%x command, len=%d " "ext_len=%d", cdb0, len, cdb_len); @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) int k, len; print_opcode_name(cdb, 0); - if (VARIABLE_LENGTH_CMD == cdb[0]) - len = cdb[7] + 8; - else - len = COMMAND_SIZE(cdb[0]); + len = scsi_command_size(cdb); /* print out all bytes in cdb */ for (k = 0; k < len; ++k) printk(" %02x", cdb[k]); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index f6980bd..3dabecb 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); #define MIN_RESET_PERIOD (15*HZ) /* - * Macro to determine the size of SCSI command. This macro takes vendor - * unique commands into account. SCSI commands in groups 6 and 7 are - * vendor unique and we will depend upon the command length being - * supplied correctly in cmd_len. - */ -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) - -/* * Note - the initial logging level can be set here to log events at boot time. * After the system is up, you may enable logging via the /proc interface. */ @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) unsigned long flags = 0; unsigned long timeout; int rtn = 0; + unsigned cmd_len; /* check if the device is still usable */ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * Before we queue this command, check if the command * length exceeds what the host adapter can handle. */ - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { + cmd_len = cmd->cmd_len; + if (!cmd_len) { + BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD); + cmd_len = COMMAND_SIZE((cmd)->cmnd[0]); + } + + if (cmd_len > cmd->device->host->max_cmd_len) { SCSI_LOG_MLQUEUE(3, - printk("queuecommand : command too long.\n")); + printk("queuecommand : command too long. " + "cdb_size=%d host->max_cmd_len=%d\n", + cmd->cmd_len, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT << 16); scsi_done(cmd); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 325270b..e621505 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, req->cmd_len = COMMAND_SIZE(cmd[0]); memcpy(req->cmd, cmd, req->cmd_len); + req->sense = sense; req->sense_len = 0; req->retries = retries; @@ -445,7 +446,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) scsi_set_resid(cmd, 0); memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); if (cmd->cmd_len == 0) - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); + cmd->cmd_len = scsi_command_size(cmd->cmnd); } void scsi_device_unbusy(struct scsi_device *sdev) @@ -1130,13 +1131,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) } cmd->cmd_len = req->cmd_len; + if (!cmd->cmd_len) + cmd->cmd_len = scsi_command_size(cmd->cmnd); + if (!req->data_len) cmd->sc_data_direction = DMA_NONE; else if (rq_data_dir(req) == WRITE) cmd->sc_data_direction = DMA_TO_DEVICE; else cmd->sc_data_direction = DMA_FROM_DEVICE; - + cmd->transfersize = req->data_len; cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 1f74bcd..32742c4 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -30,13 +30,6 @@ #endif /* - * SCSI command lengths - */ - -extern const unsigned char scsi_command_size[8]; -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] - -/* * Special value for scanning to specify scanning or rescanning of all * possible channels, (target) ids, or luns on a given shost. */ @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8]; #define MODE_SENSE_10 0x5a #define PERSISTENT_RESERVE_IN 0x5e #define PERSISTENT_RESERVE_OUT 0x5f +#define VARIABLE_LENGTH_CMD 0x7f #define REPORT_LUNS 0xa0 #define MAINTENANCE_IN 0xa3 #define MOVE_MEDIUM 0xa5 @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8]; #define ATA_12 0xa1 /* 12-byte pass-thru */ /* + * SCSI command lengths + */ + +#define SCSI_MAX_VARLEN_CDB_SIZE 260 + +/* defined in T10 SCSI Primary Commands-2 (SPC2) */ +struct scsi_varlen_cdb_hdr { + u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */ + u8 control; + u8 misc[5]; + u8 additional_cdb_length; /* total cdb length - 8 */ + __be16 service_action; + /* service specific data follows */ +}; + +static inline unsigned +scsi_varlen_cdb_length(const void *hdr) +{ + return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8; +} + +extern const unsigned char scsi_command_size_tbl[8]; +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] + +static inline unsigned +scsi_command_size(const unsigned char *cmnd) +{ + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? + scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]); +} + +/* * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft * T10/1561-D Revision 4 Draft dated 7th November 2002. */ diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index dea73e5..f4dacb1 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -78,7 +78,7 @@ struct scsi_cmnd { int allowed; int timeout_per_command; - unsigned char cmd_len; + unsigned short cmd_len; enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 4913286..31f1bfd 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -573,13 +573,11 @@ struct Scsi_Host { /* * The maximum length of SCSI commands that this host can accept. * Probably 12 for most host adapters, but could be 16 for others. + * or 260 if the driver supports variable length cdbs. * For drivers that don't set this field, a value of 12 is - * assumed. I am leaving this as a number rather than a bit - * because you never know what subsequent SCSI standards might do - * (i.e. could there be a 20 byte or a 24-byte command a few years - * down the road?). + * assumed. */ - unsigned char max_cmd_len; + unsigned short max_cmd_len; int this_id; int can_queue; -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs 2008-04-15 12:34 ` [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh @ 2008-04-16 2:09 ` FUJITA Tomonori 2008-04-16 6:40 ` Boaz Harrosh 0 siblings, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-16 2:09 UTC (permalink / raw) To: bharrosh Cc: fujita.tomonori, James.Bottomley, linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven On Tue, 15 Apr 2008 15:34:47 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > > Add support for variable-length, extended, and vendor specific > CDBs to scsi-ml. It is now possible for initiators and ULD's > to issue these types of commands. LLDs need not change much. > All they need is to raise the .max_cmd_len to the longest command > they support (see iscsi patch). > > - clean-up some code paths that did not expect commands to be > larger than 16, and change cmd_len members' type to short as > char is not enough. > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > Signed-off-by: Benny Halevy <bhalevy@panasas.com> > --- > block/scsi_ioctl.c | 5 ++--- > drivers/scsi/constants.c | 10 +++------- > drivers/scsi/scsi.c | 22 +++++++++++----------- > drivers/scsi/scsi_lib.c | 8 ++++++-- > include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- > include/scsi/scsi_cmnd.h | 2 +- > include/scsi/scsi_host.h | 8 +++----- > 7 files changed, 59 insertions(+), 36 deletions(-) > > diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c > index a2c3a93..aaf07e4 100644 > --- a/block/scsi_ioctl.c > +++ b/block/scsi_ioctl.c > @@ -33,13 +33,12 @@ > #include <scsi/scsi_cmnd.h> > > /* Command group 3 is reserved and should never be used. */ > -const unsigned char scsi_command_size[8] = > +const unsigned char scsi_command_size_tbl[8] = > { > 6, 10, 10, 12, > 16, 12, 10, 10 > }; > - > -EXPORT_SYMBOL(scsi_command_size); > +EXPORT_SYMBOL(scsi_command_size_tbl); > > #include <scsi/sg.h> > > diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c > index 403a7f2..9785d73 100644 > --- a/drivers/scsi/constants.c > +++ b/drivers/scsi/constants.c > @@ -28,7 +28,6 @@ > #define SERVICE_ACTION_OUT_12 0xa9 > #define SERVICE_ACTION_IN_16 0x9e > #define SERVICE_ACTION_OUT_16 0x9f > -#define VARIABLE_LENGTH_CMD 0x7f > > > > @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) > cdb0 = cdbp[0]; > switch(cdb0) { > case VARIABLE_LENGTH_CMD: > - len = cdbp[7] + 8; > + len = scsi_varlen_cdb_length(cdbp); > if (len < 10) { > printk("short variable length command, " > "len=%d ext_len=%d", len, cdb_len); > @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) > cdb0 = cdbp[0]; > switch(cdb0) { > case VARIABLE_LENGTH_CMD: > - len = cdbp[7] + 8; > + len = scsi_varlen_cdb_length(cdbp); > if (len < 10) { > printk("short opcode=0x%x command, len=%d " > "ext_len=%d", cdb0, len, cdb_len); > @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) > int k, len; > > print_opcode_name(cdb, 0); > - if (VARIABLE_LENGTH_CMD == cdb[0]) > - len = cdb[7] + 8; > - else > - len = COMMAND_SIZE(cdb[0]); > + len = scsi_command_size(cdb); > /* print out all bytes in cdb */ > for (k = 0; k < len; ++k) > printk(" %02x", cdb[k]); > diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c > index f6980bd..3dabecb 100644 > --- a/drivers/scsi/scsi.c > +++ b/drivers/scsi/scsi.c > @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); > #define MIN_RESET_PERIOD (15*HZ) > > /* > - * Macro to determine the size of SCSI command. This macro takes vendor > - * unique commands into account. SCSI commands in groups 6 and 7 are > - * vendor unique and we will depend upon the command length being > - * supplied correctly in cmd_len. > - */ > -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ > - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) > - > -/* > * Note - the initial logging level can be set here to log events at boot time. > * After the system is up, you may enable logging via the /proc interface. > */ > @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) > unsigned long flags = 0; > unsigned long timeout; > int rtn = 0; > + unsigned cmd_len; > > /* check if the device is still usable */ > if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { > @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) > * Before we queue this command, check if the command > * length exceeds what the host adapter can handle. > */ > - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { > + cmd_len = cmd->cmd_len; > + if (!cmd_len) { > + BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD); > + cmd_len = COMMAND_SIZE((cmd)->cmnd[0]); > + } Hmm, how can cmd->cmd_len be zero here? > + if (cmd_len > cmd->device->host->max_cmd_len) { > SCSI_LOG_MLQUEUE(3, > - printk("queuecommand : command too long.\n")); > + printk("queuecommand : command too long. " > + "cdb_size=%d host->max_cmd_len=%d\n", > + cmd->cmd_len, cmd->device->host->max_cmd_len)); > cmd->result = (DID_ABORT << 16); Why can't we just do: if (scsi_command_size(cmd->cmnd) > cmd->device->host->max_cmd_len) { > scsi_done(cmd); > diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c > index 325270b..e621505 100644 > --- a/drivers/scsi/scsi_lib.c > +++ b/drivers/scsi/scsi_lib.c > @@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, > > req->cmd_len = COMMAND_SIZE(cmd[0]); > memcpy(req->cmd, cmd, req->cmd_len); > + Please don't put a new line at a place unrelated with this patch. > req->sense = sense; > req->sense_len = 0; > req->retries = retries; > @@ -445,7 +446,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) > scsi_set_resid(cmd, 0); > memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); > if (cmd->cmd_len == 0) > - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); > + cmd->cmd_len = scsi_command_size(cmd->cmnd); > } > > void scsi_device_unbusy(struct scsi_device *sdev) > @@ -1130,13 +1131,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) > } > > cmd->cmd_len = req->cmd_len; > + if (!cmd->cmd_len) > + cmd->cmd_len = scsi_command_size(cmd->cmnd); > + how can cmd->cmd_len be zero here? SG_IO path sets up req->cmd_len properly for PC commands. > if (!req->data_len) > cmd->sc_data_direction = DMA_NONE; > else if (rq_data_dir(req) == WRITE) > cmd->sc_data_direction = DMA_TO_DEVICE; > else > cmd->sc_data_direction = DMA_FROM_DEVICE; > - > + > cmd->transfersize = req->data_len; > cmd->allowed = req->retries; > cmd->timeout_per_command = req->timeout; > diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h > index 1f74bcd..32742c4 100644 > --- a/include/scsi/scsi.h > +++ b/include/scsi/scsi.h > @@ -30,13 +30,6 @@ > #endif > > /* > - * SCSI command lengths > - */ > - > -extern const unsigned char scsi_command_size[8]; > -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] > - > -/* > * Special value for scanning to specify scanning or rescanning of all > * possible channels, (target) ids, or luns on a given shost. > */ > @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8]; > #define MODE_SENSE_10 0x5a > #define PERSISTENT_RESERVE_IN 0x5e > #define PERSISTENT_RESERVE_OUT 0x5f > +#define VARIABLE_LENGTH_CMD 0x7f > #define REPORT_LUNS 0xa0 > #define MAINTENANCE_IN 0xa3 > #define MOVE_MEDIUM 0xa5 > @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8]; > #define ATA_12 0xa1 /* 12-byte pass-thru */ > > /* > + * SCSI command lengths > + */ > + > +#define SCSI_MAX_VARLEN_CDB_SIZE 260 > + > +/* defined in T10 SCSI Primary Commands-2 (SPC2) */ > +struct scsi_varlen_cdb_hdr { > + u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */ > + u8 control; > + u8 misc[5]; > + u8 additional_cdb_length; /* total cdb length - 8 */ > + __be16 service_action; > + /* service specific data follows */ > +}; > + > +static inline unsigned > +scsi_varlen_cdb_length(const void *hdr) > +{ > + return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8; > +} > + > +extern const unsigned char scsi_command_size_tbl[8]; > +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] > + > +static inline unsigned > +scsi_command_size(const unsigned char *cmnd) > +{ > + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? > + scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]); > +} > + > +/* > * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft > * T10/1561-D Revision 4 Draft dated 7th November 2002. > */ > diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h > index dea73e5..f4dacb1 100644 > --- a/include/scsi/scsi_cmnd.h > +++ b/include/scsi/scsi_cmnd.h > @@ -78,7 +78,7 @@ struct scsi_cmnd { > int allowed; > int timeout_per_command; > > - unsigned char cmd_len; > + unsigned short cmd_len; > enum dma_data_direction sc_data_direction; > > /* These elements define the operation we are about to perform */ > diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h > index 4913286..31f1bfd 100644 > --- a/include/scsi/scsi_host.h > +++ b/include/scsi/scsi_host.h > @@ -573,13 +573,11 @@ struct Scsi_Host { > /* > * The maximum length of SCSI commands that this host can accept. > * Probably 12 for most host adapters, but could be 16 for others. > + * or 260 if the driver supports variable length cdbs. > * For drivers that don't set this field, a value of 12 is > - * assumed. I am leaving this as a number rather than a bit > - * because you never know what subsequent SCSI standards might do > - * (i.e. could there be a 20 byte or a 24-byte command a few years > - * down the road?). > + * assumed. > */ > - unsigned char max_cmd_len; > + unsigned short max_cmd_len; > > int this_id; > int can_queue; > -- > 1.5.3.3 > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs 2008-04-16 2:09 ` FUJITA Tomonori @ 2008-04-16 6:40 ` Boaz Harrosh 2008-04-16 6:49 ` [PATCH 2/3 ver2] " Boaz Harrosh 2008-04-17 4:01 ` [PATCH 2/3] " FUJITA Tomonori 0 siblings, 2 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-16 6:40 UTC (permalink / raw) To: FUJITA Tomonori Cc: James.Bottomley, linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven On Wed, Apr 16 2008 at 5:09 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > On Tue, 15 Apr 2008 15:34:47 +0300 > Boaz Harrosh <bharrosh@panasas.com> wrote: > >> Add support for variable-length, extended, and vendor specific >> CDBs to scsi-ml. It is now possible for initiators and ULD's >> to issue these types of commands. LLDs need not change much. >> All they need is to raise the .max_cmd_len to the longest command >> they support (see iscsi patch). >> >> - clean-up some code paths that did not expect commands to be >> larger than 16, and change cmd_len members' type to short as >> char is not enough. >> >> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> >> Signed-off-by: Benny Halevy <bhalevy@panasas.com> >> --- >> block/scsi_ioctl.c | 5 ++--- >> drivers/scsi/constants.c | 10 +++------- >> drivers/scsi/scsi.c | 22 +++++++++++----------- >> drivers/scsi/scsi_lib.c | 8 ++++++-- >> include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- >> include/scsi/scsi_cmnd.h | 2 +- >> include/scsi/scsi_host.h | 8 +++----- >> 7 files changed, 59 insertions(+), 36 deletions(-) >> >> diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c >> index a2c3a93..aaf07e4 100644 >> --- a/block/scsi_ioctl.c >> +++ b/block/scsi_ioctl.c >> @@ -33,13 +33,12 @@ >> #include <scsi/scsi_cmnd.h> >> >> /* Command group 3 is reserved and should never be used. */ >> -const unsigned char scsi_command_size[8] = >> +const unsigned char scsi_command_size_tbl[8] = >> { >> 6, 10, 10, 12, >> 16, 12, 10, 10 >> }; >> - >> -EXPORT_SYMBOL(scsi_command_size); >> +EXPORT_SYMBOL(scsi_command_size_tbl); >> >> #include <scsi/sg.h> >> >> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c >> index 403a7f2..9785d73 100644 >> --- a/drivers/scsi/constants.c >> +++ b/drivers/scsi/constants.c >> @@ -28,7 +28,6 @@ >> #define SERVICE_ACTION_OUT_12 0xa9 >> #define SERVICE_ACTION_IN_16 0x9e >> #define SERVICE_ACTION_OUT_16 0x9f >> -#define VARIABLE_LENGTH_CMD 0x7f >> >> >> >> @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) >> cdb0 = cdbp[0]; >> switch(cdb0) { >> case VARIABLE_LENGTH_CMD: >> - len = cdbp[7] + 8; >> + len = scsi_varlen_cdb_length(cdbp); >> if (len < 10) { >> printk("short variable length command, " >> "len=%d ext_len=%d", len, cdb_len); >> @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) >> cdb0 = cdbp[0]; >> switch(cdb0) { >> case VARIABLE_LENGTH_CMD: >> - len = cdbp[7] + 8; >> + len = scsi_varlen_cdb_length(cdbp); >> if (len < 10) { >> printk("short opcode=0x%x command, len=%d " >> "ext_len=%d", cdb0, len, cdb_len); >> @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) >> int k, len; >> >> print_opcode_name(cdb, 0); >> - if (VARIABLE_LENGTH_CMD == cdb[0]) >> - len = cdb[7] + 8; >> - else >> - len = COMMAND_SIZE(cdb[0]); >> + len = scsi_command_size(cdb); >> /* print out all bytes in cdb */ >> for (k = 0; k < len; ++k) >> printk(" %02x", cdb[k]); >> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c >> index f6980bd..3dabecb 100644 >> --- a/drivers/scsi/scsi.c >> +++ b/drivers/scsi/scsi.c >> @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); >> #define MIN_RESET_PERIOD (15*HZ) >> >> /* >> - * Macro to determine the size of SCSI command. This macro takes vendor >> - * unique commands into account. SCSI commands in groups 6 and 7 are >> - * vendor unique and we will depend upon the command length being >> - * supplied correctly in cmd_len. >> - */ >> -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ >> - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) >> - >> -/* >> * Note - the initial logging level can be set here to log events at boot time. >> * After the system is up, you may enable logging via the /proc interface. >> */ >> @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) >> unsigned long flags = 0; >> unsigned long timeout; >> int rtn = 0; >> + unsigned cmd_len; >> >> /* check if the device is still usable */ >> if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { >> @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) >> * Before we queue this command, check if the command >> * length exceeds what the host adapter can handle. >> */ >> - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { >> + cmd_len = cmd->cmd_len; >> + if (!cmd_len) { >> + BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD); >> + cmd_len = COMMAND_SIZE((cmd)->cmnd[0]); >> + } > > Hmm, how can cmd->cmd_len be zero here? > With FS_PC commands this is zero here. Because ULD prepare the command only after prep_fn. > >> + if (cmd_len > cmd->device->host->max_cmd_len) { >> SCSI_LOG_MLQUEUE(3, >> - printk("queuecommand : command too long.\n")); >> + printk("queuecommand : command too long. " >> + "cdb_size=%d host->max_cmd_len=%d\n", >> + cmd->cmd_len, cmd->device->host->max_cmd_len)); >> cmd->result = (DID_ABORT << 16); > > Why can't we just do: > > if (scsi_command_size(cmd->cmnd) > cmd->device->host->max_cmd_len) { > Because we can't. If ULD gave us length then we only use that, and we do not assume we know anything about the command. scsi_command_size() only knows about scsi commands and not all scsi commands at that, not all versions and dialects of scsi. The commit log of this patch sayes: "support for variable-length, extended, and vendor specific" This code here enables that. > >> scsi_done(cmd); >> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c >> index 325270b..e621505 100644 >> --- a/drivers/scsi/scsi_lib.c >> +++ b/drivers/scsi/scsi_lib.c >> @@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, >> >> req->cmd_len = COMMAND_SIZE(cmd[0]); >> memcpy(req->cmd, cmd, req->cmd_len); >> + > > Please don't put a new line at a place unrelated with this patch. > Ooops left over from the rebasing sorry. > >> req->sense = sense; >> req->sense_len = 0; >> req->retries = retries; >> @@ -445,7 +446,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) >> scsi_set_resid(cmd, 0); >> memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); >> if (cmd->cmd_len == 0) >> - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); >> + cmd->cmd_len = scsi_command_size(cmd->cmnd); >> } >> >> void scsi_device_unbusy(struct scsi_device *sdev) >> @@ -1130,13 +1131,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) >> } >> >> cmd->cmd_len = req->cmd_len; >> + if (!cmd->cmd_len) >> + cmd->cmd_len = scsi_command_size(cmd->cmnd); >> + > > how can cmd->cmd_len be zero here? SG_IO path sets up req->cmd_len > properly for PC commands. > It is either that or BUG_ON(), I would say that a simple thing like that I would let the Initiator get lazy if it wants to. > >> if (!req->data_len) >> cmd->sc_data_direction = DMA_NONE; >> else if (rq_data_dir(req) == WRITE) >> cmd->sc_data_direction = DMA_TO_DEVICE; >> else >> cmd->sc_data_direction = DMA_FROM_DEVICE; >> - >> + >> cmd->transfersize = req->data_len; >> cmd->allowed = req->retries; >> cmd->timeout_per_command = req->timeout; >> diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h >> index 1f74bcd..32742c4 100644 >> --- a/include/scsi/scsi.h >> +++ b/include/scsi/scsi.h >> @@ -30,13 +30,6 @@ >> #endif >> >> /* >> - * SCSI command lengths >> - */ >> - >> -extern const unsigned char scsi_command_size[8]; >> -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] >> - >> -/* >> * Special value for scanning to specify scanning or rescanning of all >> * possible channels, (target) ids, or luns on a given shost. >> */ >> @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8]; >> #define MODE_SENSE_10 0x5a >> #define PERSISTENT_RESERVE_IN 0x5e >> #define PERSISTENT_RESERVE_OUT 0x5f >> +#define VARIABLE_LENGTH_CMD 0x7f >> #define REPORT_LUNS 0xa0 >> #define MAINTENANCE_IN 0xa3 >> #define MOVE_MEDIUM 0xa5 >> @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8]; >> #define ATA_12 0xa1 /* 12-byte pass-thru */ >> >> /* >> + * SCSI command lengths >> + */ >> + >> +#define SCSI_MAX_VARLEN_CDB_SIZE 260 >> + >> +/* defined in T10 SCSI Primary Commands-2 (SPC2) */ >> +struct scsi_varlen_cdb_hdr { >> + u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */ >> + u8 control; >> + u8 misc[5]; >> + u8 additional_cdb_length; /* total cdb length - 8 */ >> + __be16 service_action; >> + /* service specific data follows */ >> +}; >> + >> +static inline unsigned >> +scsi_varlen_cdb_length(const void *hdr) >> +{ >> + return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8; >> +} >> + >> +extern const unsigned char scsi_command_size_tbl[8]; >> +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] >> + >> +static inline unsigned >> +scsi_command_size(const unsigned char *cmnd) >> +{ >> + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? >> + scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]); >> +} >> + >> +/* >> * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft >> * T10/1561-D Revision 4 Draft dated 7th November 2002. >> */ >> diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h >> index dea73e5..f4dacb1 100644 >> --- a/include/scsi/scsi_cmnd.h >> +++ b/include/scsi/scsi_cmnd.h >> @@ -78,7 +78,7 @@ struct scsi_cmnd { >> int allowed; >> int timeout_per_command; >> >> - unsigned char cmd_len; >> + unsigned short cmd_len; >> enum dma_data_direction sc_data_direction; >> >> /* These elements define the operation we are about to perform */ >> diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h >> index 4913286..31f1bfd 100644 >> --- a/include/scsi/scsi_host.h >> +++ b/include/scsi/scsi_host.h >> @@ -573,13 +573,11 @@ struct Scsi_Host { >> /* >> * The maximum length of SCSI commands that this host can accept. >> * Probably 12 for most host adapters, but could be 16 for others. >> + * or 260 if the driver supports variable length cdbs. >> * For drivers that don't set this field, a value of 12 is >> - * assumed. I am leaving this as a number rather than a bit >> - * because you never know what subsequent SCSI standards might do >> - * (i.e. could there be a 20 byte or a 24-byte command a few years >> - * down the road?). >> + * assumed. >> */ >> - unsigned char max_cmd_len; >> + unsigned short max_cmd_len; >> >> int this_id; >> int can_queue; >> -- >> 1.5.3.3 >> >> >> -- As a reply to this mail I'll send a patch without the extra space. Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 2/3 ver2] scsi: varlen extended and vendor-specific cdbs 2008-04-16 6:40 ` Boaz Harrosh @ 2008-04-16 6:49 ` Boaz Harrosh 2008-04-17 4:01 ` [PATCH 2/3] " FUJITA Tomonori 1 sibling, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-16 6:49 UTC (permalink / raw) To: FUJITA Tomonori Cc: James.Bottomley, linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven Add support for variable-length, extended, and vendor specific CDBs to scsi-ml. It is now possible for initiators and ULD's to issue these types of commands. LLDs need not change much. All they need is to raise the .max_cmd_len to the longest command they support (see iscsi patch). - clean-up some code paths that did not expect commands to be larger than 16, and change cmd_len members' type to short as char is not enough. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> --- block/scsi_ioctl.c | 5 ++--- drivers/scsi/constants.c | 10 +++------- drivers/scsi/scsi.c | 22 +++++++++++----------- drivers/scsi/scsi_lib.c | 8 ++++++-- include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- include/scsi/scsi_cmnd.h | 2 +- include/scsi/scsi_host.h | 8 +++----- 7 files changed, 59 insertions(+), 36 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a2c3a93..aaf07e4 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -33,13 +33,12 @@ #include <scsi/scsi_cmnd.h> /* Command group 3 is reserved and should never be used. */ -const unsigned char scsi_command_size[8] = +const unsigned char scsi_command_size_tbl[8] = { 6, 10, 10, 12, 16, 12, 10, 10 }; - -EXPORT_SYMBOL(scsi_command_size); +EXPORT_SYMBOL(scsi_command_size_tbl); #include <scsi/sg.h> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 403a7f2..9785d73 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -28,7 +28,6 @@ #define SERVICE_ACTION_OUT_12 0xa9 #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f -#define VARIABLE_LENGTH_CMD 0x7f @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short variable length command, " "len=%d ext_len=%d", len, cdb_len); @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short opcode=0x%x command, len=%d " "ext_len=%d", cdb0, len, cdb_len); @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) int k, len; print_opcode_name(cdb, 0); - if (VARIABLE_LENGTH_CMD == cdb[0]) - len = cdb[7] + 8; - else - len = COMMAND_SIZE(cdb[0]); + len = scsi_command_size(cdb); /* print out all bytes in cdb */ for (k = 0; k < len; ++k) printk(" %02x", cdb[k]); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index f6980bd..3dabecb 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); #define MIN_RESET_PERIOD (15*HZ) /* - * Macro to determine the size of SCSI command. This macro takes vendor - * unique commands into account. SCSI commands in groups 6 and 7 are - * vendor unique and we will depend upon the command length being - * supplied correctly in cmd_len. - */ -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) - -/* * Note - the initial logging level can be set here to log events at boot time. * After the system is up, you may enable logging via the /proc interface. */ @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) unsigned long flags = 0; unsigned long timeout; int rtn = 0; + unsigned cmd_len; /* check if the device is still usable */ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * Before we queue this command, check if the command * length exceeds what the host adapter can handle. */ - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { + cmd_len = cmd->cmd_len; + if (!cmd_len) { + BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD); + cmd_len = COMMAND_SIZE((cmd)->cmnd[0]); + } + + if (cmd_len > cmd->device->host->max_cmd_len) { SCSI_LOG_MLQUEUE(3, - printk("queuecommand : command too long.\n")); + printk("queuecommand : command too long. " + "cdb_size=%d host->max_cmd_len=%d\n", + cmd->cmd_len, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT << 16); scsi_done(cmd); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 325270b..e621505 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -445,7 +445,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) scsi_set_resid(cmd, 0); memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); if (cmd->cmd_len == 0) - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); + cmd->cmd_len = scsi_command_size(cmd->cmnd); } void scsi_device_unbusy(struct scsi_device *sdev) @@ -1130,13 +1130,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) } cmd->cmd_len = req->cmd_len; + if (!cmd->cmd_len) + cmd->cmd_len = scsi_command_size(cmd->cmnd); + if (!req->data_len) cmd->sc_data_direction = DMA_NONE; else if (rq_data_dir(req) == WRITE) cmd->sc_data_direction = DMA_TO_DEVICE; else cmd->sc_data_direction = DMA_FROM_DEVICE; - + cmd->transfersize = req->data_len; cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 1f74bcd..32742c4 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -30,13 +30,6 @@ #endif /* - * SCSI command lengths - */ - -extern const unsigned char scsi_command_size[8]; -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] - -/* * Special value for scanning to specify scanning or rescanning of all * possible channels, (target) ids, or luns on a given shost. */ @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8]; #define MODE_SENSE_10 0x5a #define PERSISTENT_RESERVE_IN 0x5e #define PERSISTENT_RESERVE_OUT 0x5f +#define VARIABLE_LENGTH_CMD 0x7f #define REPORT_LUNS 0xa0 #define MAINTENANCE_IN 0xa3 #define MOVE_MEDIUM 0xa5 @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8]; #define ATA_12 0xa1 /* 12-byte pass-thru */ /* + * SCSI command lengths + */ + +#define SCSI_MAX_VARLEN_CDB_SIZE 260 + +/* defined in T10 SCSI Primary Commands-2 (SPC2) */ +struct scsi_varlen_cdb_hdr { + u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */ + u8 control; + u8 misc[5]; + u8 additional_cdb_length; /* total cdb length - 8 */ + __be16 service_action; + /* service specific data follows */ +}; + +static inline unsigned +scsi_varlen_cdb_length(const void *hdr) +{ + return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8; +} + +extern const unsigned char scsi_command_size_tbl[8]; +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] + +static inline unsigned +scsi_command_size(const unsigned char *cmnd) +{ + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? + scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]); +} + +/* * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft * T10/1561-D Revision 4 Draft dated 7th November 2002. */ diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index dea73e5..f4dacb1 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -78,7 +78,7 @@ struct scsi_cmnd { int allowed; int timeout_per_command; - unsigned char cmd_len; + unsigned short cmd_len; enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 4913286..31f1bfd 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -573,13 +573,11 @@ struct Scsi_Host { /* * The maximum length of SCSI commands that this host can accept. * Probably 12 for most host adapters, but could be 16 for others. + * or 260 if the driver supports variable length cdbs. * For drivers that don't set this field, a value of 12 is - * assumed. I am leaving this as a number rather than a bit - * because you never know what subsequent SCSI standards might do - * (i.e. could there be a 20 byte or a 24-byte command a few years - * down the road?). + * assumed. */ - unsigned char max_cmd_len; + unsigned short max_cmd_len; int this_id; int can_queue; -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs 2008-04-16 6:40 ` Boaz Harrosh 2008-04-16 6:49 ` [PATCH 2/3 ver2] " Boaz Harrosh @ 2008-04-17 4:01 ` FUJITA Tomonori 2008-04-17 12:25 ` [PATCH 2/3 ver3] " Boaz Harrosh 1 sibling, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-17 4:01 UTC (permalink / raw) To: bharrosh Cc: fujita.tomonori, James.Bottomley, linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven On Wed, 16 Apr 2008 09:40:17 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > On Wed, Apr 16 2008 at 5:09 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > > On Tue, 15 Apr 2008 15:34:47 +0300 > > Boaz Harrosh <bharrosh@panasas.com> wrote: > > > >> Add support for variable-length, extended, and vendor specific > >> CDBs to scsi-ml. It is now possible for initiators and ULD's > >> to issue these types of commands. LLDs need not change much. > >> All they need is to raise the .max_cmd_len to the longest command > >> they support (see iscsi patch). > >> > >> - clean-up some code paths that did not expect commands to be > >> larger than 16, and change cmd_len members' type to short as > >> char is not enough. > >> > >> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > >> Signed-off-by: Benny Halevy <bhalevy@panasas.com> > >> --- > >> block/scsi_ioctl.c | 5 ++--- > >> drivers/scsi/constants.c | 10 +++------- > >> drivers/scsi/scsi.c | 22 +++++++++++----------- > >> drivers/scsi/scsi_lib.c | 8 ++++++-- > >> include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- > >> include/scsi/scsi_cmnd.h | 2 +- > >> include/scsi/scsi_host.h | 8 +++----- > >> 7 files changed, 59 insertions(+), 36 deletions(-) > >> > >> diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c > >> index a2c3a93..aaf07e4 100644 > >> --- a/block/scsi_ioctl.c > >> +++ b/block/scsi_ioctl.c > >> @@ -33,13 +33,12 @@ > >> #include <scsi/scsi_cmnd.h> > >> > >> /* Command group 3 is reserved and should never be used. */ > >> -const unsigned char scsi_command_size[8] = > >> +const unsigned char scsi_command_size_tbl[8] = > >> { > >> 6, 10, 10, 12, > >> 16, 12, 10, 10 > >> }; > >> - > >> -EXPORT_SYMBOL(scsi_command_size); > >> +EXPORT_SYMBOL(scsi_command_size_tbl); > >> > >> #include <scsi/sg.h> > >> > >> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c > >> index 403a7f2..9785d73 100644 > >> --- a/drivers/scsi/constants.c > >> +++ b/drivers/scsi/constants.c > >> @@ -28,7 +28,6 @@ > >> #define SERVICE_ACTION_OUT_12 0xa9 > >> #define SERVICE_ACTION_IN_16 0x9e > >> #define SERVICE_ACTION_OUT_16 0x9f > >> -#define VARIABLE_LENGTH_CMD 0x7f > >> > >> > >> > >> @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) > >> cdb0 = cdbp[0]; > >> switch(cdb0) { > >> case VARIABLE_LENGTH_CMD: > >> - len = cdbp[7] + 8; > >> + len = scsi_varlen_cdb_length(cdbp); > >> if (len < 10) { > >> printk("short variable length command, " > >> "len=%d ext_len=%d", len, cdb_len); > >> @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) > >> cdb0 = cdbp[0]; > >> switch(cdb0) { > >> case VARIABLE_LENGTH_CMD: > >> - len = cdbp[7] + 8; > >> + len = scsi_varlen_cdb_length(cdbp); > >> if (len < 10) { > >> printk("short opcode=0x%x command, len=%d " > >> "ext_len=%d", cdb0, len, cdb_len); > >> @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) > >> int k, len; > >> > >> print_opcode_name(cdb, 0); > >> - if (VARIABLE_LENGTH_CMD == cdb[0]) > >> - len = cdb[7] + 8; > >> - else > >> - len = COMMAND_SIZE(cdb[0]); > >> + len = scsi_command_size(cdb); > >> /* print out all bytes in cdb */ > >> for (k = 0; k < len; ++k) > >> printk(" %02x", cdb[k]); > >> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c > >> index f6980bd..3dabecb 100644 > >> --- a/drivers/scsi/scsi.c > >> +++ b/drivers/scsi/scsi.c > >> @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); > >> #define MIN_RESET_PERIOD (15*HZ) > >> > >> /* > >> - * Macro to determine the size of SCSI command. This macro takes vendor > >> - * unique commands into account. SCSI commands in groups 6 and 7 are > >> - * vendor unique and we will depend upon the command length being > >> - * supplied correctly in cmd_len. > >> - */ > >> -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ > >> - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) > >> - > >> -/* > >> * Note - the initial logging level can be set here to log events at boot time. > >> * After the system is up, you may enable logging via the /proc interface. > >> */ > >> @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) > >> unsigned long flags = 0; > >> unsigned long timeout; > >> int rtn = 0; > >> + unsigned cmd_len; > >> > >> /* check if the device is still usable */ > >> if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { > >> @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) > >> * Before we queue this command, check if the command > >> * length exceeds what the host adapter can handle. > >> */ > >> - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { > >> + cmd_len = cmd->cmd_len; > >> + if (!cmd_len) { > >> + BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD); > >> + cmd_len = COMMAND_SIZE((cmd)->cmnd[0]); > >> + } > > > > Hmm, how can cmd->cmd_len be zero here? > > > > With FS_PC commands this is zero here. Because ULD prepare the command > only after prep_fn. I don't think so. See what scsi_init_cmd_errh does. It's called before scsi_dispatch_cmd. > > > >> + if (cmd_len > cmd->device->host->max_cmd_len) { > >> SCSI_LOG_MLQUEUE(3, > >> - printk("queuecommand : command too long.\n")); > >> + printk("queuecommand : command too long. " > >> + "cdb_size=%d host->max_cmd_len=%d\n", > >> + cmd->cmd_len, cmd->device->host->max_cmd_len)); > >> cmd->result = (DID_ABORT << 16); > > > > Why can't we just do: > > > > if (scsi_command_size(cmd->cmnd) > cmd->device->host->max_cmd_len) { > > > > Because we can't. If ULD gave us length then we only use that, and we do > not assume we know anything about the command. scsi_command_size() only > knows about scsi commands and not all scsi commands at that, not all > versions and dialects of scsi. The commit log of this patch sayes: > "support for variable-length, extended, and vendor specific" > This code here enables that. Again, look at scsi_init_cmd_errh. > > > >> scsi_done(cmd); > >> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c > >> index 325270b..e621505 100644 > >> --- a/drivers/scsi/scsi_lib.c > >> +++ b/drivers/scsi/scsi_lib.c > >> @@ -195,6 +195,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, > >> > >> req->cmd_len = COMMAND_SIZE(cmd[0]); > >> memcpy(req->cmd, cmd, req->cmd_len); > >> + > > > > Please don't put a new line at a place unrelated with this patch. > > > Ooops left over from the rebasing sorry. > > > >> req->sense = sense; > >> req->sense_len = 0; > >> req->retries = retries; > >> @@ -445,7 +446,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) > >> scsi_set_resid(cmd, 0); > >> memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); > >> if (cmd->cmd_len == 0) > >> - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); > >> + cmd->cmd_len = scsi_command_size(cmd->cmnd); > >> } > >> > >> void scsi_device_unbusy(struct scsi_device *sdev) > >> @@ -1130,13 +1131,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) > >> } > >> > >> cmd->cmd_len = req->cmd_len; > >> + if (!cmd->cmd_len) > >> + cmd->cmd_len = scsi_command_size(cmd->cmnd); > >> + > > > > how can cmd->cmd_len be zero here? SG_IO path sets up req->cmd_len > > properly for PC commands. > > > > It is either that or BUG_ON(), I would say that a simple thing like that > I would let the Initiator get lazy if it wants to. Please do only what the patch describes. This patch is expected to add large command support. The above code is not related with that at all. I don't think we need the above code. But if you still think we need the above code, send a separate patch. > > > >> if (!req->data_len) > >> cmd->sc_data_direction = DMA_NONE; > >> else if (rq_data_dir(req) == WRITE) > >> cmd->sc_data_direction = DMA_TO_DEVICE; > >> else > >> cmd->sc_data_direction = DMA_FROM_DEVICE; > >> - > >> + > >> cmd->transfersize = req->data_len; > >> cmd->allowed = req->retries; > >> cmd->timeout_per_command = req->timeout; > >> diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h > >> index 1f74bcd..32742c4 100644 > >> --- a/include/scsi/scsi.h > >> +++ b/include/scsi/scsi.h > >> @@ -30,13 +30,6 @@ > >> #endif > >> > >> /* > >> - * SCSI command lengths > >> - */ > >> - > >> -extern const unsigned char scsi_command_size[8]; > >> -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] > >> - > >> -/* > >> * Special value for scanning to specify scanning or rescanning of all > >> * possible channels, (target) ids, or luns on a given shost. > >> */ > >> @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8]; > >> #define MODE_SENSE_10 0x5a > >> #define PERSISTENT_RESERVE_IN 0x5e > >> #define PERSISTENT_RESERVE_OUT 0x5f > >> +#define VARIABLE_LENGTH_CMD 0x7f > >> #define REPORT_LUNS 0xa0 > >> #define MAINTENANCE_IN 0xa3 > >> #define MOVE_MEDIUM 0xa5 > >> @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8]; > >> #define ATA_12 0xa1 /* 12-byte pass-thru */ > >> > >> /* > >> + * SCSI command lengths > >> + */ > >> + > >> +#define SCSI_MAX_VARLEN_CDB_SIZE 260 > >> + > >> +/* defined in T10 SCSI Primary Commands-2 (SPC2) */ > >> +struct scsi_varlen_cdb_hdr { > >> + u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */ > >> + u8 control; > >> + u8 misc[5]; > >> + u8 additional_cdb_length; /* total cdb length - 8 */ > >> + __be16 service_action; > >> + /* service specific data follows */ > >> +}; > >> + > >> +static inline unsigned > >> +scsi_varlen_cdb_length(const void *hdr) > >> +{ > >> + return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8; > >> +} > >> + > >> +extern const unsigned char scsi_command_size_tbl[8]; > >> +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] > >> + > >> +static inline unsigned > >> +scsi_command_size(const unsigned char *cmnd) > >> +{ > >> + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? > >> + scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]); > >> +} > >> + > >> +/* > >> * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft > >> * T10/1561-D Revision 4 Draft dated 7th November 2002. > >> */ > >> diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h > >> index dea73e5..f4dacb1 100644 > >> --- a/include/scsi/scsi_cmnd.h > >> +++ b/include/scsi/scsi_cmnd.h > >> @@ -78,7 +78,7 @@ struct scsi_cmnd { > >> int allowed; > >> int timeout_per_command; > >> > >> - unsigned char cmd_len; > >> + unsigned short cmd_len; > >> enum dma_data_direction sc_data_direction; > >> > >> /* These elements define the operation we are about to perform */ > >> diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h > >> index 4913286..31f1bfd 100644 > >> --- a/include/scsi/scsi_host.h > >> +++ b/include/scsi/scsi_host.h > >> @@ -573,13 +573,11 @@ struct Scsi_Host { > >> /* > >> * The maximum length of SCSI commands that this host can accept. > >> * Probably 12 for most host adapters, but could be 16 for others. > >> + * or 260 if the driver supports variable length cdbs. > >> * For drivers that don't set this field, a value of 12 is > >> - * assumed. I am leaving this as a number rather than a bit > >> - * because you never know what subsequent SCSI standards might do > >> - * (i.e. could there be a 20 byte or a 24-byte command a few years > >> - * down the road?). > >> + * assumed. > >> */ > >> - unsigned char max_cmd_len; > >> + unsigned short max_cmd_len; > >> > >> int this_id; > >> int can_queue; > >> -- > >> 1.5.3.3 > >> > >> > >> -- > > As a reply to this mail I'll send a patch without the extra space. > > Boaz > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs 2008-04-17 4:01 ` [PATCH 2/3] " FUJITA Tomonori @ 2008-04-17 12:25 ` Boaz Harrosh 2008-04-17 12:49 ` Boaz Harrosh 2008-04-17 13:04 ` FUJITA Tomonori 0 siblings, 2 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-17 12:25 UTC (permalink / raw) To: FUJITA Tomonori, James.Bottomley Cc: linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven Add support for variable-length, extended, and vendor specific CDBs to scsi-ml. It is now possible for initiators and ULD's to issue these types of commands. LLDs need not change much. All they need is to raise the .max_cmd_len to the longest command they support (see iscsi patch). - clean-up some code paths that did not expect commands to be larger than 16, and change cmd_len members' type to short as char is not enough. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> --- block/scsi_ioctl.c | 5 ++--- drivers/scsi/constants.c | 10 +++------- drivers/scsi/scsi.c | 15 ++++----------- drivers/scsi/scsi_lib.c | 2 +- include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- include/scsi/scsi_cmnd.h | 2 +- include/scsi/scsi_host.h | 8 +++----- 7 files changed, 47 insertions(+), 35 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a2c3a93..aaf07e4 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -33,13 +33,12 @@ #include <scsi/scsi_cmnd.h> /* Command group 3 is reserved and should never be used. */ -const unsigned char scsi_command_size[8] = +const unsigned char scsi_command_size_tbl[8] = { 6, 10, 10, 12, 16, 12, 10, 10 }; - -EXPORT_SYMBOL(scsi_command_size); +EXPORT_SYMBOL(scsi_command_size_tbl); #include <scsi/sg.h> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 403a7f2..9785d73 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -28,7 +28,6 @@ #define SERVICE_ACTION_OUT_12 0xa9 #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f -#define VARIABLE_LENGTH_CMD 0x7f @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short variable length command, " "len=%d ext_len=%d", len, cdb_len); @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short opcode=0x%x command, len=%d " "ext_len=%d", cdb0, len, cdb_len); @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) int k, len; print_opcode_name(cdb, 0); - if (VARIABLE_LENGTH_CMD == cdb[0]) - len = cdb[7] + 8; - else - len = COMMAND_SIZE(cdb[0]); + len = scsi_command_size(cdb); /* print out all bytes in cdb */ for (k = 0; k < len; ++k) printk(" %02x", cdb[k]); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index f6980bd..dd9dd65 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); #define MIN_RESET_PERIOD (15*HZ) /* - * Macro to determine the size of SCSI command. This macro takes vendor - * unique commands into account. SCSI commands in groups 6 and 7 are - * vendor unique and we will depend upon the command length being - * supplied correctly in cmd_len. - */ -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) - -/* * Note - the initial logging level can be set here to log events at boot time. * After the system is up, you may enable logging via the /proc interface. */ @@ -701,9 +692,11 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * Before we queue this command, check if the command * length exceeds what the host adapter can handle. */ - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { + if (cmd->cmd_len > cmd->device->host->max_cmd_len) { SCSI_LOG_MLQUEUE(3, - printk("queuecommand : command too long.\n")); + printk("queuecommand : command too long. " + "cdb_size=%d host->max_cmd_len=%d\n", + cmd->cmd_len, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT << 16); scsi_done(cmd); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 325270b..ba7e8ad 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -445,7 +445,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) scsi_set_resid(cmd, 0); memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); if (cmd->cmd_len == 0) - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); + cmd->cmd_len = scsi_command_size(cmd->cmnd); } void scsi_device_unbusy(struct scsi_device *sdev) diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 1f74bcd..32742c4 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -30,13 +30,6 @@ #endif /* - * SCSI command lengths - */ - -extern const unsigned char scsi_command_size[8]; -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] - -/* * Special value for scanning to specify scanning or rescanning of all * possible channels, (target) ids, or luns on a given shost. */ @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8]; #define MODE_SENSE_10 0x5a #define PERSISTENT_RESERVE_IN 0x5e #define PERSISTENT_RESERVE_OUT 0x5f +#define VARIABLE_LENGTH_CMD 0x7f #define REPORT_LUNS 0xa0 #define MAINTENANCE_IN 0xa3 #define MOVE_MEDIUM 0xa5 @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8]; #define ATA_12 0xa1 /* 12-byte pass-thru */ /* + * SCSI command lengths + */ + +#define SCSI_MAX_VARLEN_CDB_SIZE 260 + +/* defined in T10 SCSI Primary Commands-2 (SPC2) */ +struct scsi_varlen_cdb_hdr { + u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */ + u8 control; + u8 misc[5]; + u8 additional_cdb_length; /* total cdb length - 8 */ + __be16 service_action; + /* service specific data follows */ +}; + +static inline unsigned +scsi_varlen_cdb_length(const void *hdr) +{ + return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8; +} + +extern const unsigned char scsi_command_size_tbl[8]; +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] + +static inline unsigned +scsi_command_size(const unsigned char *cmnd) +{ + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? + scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]); +} + +/* * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft * T10/1561-D Revision 4 Draft dated 7th November 2002. */ diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index dea73e5..f4dacb1 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -78,7 +78,7 @@ struct scsi_cmnd { int allowed; int timeout_per_command; - unsigned char cmd_len; + unsigned short cmd_len; enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 4913286..31f1bfd 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -573,13 +573,11 @@ struct Scsi_Host { /* * The maximum length of SCSI commands that this host can accept. * Probably 12 for most host adapters, but could be 16 for others. + * or 260 if the driver supports variable length cdbs. * For drivers that don't set this field, a value of 12 is - * assumed. I am leaving this as a number rather than a bit - * because you never know what subsequent SCSI standards might do - * (i.e. could there be a 20 byte or a 24-byte command a few years - * down the road?). + * assumed. */ - unsigned char max_cmd_len; + unsigned short max_cmd_len; int this_id; int can_queue; -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs 2008-04-17 12:25 ` [PATCH 2/3 ver3] " Boaz Harrosh @ 2008-04-17 12:49 ` Boaz Harrosh 2008-04-17 13:04 ` FUJITA Tomonori 1 sibling, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-17 12:49 UTC (permalink / raw) To: FUJITA Tomonori, James.Bottomley Cc: linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven On Thu, Apr 17 2008 at 15:25 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: > Add support for variable-length, extended, and vendor specific > CDBs to scsi-ml. It is now possible for initiators and ULD's > to issue these types of commands. LLDs need not change much. > All they need is to raise the .max_cmd_len to the longest command > they support (see iscsi patch). > > - clean-up some code paths that did not expect commands to be > larger than 16, and change cmd_len members' type to short as > char is not enough. > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > Signed-off-by: Benny Halevy <bhalevy@panasas.com> > --- > block/scsi_ioctl.c | 5 ++--- > drivers/scsi/constants.c | 10 +++------- > drivers/scsi/scsi.c | 15 ++++----------- > drivers/scsi/scsi_lib.c | 2 +- > include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- > include/scsi/scsi_cmnd.h | 2 +- > include/scsi/scsi_host.h | 8 +++----- > 7 files changed, 47 insertions(+), 35 deletions(-) > > diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c > index a2c3a93..aaf07e4 100644 > --- a/block/scsi_ioctl.c > +++ b/block/scsi_ioctl.c > @@ -33,13 +33,12 @@ > #include <scsi/scsi_cmnd.h> > > /* Command group 3 is reserved and should never be used. */ > -const unsigned char scsi_command_size[8] = > +const unsigned char scsi_command_size_tbl[8] = > { > 6, 10, 10, 12, > 16, 12, 10, 10 > }; > - > -EXPORT_SYMBOL(scsi_command_size); > +EXPORT_SYMBOL(scsi_command_size_tbl); > > #include <scsi/sg.h> > > diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c > index 403a7f2..9785d73 100644 > --- a/drivers/scsi/constants.c > +++ b/drivers/scsi/constants.c > @@ -28,7 +28,6 @@ > #define SERVICE_ACTION_OUT_12 0xa9 > #define SERVICE_ACTION_IN_16 0x9e > #define SERVICE_ACTION_OUT_16 0x9f > -#define VARIABLE_LENGTH_CMD 0x7f > > > > @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) > cdb0 = cdbp[0]; > switch(cdb0) { > case VARIABLE_LENGTH_CMD: > - len = cdbp[7] + 8; > + len = scsi_varlen_cdb_length(cdbp); > if (len < 10) { > printk("short variable length command, " > "len=%d ext_len=%d", len, cdb_len); > @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) > cdb0 = cdbp[0]; > switch(cdb0) { > case VARIABLE_LENGTH_CMD: > - len = cdbp[7] + 8; > + len = scsi_varlen_cdb_length(cdbp); > if (len < 10) { > printk("short opcode=0x%x command, len=%d " > "ext_len=%d", cdb0, len, cdb_len); > @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) > int k, len; > > print_opcode_name(cdb, 0); > - if (VARIABLE_LENGTH_CMD == cdb[0]) > - len = cdb[7] + 8; > - else > - len = COMMAND_SIZE(cdb[0]); > + len = scsi_command_size(cdb); > /* print out all bytes in cdb */ > for (k = 0; k < len; ++k) > printk(" %02x", cdb[k]); > diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c > index f6980bd..dd9dd65 100644 > --- a/drivers/scsi/scsi.c > +++ b/drivers/scsi/scsi.c > @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); > #define MIN_RESET_PERIOD (15*HZ) > > /* > - * Macro to determine the size of SCSI command. This macro takes vendor > - * unique commands into account. SCSI commands in groups 6 and 7 are > - * vendor unique and we will depend upon the command length being > - * supplied correctly in cmd_len. > - */ > -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ > - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) > - > -/* > * Note - the initial logging level can be set here to log events at boot time. > * After the system is up, you may enable logging via the /proc interface. > */ > @@ -701,9 +692,11 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) > * Before we queue this command, check if the command > * length exceeds what the host adapter can handle. > */ > - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { > + if (cmd->cmd_len > cmd->device->host->max_cmd_len) { > SCSI_LOG_MLQUEUE(3, > - printk("queuecommand : command too long.\n")); > + printk("queuecommand : command too long. " > + "cdb_size=%d host->max_cmd_len=%d\n", > + cmd->cmd_len, cmd->device->host->max_cmd_len)); > cmd->result = (DID_ABORT << 16); > > scsi_done(cmd); > diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c > index 325270b..ba7e8ad 100644 > --- a/drivers/scsi/scsi_lib.c > +++ b/drivers/scsi/scsi_lib.c > @@ -445,7 +445,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) > scsi_set_resid(cmd, 0); > memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); > if (cmd->cmd_len == 0) > - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); > + cmd->cmd_len = scsi_command_size(cmd->cmnd); > } > > void scsi_device_unbusy(struct scsi_device *sdev) > diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h > index 1f74bcd..32742c4 100644 > --- a/include/scsi/scsi.h > +++ b/include/scsi/scsi.h > @@ -30,13 +30,6 @@ > #endif > > /* > - * SCSI command lengths > - */ > - > -extern const unsigned char scsi_command_size[8]; > -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] > - > -/* > * Special value for scanning to specify scanning or rescanning of all > * possible channels, (target) ids, or luns on a given shost. > */ > @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8]; > #define MODE_SENSE_10 0x5a > #define PERSISTENT_RESERVE_IN 0x5e > #define PERSISTENT_RESERVE_OUT 0x5f > +#define VARIABLE_LENGTH_CMD 0x7f > #define REPORT_LUNS 0xa0 > #define MAINTENANCE_IN 0xa3 > #define MOVE_MEDIUM 0xa5 > @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8]; > #define ATA_12 0xa1 /* 12-byte pass-thru */ > > /* > + * SCSI command lengths > + */ > + > +#define SCSI_MAX_VARLEN_CDB_SIZE 260 > + > +/* defined in T10 SCSI Primary Commands-2 (SPC2) */ > +struct scsi_varlen_cdb_hdr { > + u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */ > + u8 control; > + u8 misc[5]; > + u8 additional_cdb_length; /* total cdb length - 8 */ > + __be16 service_action; > + /* service specific data follows */ > +}; > + > +static inline unsigned > +scsi_varlen_cdb_length(const void *hdr) > +{ > + return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8; > +} > + > +extern const unsigned char scsi_command_size_tbl[8]; > +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] > + > +static inline unsigned > +scsi_command_size(const unsigned char *cmnd) > +{ > + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? > + scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]); > +} > + > +/* > * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft > * T10/1561-D Revision 4 Draft dated 7th November 2002. > */ > diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h > index dea73e5..f4dacb1 100644 > --- a/include/scsi/scsi_cmnd.h > +++ b/include/scsi/scsi_cmnd.h > @@ -78,7 +78,7 @@ struct scsi_cmnd { > int allowed; > int timeout_per_command; > > - unsigned char cmd_len; > + unsigned short cmd_len; > enum dma_data_direction sc_data_direction; > > /* These elements define the operation we are about to perform */ > diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h > index 4913286..31f1bfd 100644 > --- a/include/scsi/scsi_host.h > +++ b/include/scsi/scsi_host.h > @@ -573,13 +573,11 @@ struct Scsi_Host { > /* > * The maximum length of SCSI commands that this host can accept. > * Probably 12 for most host adapters, but could be 16 for others. > + * or 260 if the driver supports variable length cdbs. > * For drivers that don't set this field, a value of 12 is > - * assumed. I am leaving this as a number rather than a bit > - * because you never know what subsequent SCSI standards might do > - * (i.e. could there be a 20 byte or a 24-byte command a few years > - * down the road?). > + * assumed. > */ > - unsigned char max_cmd_len; > + unsigned short max_cmd_len; > > int this_id; > int can_queue; I have tested above patch both, booting and general usage of sata disks and cdrom on an x86_64 work station, and also my OSD varlen setup. And it works, so Tomo was right, we do not need the extra checks, the one at scsi_init_cmd_errh() takes care of all the cases. When I developed this, (20 month ago) I used to hit a BUG_ON(!cmd->cmd_len); in scsi_dispatch_cmd(). But I have just tested above patch (+ the BUG_ON) and it does not trigger. Thanks Tomo Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs 2008-04-17 12:25 ` [PATCH 2/3 ver3] " Boaz Harrosh 2008-04-17 12:49 ` Boaz Harrosh @ 2008-04-17 13:04 ` FUJITA Tomonori 2008-04-17 13:29 ` Boaz Harrosh 1 sibling, 1 reply; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-17 13:04 UTC (permalink / raw) To: bharrosh Cc: fujita.tomonori, James.Bottomley, linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven On Thu, 17 Apr 2008 15:25:23 +0300 Boaz Harrosh <bharrosh@panasas.com> wrote: > > Add support for variable-length, extended, and vendor specific > CDBs to scsi-ml. It is now possible for initiators and ULD's > to issue these types of commands. LLDs need not change much. > All they need is to raise the .max_cmd_len to the longest command > they support (see iscsi patch). > > - clean-up some code paths that did not expect commands to be > larger than 16, and change cmd_len members' type to short as > char is not enough. > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > Signed-off-by: Benny Halevy <bhalevy@panasas.com> > --- > block/scsi_ioctl.c | 5 ++--- > drivers/scsi/constants.c | 10 +++------- > drivers/scsi/scsi.c | 15 ++++----------- > drivers/scsi/scsi_lib.c | 2 +- > include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- > include/scsi/scsi_cmnd.h | 2 +- > include/scsi/scsi_host.h | 8 +++----- > 7 files changed, 47 insertions(+), 35 deletions(-) looks fine to me though I've not tested it. ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver3] scsi: varlen extended and vendor-specific cdbs 2008-04-17 13:04 ` FUJITA Tomonori @ 2008-04-17 13:29 ` Boaz Harrosh 0 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-17 13:29 UTC (permalink / raw) To: FUJITA Tomonori, Pete Wyckoff Cc: James.Bottomley, linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven On Thu, Apr 17 2008 at 16:04 +0300, FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote: > On Thu, 17 Apr 2008 15:25:23 +0300 > Boaz Harrosh <bharrosh@panasas.com> wrote: > >> Add support for variable-length, extended, and vendor specific >> CDBs to scsi-ml. It is now possible for initiators and ULD's >> to issue these types of commands. LLDs need not change much. >> All they need is to raise the .max_cmd_len to the longest command >> they support (see iscsi patch). >> >> - clean-up some code paths that did not expect commands to be >> larger than 16, and change cmd_len members' type to short as >> char is not enough. >> >> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> >> Signed-off-by: Benny Halevy <bhalevy@panasas.com> >> --- >> block/scsi_ioctl.c | 5 ++--- >> drivers/scsi/constants.c | 10 +++------- >> drivers/scsi/scsi.c | 15 ++++----------- >> drivers/scsi/scsi_lib.c | 2 +- >> include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- >> include/scsi/scsi_cmnd.h | 2 +- >> include/scsi/scsi_host.h | 8 +++----- >> 7 files changed, 47 insertions(+), 35 deletions(-) > > looks fine to me though I've not tested it. > -- I agree, we need more testing. I'm doing that right now. I've been running with the old patch for ages and also Pete had a nice heavy load on that code. But this here was not tried as log. Pete if you have a ready made setup maybe you can give it a go. Tomo perhaps you can add these 3 patches to your tests. You need: linux-block for-2.6.26 branch - for block support of large commands scsi-misc - for iscsi's bidi and extended commands these three patches. - scsi varlen support And then the patch for bsg. But over all I have audit the code and it looks good, Tomo was right it was redundant code. Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 3/3] iscsi_tcp: Enable large commands 2008-04-15 12:24 ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh 2008-04-15 12:30 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh 2008-04-15 12:34 ` [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh @ 2008-04-15 12:37 ` Boaz Harrosh 2008-04-15 13:08 ` James Smart 2 siblings, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-15 12:37 UTC (permalink / raw) To: FUJITA Tomonori, James Bottomley, Mike Christie Cc: linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz, Alasdair G Kergon, Geert Uytterhoeven Let through up to the largest command of 260 defined by the scsi standard. iscsi core supports this already. Now that the scsi-ml supports it we can start using large commands. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- drivers/scsi/iscsi_tcp.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 555f4e3..6500192 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1859,7 +1859,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, shost->max_lun = iscsi_max_lun; shost->max_id = 0; shost->max_channel = 0; - shost->max_cmd_len = 16; + shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE; shost->can_queue = cmds_max; if (iscsi_host_add(shost, NULL)) -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 3/3] iscsi_tcp: Enable large commands 2008-04-15 12:37 ` [PATCH 3/3] iscsi_tcp: Enable large commands Boaz Harrosh @ 2008-04-15 13:08 ` James Smart 2008-04-15 13:38 ` Boaz Harrosh 2008-04-15 13:46 ` FUJITA Tomonori 0 siblings, 2 replies; 77+ messages in thread From: James Smart @ 2008-04-15 13:08 UTC (permalink / raw) To: Boaz Harrosh Cc: FUJITA Tomonori, James Bottomley, Mike Christie, linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz, Alasdair G Kergon, Geert Uytterhoeven Boaz Harrosh wrote: > Let through up to the largest command of 260 defined by the scsi standard. > iscsi core supports this already. Now that the scsi-ml supports it we can > start using large commands. Just to double-check: if we use sg_io to pass through requests from user-land, which are addressed to drivers or transports, and which may not be a SCSI command but rather just something utilizing the sg_io infrastructure for management or pass-thru, are we limited to 260 bytes for request/cmd payload ? -- james s ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 3/3] iscsi_tcp: Enable large commands 2008-04-15 13:08 ` James Smart @ 2008-04-15 13:38 ` Boaz Harrosh 2008-04-15 13:57 ` Benny Halevy 2008-04-15 13:46 ` FUJITA Tomonori 1 sibling, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-15 13:38 UTC (permalink / raw) To: James.Smart Cc: FUJITA Tomonori, James Bottomley, Mike Christie, linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz, Alasdair G Kergon, Geert Uytterhoeven On Tue, Apr 15 2008 at 16:08 +0300, James Smart <James.Smart@Emulex.Com> wrote: > Boaz Harrosh wrote: >> Let through up to the largest command of 260 defined by the scsi standard. >> iscsi core supports this already. Now that the scsi-ml supports it we can >> start using large commands. > > Just to double-check: > if we use sg_io to pass through requests from user-land, which are addressed to > drivers or transports, and which may not be a SCSI command but rather just something > utilizing the sg_io infrastructure for management or pass-thru, are we limited to > 260 bytes for request/cmd payload ? > > -- james s I think that only bsg, after the pending patches get accepted, will let you pass larger then 16 bytes commands from user-land. sg_io is I think limited to 16. However this could be fixed. (With sg_io, did you mean commands going through the sg.c driver?) The block layer imposes no limits, and so is scsi-ml. The only limits are from ULDs, and LLDs, like here, iscsi protocol does not support more then SCSI_MAX_VARLEN_CDB_SIZE (260). If you need support in any other ULD, I will be happy to help. Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 3/3] iscsi_tcp: Enable large commands 2008-04-15 13:38 ` Boaz Harrosh @ 2008-04-15 13:57 ` Benny Halevy 0 siblings, 0 replies; 77+ messages in thread From: Benny Halevy @ 2008-04-15 13:57 UTC (permalink / raw) To: Boaz Harrosh Cc: James.Smart, FUJITA Tomonori, James Bottomley, Mike Christie, linux-scsi, Jens Axboe, Bartlomiej Zolnierkiewicz, Alasdair G Kergon, Geert Uytterhoeven On Apr. 15, 2008, 16:38 +0300, Boaz Harrosh <bharrosh@panasas.com> wrote: > On Tue, Apr 15 2008 at 16:08 +0300, James Smart <James.Smart@Emulex.Com> wrote: >> Boaz Harrosh wrote: >>> Let through up to the largest command of 260 defined by the scsi standard. >>> iscsi core supports this already. Now that the scsi-ml supports it we can >>> start using large commands. >> Just to double-check: >> if we use sg_io to pass through requests from user-land, which are addressed to >> drivers or transports, and which may not be a SCSI command but rather just something >> utilizing the sg_io infrastructure for management or pass-thru, are we limited to >> 260 bytes for request/cmd payload ? >> >> -- james s > > I think that only bsg, after the pending patches get accepted, will let you > pass larger then 16 bytes commands from user-land. sg_io is I think limited > to 16. However this could be fixed. (With sg_io, did you mean commands going > through the sg.c driver?) > > The block layer imposes no limits, and so is scsi-ml. The only limits are from > ULDs, and LLDs, like here, iscsi protocol does not support more then > SCSI_MAX_VARLEN_CDB_SIZE (260). Actually the 260 byte limit comes from SCSI variable length CDB maximum length. iSCSI allows to send larger CDBs with the Extended CDB AHS that has a 16 bit length field. Within the protocol constraints, the longest CDB would be 16 (in BHS) + 65532 (in AHS) = 65548 bytes long :) Benny > > If you need support in any other ULD, I will be happy to help. > > Boaz > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 3/3] iscsi_tcp: Enable large commands 2008-04-15 13:08 ` James Smart 2008-04-15 13:38 ` Boaz Harrosh @ 2008-04-15 13:46 ` FUJITA Tomonori 1 sibling, 0 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-15 13:46 UTC (permalink / raw) To: James.Smart Cc: bharrosh, fujita.tomonori, James.Bottomley, michaelc, linux-scsi, jens.axboe, bzolnier, agk, Geert.Uytterhoeven On Tue, 15 Apr 2008 09:08:23 -0400 James Smart <James.Smart@Emulex.Com> wrote: > Boaz Harrosh wrote: > > Let through up to the largest command of 260 defined by the scsi standard. > > iscsi core supports this already. Now that the scsi-ml supports it we can > > start using large commands. > > Just to double-check: > if we use sg_io to pass through requests from user-land, which are addressed to > drivers or transports, and which may not be a SCSI command but rather just something > utilizing the sg_io infrastructure for management or pass-thru, are we limited to > 260 bytes for request/cmd payload ? With SG_IO (block, sg.c, and bsg), the command length is still limited to 16 bytes (BLK_MAX_CDB). We will remove the limit in bsg shortly. As you know, bsg supports bidi data transfer and there is no limit on the length of request and response payload. SAS management protocol uses request and response payload for data transfer. It doesn't use the command area (that is used for SCSI command). ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-12 5:52 ` FUJITA Tomonori 2008-04-13 9:13 ` Boaz Harrosh @ 2008-04-13 14:07 ` James Bottomley 2008-04-13 16:17 ` FUJITA Tomonori 1 sibling, 1 reply; 77+ messages in thread From: James Bottomley @ 2008-04-13 14:07 UTC (permalink / raw) To: FUJITA Tomonori; +Cc: bharrosh, jens.axboe, hch, linux-scsi, akpm On Sat, 2008-04-12 at 14:52 +0900, FUJITA Tomonori wrote: > bsg are created only for scsi devices (and scsi objects like sas host) > now. Are there other means to send commands except for ioctl? Right now they are ... but the design was to allow for arbitrary packet commands (like the frame in/frame out type that SMP needs), so the anticipation is that it will be usable by arbitrary packet commands for any block conforming device, examples of which would be ide taskfiles, raid firmware commands and any other weirder native protocols. On the other hand, this is future work and won't depend on the legacy 16 byte cmd size. The only block device I know that implements SG_IO is cciss, so perhaps there's no need to support a legacy mode at all for large packet commands. James ^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH 2/3 ver2] block layer extended-cdb support 2008-04-13 14:07 ` [PATCH 2/3 ver2] block layer extended-cdb support James Bottomley @ 2008-04-13 16:17 ` FUJITA Tomonori 0 siblings, 0 replies; 77+ messages in thread From: FUJITA Tomonori @ 2008-04-13 16:17 UTC (permalink / raw) To: James.Bottomley Cc: fujita.tomonori, bharrosh, jens.axboe, hch, linux-scsi, akpm On Sun, 13 Apr 2008 09:07:55 -0500 James Bottomley <James.Bottomley@HansenPartnership.com> wrote: > On Sat, 2008-04-12 at 14:52 +0900, FUJITA Tomonori wrote: > > bsg are created only for scsi devices (and scsi objects like sas host) > > now. Are there other means to send commands except for ioctl? > > Right now they are ... but the design was to allow for arbitrary packet > commands (like the frame in/frame out type that SMP needs), so the > anticipation is that it will be usable by arbitrary packet commands for > any block conforming device, examples of which would be ide taskfiles, > raid firmware commands and any other weirder native protocols. On the > other hand, this is future work and won't depend on the legacy 16 byte > cmd size. Yeah, we could add fc stuff to the list (James Smart said that he could use bsg in LSF 2007). > The only block device I know that implements SG_IO is cciss, so perhaps > there's no need to support a legacy mode at all for large packet > commands. I thought that ub supports it too. I'll check the whole tree. ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs 2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh 2008-03-25 16:22 ` [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh 2008-03-25 16:32 ` [PATCH 2/3] block layer varlen-cdb Boaz Harrosh @ 2008-03-25 16:36 ` Boaz Harrosh 2008-04-03 16:07 ` [PATCHSET 0/3] Is it time for " Boaz Harrosh 2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh 4 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-03-25 16:36 UTC (permalink / raw) To: James Bottomley, Jens Axboe, Christoph Hellwig, linux-scsi, Andrew Add support for variable-length, extended, and vendor specific CDBs to scsi-ml. It is now possible for initiators and ULD's to issue these types of commands. LLDs need not change much. All they need is to raise the .max_cmd_len to the longest command they support (see iscsi patches). - clean-up some code paths that did not expect commands to be larger than 16, and change cmd_len members' type to short as char is not enough. - Add support for varlen_cdb in scsi_execute. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> --- block/scsi_ioctl.c | 4 ++-- drivers/scsi/constants.c | 10 +++------- drivers/scsi/scsi.c | 22 +++++++++++----------- drivers/scsi/scsi_lib.c | 27 ++++++++++++++++++++++----- include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- include/scsi/scsi_cmnd.h | 2 +- include/scsi/scsi_host.h | 8 +++----- 7 files changed, 75 insertions(+), 38 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a2c3a93..0a83a99 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -33,13 +33,13 @@ #include <scsi/scsi_cmnd.h> /* Command group 3 is reserved and should never be used. */ -const unsigned char scsi_command_size[8] = +const unsigned char scsi_command_size_tbl[8] = { 6, 10, 10, 12, 16, 12, 10, 10 }; -EXPORT_SYMBOL(scsi_command_size); +EXPORT_SYMBOL(scsi_command_size_tbl); #include <scsi/sg.h> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 403a7f2..9785d73 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -28,7 +28,6 @@ #define SERVICE_ACTION_OUT_12 0xa9 #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f -#define VARIABLE_LENGTH_CMD 0x7f @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short variable length command, " "len=%d ext_len=%d", len, cdb_len); @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short opcode=0x%x command, len=%d " "ext_len=%d", cdb0, len, cdb_len); @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) int k, len; print_opcode_name(cdb, 0); - if (VARIABLE_LENGTH_CMD == cdb[0]) - len = cdb[7] + 8; - else - len = COMMAND_SIZE(cdb[0]); + len = scsi_command_size(cdb); /* print out all bytes in cdb */ for (k = 0; k < len; ++k) printk(" %02x", cdb[k]); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index f6980bd..3dabecb 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); #define MIN_RESET_PERIOD (15*HZ) /* - * Macro to determine the size of SCSI command. This macro takes vendor - * unique commands into account. SCSI commands in groups 6 and 7 are - * vendor unique and we will depend upon the command length being - * supplied correctly in cmd_len. - */ -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) - -/* * Note - the initial logging level can be set here to log events at boot time. * After the system is up, you may enable logging via the /proc interface. */ @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) unsigned long flags = 0; unsigned long timeout; int rtn = 0; + unsigned cmd_len; /* check if the device is still usable */ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * Before we queue this command, check if the command * length exceeds what the host adapter can handle. */ - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { + cmd_len = cmd->cmd_len; + if (!cmd_len) { + BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD); + cmd_len = COMMAND_SIZE((cmd)->cmnd[0]); + } + + if (cmd_len > cmd->device->host->max_cmd_len) { SCSI_LOG_MLQUEUE(3, - printk("queuecommand : command too long.\n")); + printk("queuecommand : command too long. " + "cdb_size=%d host->max_cmd_len=%d\n", + cmd->cmd_len, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT << 16); scsi_done(cmd); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 75f3aab..6333126 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -193,8 +193,16 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, buffer, bufflen, __GFP_WAIT)) goto out; - req->cmd_len = COMMAND_SIZE(cmd[0]); - memcpy(req->cmd, cmd, req->cmd_len); + if (cmd[0] == VARIABLE_LENGTH_CMD) + rq_set_varlen_cdb(req, (u8 *)cmd, scsi_varlen_cdb_length(cmd)); + else { + req->cmd_len = COMMAND_SIZE(cmd[0]); + memcpy(req->cmd, cmd, req->cmd_len); + if (req->cmd_len < MAX_COMMAND_SIZE) + memset(&req->cmd[req->cmd_len], 0, + MAX_COMMAND_SIZE - req->cmd_len); + } + req->sense = sense; req->sense_len = 0; req->retries = retries; @@ -445,7 +453,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) scsi_set_resid(cmd, 0); memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); if (cmd->cmd_len == 0) - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); + cmd->cmd_len = scsi_command_size(cmd->cmnd); } void scsi_device_unbusy(struct scsi_device *sdev) @@ -1100,6 +1108,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd; + u8 *varlen_cdb; int ret = scsi_prep_state_check(sdev, req); if (ret != BLKPREP_OK) @@ -1131,14 +1140,22 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) req->buffer = NULL; } - cmd->cmd_len = req->cmd_len; + varlen_cdb = rq_get_varlen_cdb(req); + if (varlen_cdb) { + cmd->cmnd = varlen_cdb; + cmd->cmd_len = req->varlen_cdb_len; + } else if (req->cmd_len) + cmd->cmd_len = req->cmd_len; + else + cmd->cmd_len = scsi_command_size(cmd->cmnd); + if (!req->data_len) cmd->sc_data_direction = DMA_NONE; else if (rq_data_dir(req) == WRITE) cmd->sc_data_direction = DMA_TO_DEVICE; else cmd->sc_data_direction = DMA_FROM_DEVICE; - + cmd->transfersize = req->data_len; cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 1f74bcd..0ba902c 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -30,13 +30,6 @@ #endif /* - * SCSI command lengths - */ - -extern const unsigned char scsi_command_size[8]; -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] - -/* * Special value for scanning to specify scanning or rescanning of all * possible channels, (target) ids, or luns on a given shost. */ @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8]; #define MODE_SENSE_10 0x5a #define PERSISTENT_RESERVE_IN 0x5e #define PERSISTENT_RESERVE_OUT 0x5f +#define VARIABLE_LENGTH_CMD 0x7f #define REPORT_LUNS 0xa0 #define MAINTENANCE_IN 0xa3 #define MOVE_MEDIUM 0xa5 @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8]; #define ATA_12 0xa1 /* 12-byte pass-thru */ /* + * SCSI command lengths + */ + +#define SCSI_MAX_VARLEN_CDB_SIZE 260 + +/* defined in T10 SCSI Primary Commands-2 (SPC2) */ +struct scsi_varlen_cdb_hdr { + u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */ + u8 control; + u8 misc[5]; + u8 additional_cdb_length; /* total cdb length - 8 */ + __be16 service_action; + /* service specific data follows */ +}; + +static inline unsigned +scsi_varlen_cdb_length(const void *hdr) +{ + return ((struct scsi_varlen_cdb_hdr*)hdr)->additional_cdb_length + 8; +} + +extern const unsigned char scsi_command_size_tbl[8]; +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] + +static inline unsigned +scsi_command_size(const unsigned char *cmnd) +{ + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? scsi_varlen_cdb_length(cmnd) : + COMMAND_SIZE(cmnd[0]); +} + +/* * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft * T10/1561-D Revision 4 Draft dated 7th November 2002. */ diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index dea73e5..f4dacb1 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -78,7 +78,7 @@ struct scsi_cmnd { int allowed; int timeout_per_command; - unsigned char cmd_len; + unsigned short cmd_len; enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 4913286..31f1bfd 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -573,13 +573,11 @@ struct Scsi_Host { /* * The maximum length of SCSI commands that this host can accept. * Probably 12 for most host adapters, but could be 16 for others. + * or 260 if the driver supports variable length cdbs. * For drivers that don't set this field, a value of 12 is - * assumed. I am leaving this as a number rather than a bit - * because you never know what subsequent SCSI standards might do - * (i.e. could there be a 20 byte or a 24-byte command a few years - * down the road?). + * assumed. */ - unsigned char max_cmd_len; + unsigned short max_cmd_len; int this_id; int can_queue; -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs 2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh ` (2 preceding siblings ...) 2008-03-25 16:36 ` [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh @ 2008-04-03 16:07 ` Boaz Harrosh 2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh 4 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-03 16:07 UTC (permalink / raw) To: James Bottomley, Jens Axboe, Andrew Morton, FUJITA Tomonori Cc: Christoph Hellwig, linux-scsi Boaz Harrosh wrote: > Submitted is a patchset for adding support for variable-length, extended, > and vendor specific CDBs. It should now cover the entire range of the > SCSI standard. (and/or any other use of command packets in block devices) > > They are based on scsi-misc/scsi-rc-fixes/linux-block. They are aimed > for the 2.6.26 merge window. Andrew please also include them in -mm > for testing. > ping James. Are you giving me the other side of the boot on these patches? Is that NO for Linux-next or NACK for never? If it is a maybe. Could you please acknowledge a "maybe, need testing" so they can be tested in -mm tree. A new -mm tree has passed after I sent these patches and they are still not tested there. ping Jens. I need your ACK on the block bits of these patches. (patch 2/3). There are already users that might use this facility if available. Andrew Hi? Could we test these patches anyway. It is a new fixture for supporting more of the scsi standard. And a way for vendor specific commands to any scsi/block device in a common way. Today every driver/vendor cooks it's own char device and private ioctrls to issue such commands. With these patches and a patch to the bsg driver that are already used more then a year, these things could be done in one standard way. Including very efficient way to pass large chunks of data. The new fixture is not dangerous at all, only the first patch is a cleanup and optimization which might be dangerous (theoretically), hence the request for testing. I did it this way so the overall cost of the enhancement is zero, or actually we gain a few bytes and a couple of cycles. These 3 patches are on a git here: git://git.open-osd.org/open-osd.git varlen And on the gitweb here: http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=shortlog;h=varlen They will be rebased from time to time ontop of latest scsi-misc/scsi-rc-fixes Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCHSET 0/4 ver2] Is it time for varlen extended and vendor-specific cdbs 2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh ` (3 preceding siblings ...) 2008-04-03 16:07 ` [PATCHSET 0/3] Is it time for " Boaz Harrosh @ 2008-04-13 16:30 ` Boaz Harrosh 2008-04-13 16:37 ` [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh ` (3 more replies) 4 siblings, 4 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-13 16:30 UTC (permalink / raw) To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike Yet another iteration with James's suggestions and the 3rd patch converted to the new block API. Also a small patch for iscsi_tcp.c --- Submitted is a patchset for adding support for variable-length, extended, and vendor specific CDBs. It should now cover the entire range of the SCSI standard, and/or any other use of command packets in block devices. They are based on scsi-misc. They are aimed for the 2.6.26 merge window. Andrew ! Please include them in -mm for testing. Atleast the first patch that no one had any comments and is the theoretically dangerous cleanup. Difference from last time, is at struct request. I did a smallish hack to save the extra pointer space. The pointer now shares it's space with the request->cmd, as they are mutual exclusive. The flag to switch between them is when cmd_len == 0 and varlen_cdb_len != 0 I've added 3 accessors to hide the mess. I think this approach should be safe with legacy drivers. This is on top of the size shrink to struct scsi_cmnd gained in the first patch. We save upto 12 bytes on 32 bit ARCHs So over all, this cleans things up, and add fixtures without *any extra cost*. [1/4] Let scsi_cmnd->cmnd use request->cmd buffer Here I let scsi_cmnd->cmnd point to the space allocated by request->cmd, instead of copying the data. The scsi_cmnd->cmd_len is guaranteed to contain the right length of the command. I have tried to go over every single place in the kernel that uses scsi_cmnd->cmnd and make sure it looks sane. Surprisingly to me, that was not at all bad. I hope I did not miss anything. I've tested on an x86_64 machine booting from a sata disk and ran the iscsi regression tests as well as my bidi and varlen tests on top of the complete patchset and all tests passed. [2/4] block layer varlen-cd Here I added an option to use a user supplied buffer for an arbitrary large command. Buffer must be kept valid until execution of request ends. The pointer to the buffer shares it's space with the fixed length command, so the size of struct request does not change. [3/4] scsi: varlen extended and vendor-specific cdbs Adds support for variable length, extended, and vendor-specific cdbs at the scsi mid-layer. [4/4] iscsi_tcp: iscsi_tcp: Enable large commands just a one liner, Mike I need your Sign-off-by on this one. Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer 2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh @ 2008-04-13 16:37 ` Boaz Harrosh 2008-04-13 16:39 ` [PATCH 2/4] block layer extended-cdb support Boaz Harrosh ` (2 subsequent siblings) 3 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-13 16:37 UTC (permalink / raw) To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike - struct scsi_cmnd had a 16 bytes command buffer of its own. This is an unnecessary duplication and copy of request's cmd. It is probably left overs from the time that scsi_cmnd could function without a request attached. So clean that up. - Once above is done, few places, apart from scsi-ml, needed adjustments due to changing the data type of scsi_cmnd->cmnd. - Lots of drivers still use MAX_COMMAND_SIZE. So I have left that #define but equate it to BLK_MAX_CDB. The way I see it and is reflected in the patch below is. MAX_COMMAND_SIZE - means: The longest fixed-length (*) SCSI CDB as per the SCSI standard and is not related to the implementation. BLK_MAX_CDB. - The allocated space at the request level - I have audit all ISA drivers and made sure none use ->cmnd in a DMA Operation. Same audit was done by Andi Kleen. (*)fixed-length here means commands that their size can be determined by their opcode and the CDB does not carry a length specifier, (unlike the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly true and the SCSI standard also defines extended commands and vendor specific commands that can be bigger than 16 bytes. The kernel will support these using the same infrastructure used for VARLEN CDB's. So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml supports without specifying a cmd_len by ULD's Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- drivers/firewire/fw-sbp2.c | 2 +- drivers/s390/scsi/zfcp_dbf.c | 2 +- drivers/s390/scsi/zfcp_fsf.c | 2 +- drivers/scsi/53c700.c | 6 +++--- drivers/scsi/a100u2w.c | 2 +- drivers/scsi/gdth.c | 2 +- drivers/scsi/hptiop.c | 6 +++--- drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- drivers/scsi/initio.c | 2 +- drivers/scsi/qla1280.c | 4 ++-- drivers/scsi/scsi_error.c | 14 ++++++++------ drivers/scsi/scsi_lib.c | 5 +++-- drivers/scsi/scsi_tgt_lib.c | 2 ++ drivers/usb/storage/isd200.c | 2 ++ include/scsi/scsi_cmnd.h | 21 +++++++++++++++++++-- include/scsi/scsi_eh.h | 4 ++-- 16 files changed, 51 insertions(+), 27 deletions(-) diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 62b4e47..2260e56 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -1492,7 +1492,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) memset(orb->request.command_block, 0, sizeof(orb->request.command_block)); - memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); + memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len); orb->base.callback = complete_command_orb; orb->base.request_bus = diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 85ba4cc..1bec0b2 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -1057,7 +1057,7 @@ static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level, rec->scsi_result = scsi_cmnd->result; rec->scsi_cmnd = (unsigned long)scsi_cmnd; rec->scsi_serial = scsi_cmnd->serial_number; - memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd, + memcpy(rec->scsi_opcode, scsi_cmnd->cmnd, min((int)scsi_cmnd->cmd_len, ZFCP_DBF_SCSI_OPCODE)); rec->scsi_retries = scsi_cmnd->retries; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index b7aa969..ea46881 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4024,7 +4024,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n", scpnt->result); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, - (void *) &scpnt->cmnd, scpnt->cmd_len); + scpnt->cmnd, scpnt->cmd_len); ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n", fcp_rsp_iu->fcp_sns_len); diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index f4c4fe9..f5a9add 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, (struct NCR_700_command_slot *)SCp->host_scribble; dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); + MAX_COMMAND_SIZE, DMA_TO_DEVICE); if (slot->flags == NCR_700_FLAG_AUTOSENSE) { char *cmnd = NCR_700_get_sense_cmnd(SCp->device); #ifdef NCR_700_DEBUG @@ -1004,7 +1004,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, * here */ NCR_700_unmap(hostdata, SCp, slot); dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), + MAX_COMMAND_SIZE, DMA_TO_DEVICE); cmnd[0] = REQUEST_SENSE; @@ -1901,7 +1901,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) } slot->resume_offset = 0; slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); + MAX_COMMAND_SIZE, DMA_TO_DEVICE); NCR_700_start_command(SCp); return 0; } diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 792b2e8..ced3eeb 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -895,7 +895,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru } else { scb->tag_msg = 0; /* No tag support */ } - memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len); + memcpy(scb->cdb, cmd->cmnd, scb->cdb_len); } /** diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index c6d6e7c..8e2e964 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -465,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, scp->request = (struct request *)&wait; scp->timeout_per_command = timeout*HZ; scp->cmd_len = 12; - memcpy(scp->cmnd, cmnd, 12); + scp->cmnd = cmnd; cmndinfo.priority = IOCTL_PRI; cmndinfo.internal_cmd_str = gdtcmd; cmndinfo.internal_command = 1; diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index beecda9..a24c5e3 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -763,9 +763,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, scp, host->host_no, scp->device->channel, scp->device->id, scp->device->lun, - *((u32 *)&scp->cmnd), - *((u32 *)&scp->cmnd + 1), - *((u32 *)&scp->cmnd + 2), + ((u32 *)scp->cmnd)[0], + ((u32 *)scp->cmnd)[1], + ((u32 *)scp->cmnd)[2], _req->index, _req->req_virt); scp->result = 0; diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 78d46a9..df9b865 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -738,7 +738,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, srp_cmd = &evt_struct->iu.srp.cmd; memset(srp_cmd, 0x00, SRP_MAX_IU_LEN); srp_cmd->opcode = SRP_CMD; - memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd)); + memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb)); srp_cmd->lun = ((u64) lun) << 48; if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index dbae3fd..e3f7397 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c cblk->hastat = 0; cblk->tastat = 0; /* Command the command */ - memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len); + memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len); /* Set up tags */ if (cmnd->device->tagged_supported) { /* Tag Support */ diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 68c0d09..b53420b 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -2863,7 +2863,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Load SCSI command packet. */ pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd)); /* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ /* Set transfer direction. */ @@ -3132,7 +3132,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Load SCSI command packet. */ pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd)); /*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ /* Set transfer direction. */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 221f31e..8b5748a 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -626,7 +626,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) * @scmd: SCSI command structure to hijack * @ses: structure to save restore information * @cmnd: CDB to send. Can be NULL if no new cmnd is needed - * @cmnd_size: size in bytes of @cmnd + * @cmnd_size: size in bytes of @cmnd (must be <= BLK_MAX_CDB) * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) * * This function is used to save a scsi command information before re-execution @@ -648,12 +648,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, * command. */ ses->cmd_len = scmd->cmd_len; - memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd)); + ses->cmnd = scmd->cmnd; ses->data_direction = scmd->sc_data_direction; ses->sdb = scmd->sdb; ses->next_rq = scmd->request->next_rq; ses->result = scmd->result; + scmd->cmnd = ses->eh_cmnd; + memset(scmd->cmnd, 0, BLK_MAX_CDB); memset(&scmd->sdb, 0, sizeof(scmd->sdb)); scmd->request->next_rq = NULL; @@ -665,14 +667,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, scmd->sdb.table.sgl = &ses->sense_sgl; scmd->sc_data_direction = DMA_FROM_DEVICE; scmd->sdb.table.nents = 1; - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); scmd->cmnd[0] = REQUEST_SENSE; scmd->cmnd[4] = scmd->sdb.length; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } else { scmd->sc_data_direction = DMA_NONE; if (cmnd) { - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); + BUG_ON(cmnd_size > BLK_MAX_CDB); memcpy(scmd->cmnd, cmnd, cmnd_size); scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } @@ -705,7 +706,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) * Restore original data */ scmd->cmd_len = ses->cmd_len; - memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd)); + scmd->cmnd = ses->cmnd; scmd->sc_data_direction = ses->data_direction; scmd->sdb = ses->sdb; scmd->request->next_rq = ses->next_rq; @@ -1774,7 +1775,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scmd->request = &req; memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); - memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd)); + scmd->cmnd = req.cmd; + memset(scmd->cmnd, 0, BLK_MAX_CDB); scmd->scsi_done = scsi_reset_provider_done_command; memset(&scmd->sdb, 0, sizeof(scmd->sdb)); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 67f412b..325270b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1090,6 +1090,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, cmd->tag = req->tag; cmd->request = req; + cmd->cmnd = req->cmd; + return cmd; } @@ -1127,8 +1129,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) req->buffer = NULL; } - BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); - memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); cmd->cmd_len = req->cmd_len; if (!req->data_len) cmd->sc_data_direction = DMA_NONE; @@ -1165,6 +1165,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) if (unlikely(!cmd)) return BLKPREP_DEFER; + memset(cmd->cmnd, 0, BLK_MAX_CDB); return scsi_init_io(cmd, GFP_ATOMIC); } EXPORT_SYMBOL(scsi_setup_fs_cmnd); diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index a0f308b..8c92ef3 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -107,6 +107,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, cmd->jiffies_at_alloc = jiffies; cmd->request = rq; + cmd->cmnd = rq->cmd; + rq->special = cmd; rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd_flags |= REQ_TYPE_BLOCK_PC; diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 971d13d..3addcd8 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -292,6 +292,7 @@ struct isd200_info { /* maximum number of LUNs supported */ unsigned char MaxLUNs; + unsigned char cmnd[BLK_MAX_CDB]; struct scsi_cmnd srb; struct scatterlist sg; }; @@ -450,6 +451,7 @@ static int isd200_action( struct us_data *us, int action, memset(&ata, 0, sizeof(ata)); memset(&srb_dev, 0, sizeof(srb_dev)); + srb->cmnd = info->cmnd; srb->device = &srb_dev; ++srb->serial_number; diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 8d20e60..dea73e5 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -7,10 +7,28 @@ #include <linux/types.h> #include <linux/timer.h> #include <linux/scatterlist.h> +#include <linux/blkdev.h> struct Scsi_Host; struct scsi_device; +/* + * MAX_COMMAND_SIZE is: + * The longest fixed-length SCSI CDB as per the SCSI standard. + * fixed-length means: commands that their size can be determined + * by their opcode and the CDB does not carry a length specifier, (unlike + * the VARIABLE_LENGTH_CMD(0x7f) command). This is actually not exactly + * true and the SCSI standard also defines extended commands and + * vendor specific commands that can be bigger than 16 bytes. The kernel + * will support these using the same infrastructure used for VARLEN CDB's. + * So in effect MAX_COMMAND_SIZE means the maximum size command scsi-ml + * supports without specifying a cmd_len by ULD's + */ +#define MAX_COMMAND_SIZE 16 +#if (MAX_COMMAND_SIZE > BLK_MAX_CDB) +# error MAX_COMMAND_SIZE can not be smaller than BLK_MAX_CDB +#endif + struct scsi_data_buffer { struct sg_table table; unsigned length; @@ -64,8 +82,7 @@ struct scsi_cmnd { enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ -#define MAX_COMMAND_SIZE 16 - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char *cmnd; struct timer_list eh_timeout; /* Used to time out the command. */ diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index d3a133b..2a9add2 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -75,11 +75,11 @@ struct scsi_eh_save { int result; enum dma_data_direction data_direction; unsigned char cmd_len; - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char *cmnd; struct scsi_data_buffer sdb; struct request *next_rq; - /* new command support */ + unsigned char eh_cmnd[BLK_MAX_CDB]; struct scatterlist sense_sgl; }; -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH 2/4] block layer extended-cdb support 2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh 2008-04-13 16:37 ` [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh @ 2008-04-13 16:39 ` Boaz Harrosh 2008-04-13 16:39 ` [PATCH 3/4] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh 2008-04-13 16:41 ` [PATCH 4/4] iscsi_tcp: Enable large command Boaz Harrosh 3 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-13 16:39 UTC (permalink / raw) To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike - add ext_cdb and ext_cdb_len to hold a large external cdb if needed. They start as empty. Allocation of buffer must be done by user and held until request execution is done. - Since there can be either a fix_length command up to 16 bytes or an external extended command but never both, we hold the two types in a union to save space. The presence of ext_cdb_len!=0 and cmd_len==0 signals an ext_cdb mode. - Use new rq_set_cdb() to set everything up in a way that will not confuse drivers that do not support extended cdb's. - Use rq_get_cdb()/rq_get_cdb_len() to retrieve command and length in a generic way. - Once all drivers and users convert to the new accessors the cmd[] 16 bytes buffer can be discarded. - Note that this patch does not add any size to struct request since the unsigned cmd_len is split here to 2 ushorts, which is more then enough. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- block/blk-core.c | 2 ++ include/linux/blkdev.h | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 2a438a9..cc9a790 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -141,6 +141,8 @@ void rq_init(struct request_queue *q, struct request *rq) rq->end_io = NULL; rq->end_io_data = NULL; rq->next_rq = NULL; + rq->ext_cdb_len = 0; + rq->ext_cdb = NULL; } static void req_bio_endio(struct request *rq, struct bio *bio, diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 6f79d40..2f87c9d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -213,8 +213,15 @@ struct request { /* * when request is used as a packet command carrier */ - unsigned int cmd_len; - unsigned char cmd[BLK_MAX_CDB]; + unsigned short cmd_len; + unsigned short ext_cdb_len; /* length of ext_cdb buffer */ + union { + unsigned char cmd[BLK_MAX_CDB]; + unsigned char *ext_cdb;/* an optional extended cdb. + * points to a user buffer that must + * be valid until end of request + */ + }; unsigned int data_len; unsigned int extra_len; /* length of alignment and padding */ @@ -484,6 +491,36 @@ enum { #define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC) #define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META) +static inline void rq_set_cdb(struct request *rq, u8 *cdb, short cdb_len) +{ + if (cdb_len <= BLK_MAX_CDB) { + memcpy(rq->cmd, cdb, cdb_len); + rq->cmd_len = cdb_len; + rq->ext_cdb_len = 0; + } + else { + rq->cmd_len = 0; /* Make sure legacy drivers don't get confused */ + rq->ext_cdb_len = cdb_len; + rq->ext_cdb = cdb; + } +} + +static inline u8 *rq_get_cdb(struct request *rq) +{ + if (!rq->cmd_len && rq->ext_cdb_len) + return rq->ext_cdb; + else + return rq->cmd; +} + +static inline unsigned short rq_get_cdb_len(struct request *rq) +{ + if (!rq->cmd_len && rq->ext_cdb_len) + return rq->ext_cdb_len; + else + return rq->cmd_len; +} + static inline int blk_queue_full(struct request_queue *q, int rw) { if (rw == READ) -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH 3/4] scsi: varlen extended and vendor-specific cdbs 2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh 2008-04-13 16:37 ` [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh 2008-04-13 16:39 ` [PATCH 2/4] block layer extended-cdb support Boaz Harrosh @ 2008-04-13 16:39 ` Boaz Harrosh 2008-04-13 16:41 ` [PATCH 4/4] iscsi_tcp: Enable large command Boaz Harrosh 3 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2008-04-13 16:39 UTC (permalink / raw) To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike Add support for variable-length, extended, and vendor specific CDBs to scsi-ml. It is now possible for initiators and ULD's to issue these types of commands. LLDs need not change much. All they need is to raise the .max_cmd_len to the longest command they support (see iscsi patches). - clean-up some code paths that did not expect commands to be larger than 16, and change cmd_len members' type to short as char is not enough. - Add support for varlen_cdb in scsi_execute. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> --- block/scsi_ioctl.c | 4 ++-- drivers/scsi/constants.c | 10 +++------- drivers/scsi/scsi.c | 22 +++++++++++----------- drivers/scsi/scsi_lib.c | 18 ++++++++++++------ include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- include/scsi/scsi_cmnd.h | 2 +- include/scsi/scsi_host.h | 8 +++----- 7 files changed, 65 insertions(+), 39 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a2c3a93..0a83a99 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -33,13 +33,13 @@ #include <scsi/scsi_cmnd.h> /* Command group 3 is reserved and should never be used. */ -const unsigned char scsi_command_size[8] = +const unsigned char scsi_command_size_tbl[8] = { 6, 10, 10, 12, 16, 12, 10, 10 }; -EXPORT_SYMBOL(scsi_command_size); +EXPORT_SYMBOL(scsi_command_size_tbl); #include <scsi/sg.h> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 403a7f2..9785d73 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -28,7 +28,6 @@ #define SERVICE_ACTION_OUT_12 0xa9 #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f -#define VARIABLE_LENGTH_CMD 0x7f @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short variable length command, " "len=%d ext_len=%d", len, cdb_len); @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short opcode=0x%x command, len=%d " "ext_len=%d", cdb0, len, cdb_len); @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) int k, len; print_opcode_name(cdb, 0); - if (VARIABLE_LENGTH_CMD == cdb[0]) - len = cdb[7] + 8; - else - len = COMMAND_SIZE(cdb[0]); + len = scsi_command_size(cdb); /* print out all bytes in cdb */ for (k = 0; k < len; ++k) printk(" %02x", cdb[k]); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index f6980bd..3dabecb 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); #define MIN_RESET_PERIOD (15*HZ) /* - * Macro to determine the size of SCSI command. This macro takes vendor - * unique commands into account. SCSI commands in groups 6 and 7 are - * vendor unique and we will depend upon the command length being - * supplied correctly in cmd_len. - */ -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) - -/* * Note - the initial logging level can be set here to log events at boot time. * After the system is up, you may enable logging via the /proc interface. */ @@ -620,6 +611,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) unsigned long flags = 0; unsigned long timeout; int rtn = 0; + unsigned cmd_len; /* check if the device is still usable */ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { @@ -701,9 +693,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * Before we queue this command, check if the command * length exceeds what the host adapter can handle. */ - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { + cmd_len = cmd->cmd_len; + if (!cmd_len) { + BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD); + cmd_len = COMMAND_SIZE((cmd)->cmnd[0]); + } + + if (cmd_len > cmd->device->host->max_cmd_len) { SCSI_LOG_MLQUEUE(3, - printk("queuecommand : command too long.\n")); + printk("queuecommand : command too long. " + "cdb_size=%d host->max_cmd_len=%d\n", + cmd->cmd_len, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT << 16); scsi_done(cmd); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 325270b..76cd886 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -193,8 +193,11 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, buffer, bufflen, __GFP_WAIT)) goto out; - req->cmd_len = COMMAND_SIZE(cmd[0]); - memcpy(req->cmd, cmd, req->cmd_len); + rq_set_cdb(req, (u8 *)cmd, scsi_command_size(cmd)); + if (rq_get_cdb_len(req) < MAX_COMMAND_SIZE) + memset(&req->cmd[req->cmd_len], 0, + MAX_COMMAND_SIZE - req->cmd_len); + req->sense = sense; req->sense_len = 0; req->retries = retries; @@ -445,7 +448,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) scsi_set_resid(cmd, 0); memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); if (cmd->cmd_len == 0) - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); + cmd->cmd_len = scsi_command_size(cmd->cmnd); } void scsi_device_unbusy(struct scsi_device *sdev) @@ -1090,7 +1093,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, cmd->tag = req->tag; cmd->request = req; - cmd->cmnd = req->cmd; + cmd->cmnd = rq_get_cdb(req); return cmd; } @@ -1129,14 +1132,17 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) req->buffer = NULL; } - cmd->cmd_len = req->cmd_len; + cmd->cmd_len = rq_get_cdb_len(req); + if (!cmd->cmd_len) + cmd->cmd_len = scsi_command_size(cmd->cmnd); + if (!req->data_len) cmd->sc_data_direction = DMA_NONE; else if (rq_data_dir(req) == WRITE) cmd->sc_data_direction = DMA_TO_DEVICE; else cmd->sc_data_direction = DMA_FROM_DEVICE; - + cmd->transfersize = req->data_len; cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 1f74bcd..0ba902c 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -30,13 +30,6 @@ #endif /* - * SCSI command lengths - */ - -extern const unsigned char scsi_command_size[8]; -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] - -/* * Special value for scanning to specify scanning or rescanning of all * possible channels, (target) ids, or luns on a given shost. */ @@ -109,6 +102,7 @@ extern const unsigned char scsi_command_size[8]; #define MODE_SENSE_10 0x5a #define PERSISTENT_RESERVE_IN 0x5e #define PERSISTENT_RESERVE_OUT 0x5f +#define VARIABLE_LENGTH_CMD 0x7f #define REPORT_LUNS 0xa0 #define MAINTENANCE_IN 0xa3 #define MOVE_MEDIUM 0xa5 @@ -136,6 +130,38 @@ extern const unsigned char scsi_command_size[8]; #define ATA_12 0xa1 /* 12-byte pass-thru */ /* + * SCSI command lengths + */ + +#define SCSI_MAX_VARLEN_CDB_SIZE 260 + +/* defined in T10 SCSI Primary Commands-2 (SPC2) */ +struct scsi_varlen_cdb_hdr { + u8 opcode; /* opcode always == VARIABLE_LENGTH_CMD */ + u8 control; + u8 misc[5]; + u8 additional_cdb_length; /* total cdb length - 8 */ + __be16 service_action; + /* service specific data follows */ +}; + +static inline unsigned +scsi_varlen_cdb_length(const void *hdr) +{ + return ((struct scsi_varlen_cdb_hdr*)hdr)->additional_cdb_length + 8; +} + +extern const unsigned char scsi_command_size_tbl[8]; +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] + +static inline unsigned +scsi_command_size(const unsigned char *cmnd) +{ + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? scsi_varlen_cdb_length(cmnd) : + COMMAND_SIZE(cmnd[0]); +} + +/* * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft * T10/1561-D Revision 4 Draft dated 7th November 2002. */ diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index dea73e5..f4dacb1 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -78,7 +78,7 @@ struct scsi_cmnd { int allowed; int timeout_per_command; - unsigned char cmd_len; + unsigned short cmd_len; enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 4913286..31f1bfd 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -573,13 +573,11 @@ struct Scsi_Host { /* * The maximum length of SCSI commands that this host can accept. * Probably 12 for most host adapters, but could be 16 for others. + * or 260 if the driver supports variable length cdbs. * For drivers that don't set this field, a value of 12 is - * assumed. I am leaving this as a number rather than a bit - * because you never know what subsequent SCSI standards might do - * (i.e. could there be a 20 byte or a 24-byte command a few years - * down the road?). + * assumed. */ - unsigned char max_cmd_len; + unsigned short max_cmd_len; int this_id; int can_queue; -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH 4/4] iscsi_tcp: Enable large command 2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh ` (2 preceding siblings ...) 2008-04-13 16:39 ` [PATCH 3/4] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh @ 2008-04-13 16:41 ` Boaz Harrosh 2008-04-18 17:11 ` Mike Christie 3 siblings, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2008-04-13 16:41 UTC (permalink / raw) To: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton, Mike Let through up to the largest command of 260 defined by the scsi standard. iscsi core supports this already. Now that the scsi-ml supports it we can start using large commands. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- drivers/scsi/iscsi_tcp.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 555f4e3..6500192 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1859,7 +1859,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, shost->max_lun = iscsi_max_lun; shost->max_id = 0; shost->max_channel = 0; - shost->max_cmd_len = 16; + shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE; shost->can_queue = cmds_max; if (iscsi_host_add(shost, NULL)) -- 1.5.3.3 ^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH 4/4] iscsi_tcp: Enable large command 2008-04-13 16:41 ` [PATCH 4/4] iscsi_tcp: Enable large command Boaz Harrosh @ 2008-04-18 17:11 ` Mike Christie 0 siblings, 0 replies; 77+ messages in thread From: Mike Christie @ 2008-04-18 17:11 UTC (permalink / raw) To: Boaz Harrosh; +Cc: James Bottomley, Jens Axboe, linux-scsi, Andrew Morton Boaz Harrosh wrote: > Let through up to the largest command of 260 defined by the scsi standard. > iscsi core supports this already. Now that the scsi-ml supports it we can > start using large commands. > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > --- > drivers/scsi/iscsi_tcp.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c > index 555f4e3..6500192 100644 > --- a/drivers/scsi/iscsi_tcp.c > +++ b/drivers/scsi/iscsi_tcp.c > @@ -1859,7 +1859,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, > shost->max_lun = iscsi_max_lun; > shost->max_id = 0; > shost->max_channel = 0; > - shost->max_cmd_len = 16; > + shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE; > shost->can_queue = cmds_max; > > if (iscsi_host_add(shost, NULL)) This is fine whenever all this stuff gets in. acked-by: Mike Christie <michaelc@cs.wisc.edu> ^ permalink raw reply [flat|nested] 77+ messages in thread
* [RFC 0/4] varlen extended and vendor-specific cdbs @ 2007-11-01 17:54 Boaz Harrosh 2007-11-01 18:07 ` [PATCH 3/4] scsi: " Boaz Harrosh 0 siblings, 1 reply; 77+ messages in thread From: Boaz Harrosh @ 2007-11-01 17:54 UTC (permalink / raw) To: James Bottomley, Jens Axboe, Mike Christie, FUJITA Tomonori, linux-scsi Cc: Pete Wyckoff, Benny Halevy This is a proposal for adding support for variable-length, extended, and vendor specific CDBs. It should now cover the entire range of the SCSI standard. This patchset extends my original submission (over a year old) in that it starts with cleaning up scsi_cmnd, hence the first patch. The other three are similar to the ones submitted before. This effort is orthogonal to the bidi and scsi_data_buffer effort and can be accepted now. The patchset, however, is presented in this RFC on top of the scsi_data_buffer patches, as they sit in my tree. They can easily be rebased to current scsi-misc. The iscsi patch is on top of the iscsi branch of the iscsi-git-tree. (Matthew, these patches will conflict with your scsi_cmnd cleanup patches I promise to rebase them before submission) A complete git-tree based on scsi-misc which includes a complete bidi and varlen work can be fetched from: - git://git.bhalevy.com/open-osd bidi branch (varlen branch is this work) - http://www.bhalevy.com/git - has the gitweb GUI [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-cdb Unlike the scsi approach (see below), I did not want to unify cmd[]/cmd_len and the *varlen_cdb and varlen_cdb_len members of struct request. This is because unlike scsi, block devices do not have a .max_cmd_len parameter to protect them from unexpected large commands. In the case varlen_cdb and varlen_cdb_len are used the cmd[] buffer is ignored and the cmd_len will be set to zero. [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: extended cdb support This is on top of the iscsi branch. In the URL above there are the three missing patches for iscsi, that add support for AHSs. Boaz ^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH 3/4] scsi: varlen extended and vendor-specific cdbs 2007-11-01 17:54 [RFC 0/4] varlen extended and vendor-specific cdbs Boaz Harrosh @ 2007-11-01 18:07 ` Boaz Harrosh 0 siblings, 0 replies; 77+ messages in thread From: Boaz Harrosh @ 2007-11-01 18:07 UTC (permalink / raw) To: James Bottomley, Jens Axboe, Mike Christie, FUJITA Tomonori, linux-scsi Cc: Pete Wyckoff, Benny Halevy Add support for variable-length, extended, and vendor specific CDBs to scsi-ml. It is now possible for initiators and ULD's to issue these types of commands. LLDs need not change much. All they need is to raise the .max_cmd_len to the longest command they support (see iscsi patches). - clean-up some code paths that did not expect commands to be larger than 16, and change cmd_len members' type to short as char is not enough. - Add support for varlen_cdb in scsi_execute. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> --- block/scsi_ioctl.c | 4 ++-- drivers/scsi/constants.c | 10 +++------- drivers/scsi/scsi.c | 22 +++++++++++----------- drivers/scsi/scsi_lib.c | 25 +++++++++++++++++++++---- include/scsi/scsi.h | 40 +++++++++++++++++++++++++++++++++------- include/scsi/scsi_cmnd.h | 2 +- include/scsi/scsi_host.h | 8 +++----- 7 files changed, 74 insertions(+), 37 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 91c7322..f08e196 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -33,13 +33,13 @@ #include <scsi/scsi_cmnd.h> /* Command group 3 is reserved and should never be used. */ -const unsigned char scsi_command_size[8] = +const unsigned char scsi_command_size_tbl[8] = { 6, 10, 10, 12, 16, 12, 10, 10 }; -EXPORT_SYMBOL(scsi_command_size); +EXPORT_SYMBOL(scsi_command_size_tbl); #include <scsi/sg.h> diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 024553f..5edfe0f 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -28,7 +28,6 @@ #define SERVICE_ACTION_OUT_12 0xa9 #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f -#define VARIABLE_LENGTH_CMD 0x7f @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short variable length command, " "len=%d ext_len=%d", len, cdb_len); @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short opcode=0x%x command, len=%d " "ext_len=%d", cdb0, len, cdb_len); @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) int k, len; print_opcode_name(cdb, 0); - if (VARIABLE_LENGTH_CMD == cdb[0]) - len = cdb[7] + 8; - else - len = COMMAND_SIZE(cdb[0]); + len = scsi_command_size(cdb); /* print out all bytes in cdb */ for (k = 0; k < len; ++k) printk(" %02x", cdb[k]); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index e7dd171..6bbc053 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); #define MIN_RESET_PERIOD (15*HZ) /* - * Macro to determine the size of SCSI command. This macro takes vendor - * unique commands into account. SCSI commands in groups 6 and 7 are - * vendor unique and we will depend upon the command length being - * supplied correctly in cmd_len. - */ -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) - -/* * Note - the initial logging level can be set here to log events at boot time. * After the system is up, you may enable logging via the /proc interface. */ @@ -467,6 +458,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)) { @@ -548,9 +540,17 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * Before we queue this command, check if the command * length exceeds what the host adapter can handle. */ - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { + cmd_len = cmd->cmd_len; + if (!cmd_len) { + BUG_ON(cmd->cmnd[0] == VARIABLE_LENGTH_CMD); + cmd_len = COMMAND_SIZE((cmd)->cmnd[0]); + } + + if (cmd_len > cmd->device->host->max_cmd_len) { SCSI_LOG_MLQUEUE(3, - printk("queuecommand : command too long.\n")); + printk("queuecommand : command too long. " + "cdb_size=%d host->max_cmd_len=%d\n", + cmd->cmd_len, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT << 16); scsi_done(cmd); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 0a940f4..c7e38f4 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -190,8 +190,18 @@ 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) { + req->varlen_cdb_len = scsi_varlen_cdb_length(cmd); + req->varlen_cdb = (unsigned char *)cmd; + req->cmd_len = 0; + } 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; @@ -441,7 +451,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) scsi_set_resid(cmd, 0); memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer); 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) @@ -1188,7 +1198,14 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) req->buffer = NULL; } - cmd->cmd_len = req->cmd_len; + if (req->varlen_cdb) { + cmd->cmnd = req->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) diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 702fcfe..43c2ef1 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -11,13 +11,6 @@ #include <linux/types.h> /* - * 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. */ @@ -89,6 +82,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 @@ -116,6 +110,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 { + unsigned char opcode; /* opcode always == VARIABLE_LENGTH_CMD */ + unsigned char control; + unsigned char misc[5]; + unsigned char additional_cdb_length; /* total cdb length - 8 */ + unsigned char service_action[2]; + /* service specific data follows */ +}; + +static inline unsigned +scsi_varlen_cdb_length(const void *hdr) +{ + return ((struct scsi_varlen_cdb_hdr*)hdr)->additional_cdb_length + 8; +} + +extern const unsigned char scsi_command_size_tbl[8]; +#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7] + +static inline unsigned +scsi_command_size(const unsigned char *cmnd) +{ + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? scsi_varlen_cdb_length(cmnd) : + COMMAND_SIZE(cmnd[0]); +} + +/* * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft * T10/1561-D Revision 4 Draft dated 7th November 2002. */ diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 65f5627..7f76413 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -68,7 +68,7 @@ struct scsi_cmnd { int allowed; int timeout_per_command; - unsigned char cmd_len; + unsigned short cmd_len; enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index cb2bcab..35c231c 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -574,13 +574,11 @@ struct Scsi_Host { /* * The maximum length of SCSI commands that this host can accept. * Probably 12 for most host adapters, but could be 16 for others. + * or 260 if the driver supports variable length cdbs. * For drivers that don't set this field, a value of 12 is - * assumed. I am leaving this as a number rather than a bit - * because you never know what subsequent SCSI standards might do - * (i.e. could there be a 20 byte or a 24-byte command a few years - * down the road?). + * assumed. */ - unsigned char max_cmd_len; + unsigned short max_cmd_len; int this_id; int can_queue; -- 1.5.3.1 ^ permalink raw reply related [flat|nested] 77+ messages in thread
end of thread, other threads:[~2008-04-18 17:13 UTC | newest] Thread overview: 77+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-03-25 16:21 [PATCHSET 0/3] Is it time for varlen extended and vendor-specific cdbs Boaz Harrosh 2008-03-25 16:22 ` [PATCH] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh 2008-03-25 16:32 ` [PATCH 2/3] block layer varlen-cdb Boaz Harrosh 2008-04-03 16:43 ` James Bottomley 2008-04-03 17:26 ` Benny Halevy 2008-04-03 18:32 ` [PATCH 2/3 ver2] block layer extended-cdb support Boaz Harrosh 2008-04-04 11:46 ` Jens Axboe 2008-04-06 9:35 ` Boaz Harrosh 2008-04-06 11:05 ` Boaz Harrosh 2008-04-07 8:31 ` Jens Axboe 2008-04-12 5:52 ` FUJITA Tomonori 2008-04-13 9:13 ` Boaz Harrosh 2008-04-13 16:17 ` FUJITA Tomonori 2008-04-13 16:50 ` Boaz Harrosh 2008-04-14 9:49 ` [PATCH 2/3 ver3] " Boaz Harrosh 2008-04-14 11:04 ` FUJITA Tomonori 2008-04-14 11:28 ` Boaz Harrosh 2008-04-14 12:08 ` FUJITA Tomonori 2008-04-14 12:22 ` Boaz Harrosh 2008-04-14 11:04 ` [PATCH 2/3 ver2] " FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 1/4] block: no need to initialize rq->cmd in prepare_flush_fn hook FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 2/4] block: no need to initialize rq->cmd with blk_get_request FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 3/4] block: replace sizeof(rq->cmd) with BLK_MAX_CDB FUJITA Tomonori 2008-04-14 10:50 ` [PATCH 4/4] block: add large command support FUJITA Tomonori 2008-04-14 11:29 ` Jens Axboe 2008-04-14 12:08 ` FUJITA Tomonori 2008-04-15 22:50 ` Bartlomiej Zolnierkiewicz 2008-04-15 22:57 ` FUJITA Tomonori 2008-04-16 0:22 ` Bartlomiej Zolnierkiewicz 2008-04-16 8:33 ` Jens Axboe 2008-04-16 9:08 ` Boaz Harrosh 2008-04-16 9:42 ` Jens Axboe 2008-04-16 22:28 ` Bartlomiej Zolnierkiewicz 2008-04-17 3:59 ` FUJITA Tomonori 2008-04-17 7:07 ` Jens Axboe 2008-04-17 11:55 ` Bartlomiej Zolnierkiewicz 2008-04-17 11:58 ` Bartlomiej Zolnierkiewicz 2008-04-17 12:07 ` FUJITA Tomonori 2008-04-17 4:02 ` FUJITA Tomonori 2008-04-14 14:41 ` Pete Wyckoff 2008-04-14 22:33 ` FUJITA Tomonori 2008-04-15 13:44 ` Pete Wyckoff 2008-04-15 7:45 ` Boaz Harrosh 2008-04-15 10:05 ` FUJITA Tomonori 2008-04-15 7:29 ` Jens Axboe 2008-04-14 11:21 ` [PATCH 0/4] add large command support to the block layer FUJITA Tomonori 2008-04-14 11:38 ` Boaz Harrosh 2008-04-14 12:36 ` Boaz Harrosh 2008-04-14 13:06 ` FUJITA Tomonori 2008-04-15 12:24 ` [PATCH 0/3] scsi: variable-length CDBs support Boaz Harrosh 2008-04-15 12:30 ` [PATCH 1/3] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh 2008-04-15 12:34 ` [PATCH 2/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh 2008-04-16 2:09 ` FUJITA Tomonori 2008-04-16 6:40 ` Boaz Harrosh 2008-04-16 6:49 ` [PATCH 2/3 ver2] " Boaz Harrosh 2008-04-17 4:01 ` [PATCH 2/3] " FUJITA Tomonori 2008-04-17 12:25 ` [PATCH 2/3 ver3] " Boaz Harrosh 2008-04-17 12:49 ` Boaz Harrosh 2008-04-17 13:04 ` FUJITA Tomonori 2008-04-17 13:29 ` Boaz Harrosh 2008-04-15 12:37 ` [PATCH 3/3] iscsi_tcp: Enable large commands Boaz Harrosh 2008-04-15 13:08 ` James Smart 2008-04-15 13:38 ` Boaz Harrosh 2008-04-15 13:57 ` Benny Halevy 2008-04-15 13:46 ` FUJITA Tomonori 2008-04-13 14:07 ` [PATCH 2/3 ver2] block layer extended-cdb support James Bottomley 2008-04-13 16:17 ` FUJITA Tomonori 2008-03-25 16:36 ` [PATCH 3/3] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh 2008-04-03 16:07 ` [PATCHSET 0/3] Is it time for " Boaz Harrosh 2008-04-13 16:30 ` [PATCHSET 0/4 ver2] " Boaz Harrosh 2008-04-13 16:37 ` [PATCH 1/4] Let scsi_cmnd->cmnd use request->cmd buffer Boaz Harrosh 2008-04-13 16:39 ` [PATCH 2/4] block layer extended-cdb support Boaz Harrosh 2008-04-13 16:39 ` [PATCH 3/4] scsi: varlen extended and vendor-specific cdbs Boaz Harrosh 2008-04-13 16:41 ` [PATCH 4/4] iscsi_tcp: Enable large command Boaz Harrosh 2008-04-18 17:11 ` Mike Christie -- strict thread matches above, loose matches on Subject: below -- 2007-11-01 17:54 [RFC 0/4] varlen extended and vendor-specific cdbs Boaz Harrosh 2007-11-01 18:07 ` [PATCH 3/4] scsi: " Boaz Harrosh
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).