From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> This patch adds a '#define TCM_MAX_COMMAND_SIZE 32' and converts all inline TCM core and subsystem CDB size defines to use TCM_MAX_COMMAND_SIZE instead of the 16-byte MAX_COMMAND_SIZE. This includes the conversion of MAX_COMMAND_SIZE in certain places to use include/scsi/scsi.h:scsi_command_size() to properly extract the size of a received CDB based on opcode. This patch also includes the conversion of the FILEIO, IBLOCK, PSCSI, RAMDISK and STGT subsystem modules to use TCM_MAX_COMMAND_SIZE for their default internal inline CDB size. It also adds transport_lba_64_ext() and transport_get_sectors_32() callers into target_core_transport.c to be used for extracting a 64-bit logical block address and 32-bit transfer length (in block) from 32-byte CDBs. Finally this patch adds split_cdb_XX_32() and split_cdb_XX_32() for handling the generation of 32-byte CDBs for individual struct se_task. Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx> --- drivers/target/target_core_file.h | 2 +- drivers/target/target_core_iblock.h | 2 +- drivers/target/target_core_pscsi.c | 2 +- drivers/target/target_core_pscsi.h | 2 +- drivers/target/target_core_rd.h | 2 +- drivers/target/target_core_scdb.c | 38 +++++++++++++++++++++++++++ drivers/target/target_core_scdb.h | 2 + drivers/target/target_core_stgt.h | 2 +- drivers/target/target_core_transport.c | 44 ++++++++++++++++++++++++++++--- include/target/target_core_base.h | 13 +++++++++ 10 files changed, 98 insertions(+), 11 deletions(-) diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h index 7831034..35726f1 100644 --- a/drivers/target/target_core_file.h +++ b/drivers/target/target_core_file.h @@ -26,7 +26,7 @@ extern int linux_blockdevice_check(int, int); struct fd_request { /* SCSI CDB from iSCSI Command PDU */ - unsigned char fd_scsi_cdb[MAX_COMMAND_SIZE]; + unsigned char fd_scsi_cdb[TCM_MAX_COMMAND_SIZE]; /* Data Direction */ u8 fd_data_direction; /* Total length of request */ diff --git a/drivers/target/target_core_iblock.h b/drivers/target/target_core_iblock.h index 76c39a9..3582aac 100644 --- a/drivers/target/target_core_iblock.h +++ b/drivers/target/target_core_iblock.h @@ -12,7 +12,7 @@ extern struct se_global *se_global; struct iblock_req { - unsigned char ib_scsi_cdb[MAX_COMMAND_SIZE]; + unsigned char ib_scsi_cdb[TCM_MAX_COMMAND_SIZE]; atomic_t ib_bio_cnt; u32 ib_sg_count; void *ib_buf; diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 803853d..beca807 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -743,7 +743,7 @@ static inline void pscsi_blk_init_request( * Load the referenced struct se_task's SCSI CDB into * include/linux/blkdev.h:struct request->cmd */ - pt->pscsi_req->cmd_len = COMMAND_SIZE(pt->pscsi_cdb[0]); + pt->pscsi_req->cmd_len = scsi_command_size(pt->pscsi_cdb); memcpy(pt->pscsi_req->cmd, pt->pscsi_cdb, pt->pscsi_req->cmd_len); /* * Setup pointer for outgoing sense data. diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h index db09d6a..086e6f1 100644 --- a/drivers/target/target_core_pscsi.h +++ b/drivers/target/target_core_pscsi.h @@ -28,7 +28,7 @@ extern int linux_blockdevice_check(int, int); #include <linux/kobject.h> struct pscsi_plugin_task { - unsigned char pscsi_cdb[MAX_COMMAND_SIZE]; + unsigned char pscsi_cdb[TCM_MAX_COMMAND_SIZE]; unsigned char pscsi_sense[SCSI_SENSE_BUFFERSIZE]; int pscsi_direction; int pscsi_result; diff --git a/drivers/target/target_core_rd.h b/drivers/target/target_core_rd.h index 8170b41..2008807 100644 --- a/drivers/target/target_core_rd.h +++ b/drivers/target/target_core_rd.h @@ -31,7 +31,7 @@ void rd_module_exit(void); struct rd_request { /* SCSI CDB from iSCSI Command PDU */ - unsigned char rd_scsi_cdb[MAX_COMMAND_SIZE]; + unsigned char rd_scsi_cdb[TCM_MAX_COMMAND_SIZE]; /* Data Direction */ u8 rd_data_direction; /* Total length of request */ diff --git a/drivers/target/target_core_scdb.c b/drivers/target/target_core_scdb.c index 8bcfeaf..76a7de0 100644 --- a/drivers/target/target_core_scdb.c +++ b/drivers/target/target_core_scdb.c @@ -28,6 +28,7 @@ #include <linux/net.h> #include <linux/string.h> +#include <scsi/scsi.h> #include <target/target_core_base.h> #include <target/target_core_transport.h> @@ -147,3 +148,40 @@ void split_cdb_RW_16( cdb[0] = (rw) ? 0x8a : 0x88; split_cdb_XX_16(lba, sectors, &cdb[0]); } + +/* + * split_cdb_XX_32(): + * + * 64-bit LBA w/ 32-bit SECTORS such as READ_32, WRITE_32 and XDWRITEREAD_32 + */ +void split_cdb_XX_32( + unsigned long long lba, + u32 *sectors, + unsigned char *cdb) +{ + cdb[12] = (lba >> 56) & 0xff; + cdb[13] = (lba >> 48) & 0xff; + cdb[14] = (lba >> 40) & 0xff; + cdb[15] = (lba >> 32) & 0xff; + cdb[16] = (lba >> 24) & 0xff; + cdb[17] = (lba >> 16) & 0xff; + cdb[18] = (lba >> 8) & 0xff; + cdb[19] = lba & 0xff; + cdb[28] = (*sectors >> 24) & 0xff; + cdb[29] = (*sectors >> 16) & 0xff; + cdb[30] = (*sectors >> 8) & 0xff; + cdb[31] = *sectors & 0xff; +} + +void split_cdb_RW_32( + unsigned long long lba, + u32 *sectors, + unsigned char *cdb, + int rw) +{ + /* + * Set service action for VARIABLE_LENGTH_CMD + */ + cdb[9] = (rw) ? WRITE_32 : READ_32; + split_cdb_XX_32(lba, sectors, &cdb[0]); +} diff --git a/drivers/target/target_core_scdb.h b/drivers/target/target_core_scdb.h index 57688e2..1b0dc74 100644 --- a/drivers/target/target_core_scdb.h +++ b/drivers/target/target_core_scdb.h @@ -9,5 +9,7 @@ extern void split_cdb_XX_12(unsigned long long, u32 *, unsigned char *); extern void split_cdb_RW_12(unsigned long long, u32 *, unsigned char *, int); extern void split_cdb_XX_16(unsigned long long, u32 *, unsigned char *); extern void split_cdb_RW_16(unsigned long long, u32 *, unsigned char *, int); +extern void split_cdb_XX_32(unsigned long long, u32 *, unsigned char *); +extern void split_cdb_RW_32(unsigned long long, u32 *, unsigned char *, int); #endif /* TARGET_CORE_SCDB_H */ diff --git a/drivers/target/target_core_stgt.h b/drivers/target/target_core_stgt.h index b82300c..8582776 100644 --- a/drivers/target/target_core_stgt.h +++ b/drivers/target/target_core_stgt.h @@ -23,7 +23,7 @@ extern int linux_blockdevice_check(int, int); #include <linux/kobject.h> struct stgt_plugin_task { - unsigned char stgt_cdb[MAX_COMMAND_SIZE]; + unsigned char stgt_cdb[TCM_MAX_COMMAND_SIZE]; unsigned char stgt_sense[SCSI_SENSE_BUFFERSIZE]; int stgt_direction; int stgt_result; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 49d5946..a3016f7 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2636,7 +2636,8 @@ static int transport_process_control_sg_transform( cdb = TRANSPORT(dev)->get_cdb(task); if (cdb) - memcpy(cdb, T_TASK(cmd)->t_task_cdb, MAX_COMMAND_SIZE); + memcpy(cdb, T_TASK(cmd)->t_task_cdb, + scsi_command_size(T_TASK(cmd)->t_task_cdb)); task->task_size = cmd->data_length; task->task_sg_num = 1; @@ -2677,7 +2678,8 @@ static int transport_process_control_nonsg_transform( cdb = TRANSPORT(dev)->get_cdb(task); if (cdb) - memcpy(cdb, T_TASK(cmd)->t_task_cdb, MAX_COMMAND_SIZE); + memcpy(cdb, T_TASK(cmd)->t_task_cdb, + scsi_command_size(T_TASK(cmd)->t_task_cdb)); task->task_size = cmd->data_length; task->task_sg_num = 0; @@ -2711,7 +2713,8 @@ static int transport_process_non_data_transform( cdb = TRANSPORT(dev)->get_cdb(task); if (cdb) - memcpy(cdb, T_TASK(cmd)->t_task_cdb, MAX_COMMAND_SIZE); + memcpy(cdb, T_TASK(cmd)->t_task_cdb, + scsi_command_size(T_TASK(cmd)->t_task_cdb)); task->task_size = cmd->data_length; task->task_sg_num = 0; @@ -2902,7 +2905,7 @@ int transport_generic_allocate_tasks( /* * Copy the original CDB into T_TASK(cmd). */ - memcpy(T_TASK(cmd)->t_task_cdb, cdb, MAX_COMMAND_SIZE); + memcpy(T_TASK(cmd)->t_task_cdb, cdb, scsi_command_size(cdb)); /* * Check for SAM Task Attribute Emulation */ @@ -3829,6 +3832,19 @@ static inline unsigned long long transport_lba_64(unsigned char *cdb) return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; } +/* + * For VARIABLE_LENGTH_CDB w/ 32 byte extended CDBs + */ +static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) +{ + unsigned int __v1, __v2; + + __v1 = (cdb[12] << 24) | (cdb[13] << 16) | (cdb[14] << 8) | cdb[15]; + __v2 = (cdb[16] << 24) | (cdb[17] << 16) | (cdb[18] << 8) | cdb[19]; + + return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; +} + /* transport_set_supported_SAM_opcode(): * * @@ -4370,6 +4386,23 @@ type_disk: (cdb[12] << 8) + cdb[13]; } +/* + * Used for VARIABLE_LENGTH_CDB WRITE_32 and READ_32 variants + */ +static inline u32 transport_get_sectors_32( + unsigned char *cdb, + struct se_cmd *cmd, + int *ret) +{ + /* + * Assume TYPE_DISK for non struct se_device objects. + * Use 32-bit sector value. + */ + return (u32)(cdb[28] << 24) + (cdb[29] << 16) + + (cdb[30] << 8) + cdb[31]; + +} + static inline u32 transport_get_size( u32 sectors, unsigned char *cdb, @@ -7496,7 +7529,8 @@ u32 transport_generic_get_cdb_count( cdb = TRANSPORT(dev)->get_cdb(task); if ((cdb)) { - memcpy(cdb, T_TASK(cmd)->t_task_cdb, MAX_COMMAND_SIZE); + memcpy(cdb, T_TASK(cmd)->t_task_cdb, + scsi_command_size(T_TASK(cmd)->t_task_cdb)); cmd->transport_split_cdb(task->task_lba, &task->task_sectors, cdb); } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 97e9715..eb0a228 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -17,6 +17,19 @@ /* Maximum Number of LUNs per Target Portal Group */ #define TRANSPORT_MAX_LUNS_PER_TPG 256 /* + * By default we use 32-byte CDBs in TCM Core and subsystem plugin code. + * + * Note that both include/scsi/scsi_cmnd.h:MAX_COMMAND_SIZE and + * include/linux/blkdev.h:BLOCK_MAX_CDB as of v2.6.36-rc4 still use + * 16-byte CDBs by default and require an extra allocation for + * 32-byte CDBs to becasue of legacy issues. + * + * Within TCM Core there are no such legacy limitiations, so we go ahead + * use 32-byte CDBs by default and use include/scsi/scsi.h:scsi_command_size() + * within all TCM Core and subsystem plugin code. + */ +#define TCM_MAX_COMMAND_SIZE 32 +/* * From include/scsi/scsi_cmnd.h:SCSI_SENSE_BUFFERSIZE, currently * defined 96, but the real limit is 252 (or 260 including the header) */ -- 1.5.6.5 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html