[PATCH 1/3] tcm: Add native 32-byte CDB support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux