[PATCH 7/8] pscsi: stop parsing most commands

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

 



For pscsi we just pass the commands down to the lower level SCSI device,
so we don't need to do any LBA/range checks.  Stop parsing any of that
information in the pscsi driver and thus allow it to pass through arbitrary
commands.

Signed-off-by: Christoph Hellwig <hch@xxxxxx>

---
 drivers/target/target_core_internal.h  |    1 
 drivers/target/target_core_pscsi.c     |  492 ++-------------------------------
 drivers/target/target_core_sbc.c       |   37 +-
 drivers/target/target_core_spc.c       |   17 -
 drivers/target/target_core_transport.c |   47 ---
 include/target/target_core_backend.h   |    6 
 6 files changed, 71 insertions(+), 529 deletions(-)

Index: lio-core/drivers/target/target_core_transport.c
===================================================================
--- lio-core.orig/drivers/target/target_core_transport.c	2012-05-20 16:52:16.926610206 +0200
+++ lio-core/drivers/target/target_core_transport.c	2012-05-20 16:53:28.094612031 +0200
@@ -1343,7 +1343,7 @@ static inline void transport_generic_pre
 	}
 }
 
-static int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
+int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
 {
 	struct se_device *dev = cmd->se_dev;
 
@@ -1469,7 +1469,6 @@ int target_setup_cmd_from_cdb(
 	u32 pr_reg_type = 0;
 	u8 alua_ascq = 0;
 	unsigned long flags;
-	unsigned int size;
 	int ret;
 
 	transport_generic_prepare_cdb(cdb);
@@ -1561,11 +1560,7 @@ int target_setup_cmd_from_cdb(
 		 */
 	}
 
-	ret = cmd->se_dev->transport->parse_cdb(cmd, &size);
-	if (ret < 0)
-		return ret;
-
-	ret = target_cmd_size_check(cmd, size);
+	ret = cmd->se_dev->transport->parse_cdb(cmd);
 	if (ret < 0)
 		return ret;
 
@@ -2163,32 +2158,6 @@ out:
 	return -1;
 }
 
-static inline long long transport_dev_end_lba(struct se_device *dev)
-{
-	return dev->transport->get_blocks(dev) + 1;
-}
-
-static int transport_cmd_get_valid_sectors(struct se_cmd *cmd)
-{
-	struct se_device *dev = cmd->se_dev;
-	u32 sectors;
-
-	if (dev->transport->get_device_type(dev) != TYPE_DISK)
-		return 0;
-
-	sectors = (cmd->data_length / dev->se_sub_dev->se_dev_attrib.block_size);
-
-	if ((cmd->t_task_lba + sectors) > transport_dev_end_lba(dev)) {
-		pr_err("LBA: %llu Sectors: %u exceeds"
-			" transport_dev_end_lba(): %llu\n",
-			cmd->t_task_lba, sectors,
-			transport_dev_end_lba(dev));
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 /*
  * Called from I/O completion to determine which dormant/delayed
  * and ordered cmds need to have their tasks added to the execution queue.
@@ -2632,7 +2601,6 @@ out:
  */
 int transport_generic_new_cmd(struct se_cmd *cmd)
 {
-	struct se_device *dev = cmd->se_dev;
 	int ret = 0;
 
 	/*
@@ -2666,17 +2634,6 @@ int transport_generic_new_cmd(struct se_
 		return 0;
 	}
 
-	if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
-		struct se_dev_attrib *attr = &dev->se_sub_dev->se_dev_attrib;
-
-		if (transport_cmd_get_valid_sectors(cmd) < 0)
-			return -EINVAL;
-
-		BUG_ON(cmd->data_length % attr->block_size);
-		BUG_ON(DIV_ROUND_UP(cmd->data_length, attr->block_size) >
-			attr->hw_max_sectors);
-	}
-
 	atomic_inc(&cmd->t_fe_count);
 
 	/*
Index: lio-core/drivers/target/target_core_sbc.c
===================================================================
--- lio-core.orig/drivers/target/target_core_sbc.c	2012-05-20 16:52:19.000000000 +0200
+++ lio-core/drivers/target/target_core_sbc.c	2012-05-20 16:53:28.094612031 +0200
@@ -395,11 +395,12 @@ out:
 	kfree(buf);
 }
 
-int sbc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
+int sbc_parse_cdb(struct se_cmd *cmd)
 {
 	struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
 	struct se_device *dev = cmd->se_dev;
 	unsigned char *cdb = cmd->t_task_cdb;
+	unsigned int size;
 	u32 sectors = 0;
 	int ret;
 
@@ -497,7 +498,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 				goto out_invalid_cdb_field;
 			}
 
-			*size = sbc_get_size(cmd, 1);
+			size = sbc_get_size(cmd, 1);
 			cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
 
 			if (sbc_write_same_supported(dev, &cdb[10]) < 0)
@@ -512,7 +513,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 		break;
 	}
 	case READ_CAPACITY:
-		*size = READ_CAP_LEN;
+		size = READ_CAP_LEN;
 		cmd->execute_cmd = sbc_emulate_readcapacity;
 		break;
 	case SERVICE_ACTION_IN:
@@ -525,7 +526,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 				cmd->t_task_cdb[1] & 0x1f);
 			goto out_invalid_cdb_field;
 		}
-		*size = (cdb[10] << 24) | (cdb[11] << 16) |
+		size = (cdb[10] << 24) | (cdb[11] << 16) |
 		       (cdb[12] << 8) | cdb[13];
 		break;
 	case SYNCHRONIZE_CACHE:
@@ -541,7 +542,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 			cmd->t_task_lba = transport_lba_64(cdb);
 		}
 
-		*size = sbc_get_size(cmd, sectors);
+		size = sbc_get_size(cmd, sectors);
 
 		/*
 		 * Check to ensure that LBA + Range does not exceed past end of
@@ -554,7 +555,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 		cmd->execute_cmd = sbc_emulate_synchronize_cache;
 		break;
 	case UNMAP:
-		*size = get_unaligned_be16(&cdb[7]);
+		size = get_unaligned_be16(&cdb[7]);
 		cmd->execute_cmd = sbc_emulate_unmap;
 		break;
 	case WRITE_SAME_16:
@@ -564,7 +565,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 			goto out_invalid_cdb_field;
 		}
 
-		*size = sbc_get_size(cmd, 1);
+		size = sbc_get_size(cmd, 1);
 		cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
 
 		if (sbc_write_same_supported(dev, &cdb[1]) < 0)
@@ -578,7 +579,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 			goto out_invalid_cdb_field;
 		}
 
-		*size = sbc_get_size(cmd, 1);
+		size = sbc_get_size(cmd, 1);
 		cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
 
 		/*
@@ -590,11 +591,11 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 		cmd->execute_cmd = sbc_emulate_write_same;
 		break;
 	case VERIFY:
-		*size = 0;
+		size = 0;
 		cmd->execute_cmd = sbc_emulate_verify;
 		break;
 	default:
-		ret = spc_parse_cdb(cmd, size, false);
+		ret = spc_parse_cdb(cmd, &size);
 		if (ret)
 			return ret;
 	}
@@ -604,6 +605,8 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 		goto out_unsupported_cdb;
 
 	if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
+		unsigned long long end_lba;
+
 		if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) {
 			printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
 				" big sectors %u exceeds fabric_max_sectors:"
@@ -619,9 +622,21 @@ int sbc_parse_cdb(struct se_cmd *cmd, un
 			goto out_invalid_cdb_field;
 		}
 
-		*size = sbc_get_size(cmd, sectors);
+		end_lba = dev->transport->get_blocks(dev) + 1;
+		if (cmd->t_task_lba + sectors > end_lba) {
+			pr_err("cmd exceeds last lba %llu "
+				"(lba %llu, sectors %u)\n",
+				end_lba, cmd->t_task_lba, sectors);
+			goto out_invalid_cdb_field;
+		}
+
+		size = sbc_get_size(cmd, sectors);
 	}
 
+	ret = target_cmd_size_check(cmd, size);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 
 out_unsupported_cdb:
Index: lio-core/drivers/target/target_core_pscsi.c
===================================================================
--- lio-core.orig/drivers/target/target_core_pscsi.c	2012-05-20 16:52:16.000000000 +0200
+++ lio-core/drivers/target/target_core_pscsi.c	2012-05-20 16:53:28.094612031 +0200
@@ -1022,304 +1022,36 @@ fail:
 	return -ENOMEM;
 }
 
-static inline u32 pscsi_get_sectors_6(
-	unsigned char *cdb,
-	struct se_cmd *cmd,
-	int *ret)
-{
-	struct se_device *dev = cmd->se_dev;
-
-	/*
-	 * Assume TYPE_DISK for non struct se_device objects.
-	 * Use 8-bit sector value.
-	 */
-	if (!dev)
-		goto type_disk;
-
-	/*
-	 * Use 24-bit allocation length for TYPE_TAPE.
-	 */
-	if (dev->transport->get_device_type(dev) == TYPE_TAPE)
-		return (u32)(cdb[2] << 16) + (cdb[3] << 8) + cdb[4];
-
-	/*
-	 * Everything else assume TYPE_DISK Sector CDB location.
-	 * Use 8-bit sector value.  SBC-3 says:
-	 *
-	 *   A TRANSFER LENGTH field set to zero specifies that 256
-	 *   logical blocks shall be written.  Any other value
-	 *   specifies the number of logical blocks that shall be
-	 *   written.
-	 */
-type_disk:
-	return cdb[4] ? : 256;
-}
-
-static inline u32 pscsi_get_sectors_10(
-	unsigned char *cdb,
-	struct se_cmd *cmd,
-	int *ret)
-{
-	struct se_device *dev = cmd->se_dev;
-
-	/*
-	 * Assume TYPE_DISK for non struct se_device objects.
-	 * Use 16-bit sector value.
-	 */
-	if (!dev)
-		goto type_disk;
-
-	/*
-	 * XXX_10 is not defined in SSC, throw an exception
-	 */
-	if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
-		*ret = -EINVAL;
-		return 0;
-	}
-
-	/*
-	 * Everything else assume TYPE_DISK Sector CDB location.
-	 * Use 16-bit sector value.
-	 */
-type_disk:
-	return (u32)(cdb[7] << 8) + cdb[8];
-}
-
-static inline u32 pscsi_get_sectors_12(
-	unsigned char *cdb,
-	struct se_cmd *cmd,
-	int *ret)
-{
-	struct se_device *dev = cmd->se_dev;
-
-	/*
-	 * Assume TYPE_DISK for non struct se_device objects.
-	 * Use 32-bit sector value.
-	 */
-	if (!dev)
-		goto type_disk;
-
-	/*
-	 * XXX_12 is not defined in SSC, throw an exception
-	 */
-	if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
-		*ret = -EINVAL;
-		return 0;
-	}
-
-	/*
-	 * Everything else assume TYPE_DISK Sector CDB location.
-	 * Use 32-bit sector value.
-	 */
-type_disk:
-	return (u32)(cdb[6] << 24) + (cdb[7] << 16) + (cdb[8] << 8) + cdb[9];
-}
-
-static inline u32 pscsi_get_sectors_16(
-	unsigned char *cdb,
-	struct se_cmd *cmd,
-	int *ret)
-{
-	struct se_device *dev = cmd->se_dev;
-
-	/*
-	 * Assume TYPE_DISK for non struct se_device objects.
-	 * Use 32-bit sector value.
-	 */
-	if (!dev)
-		goto type_disk;
-
-	/*
-	 * Use 24-bit allocation length for TYPE_TAPE.
-	 */
-	if (dev->transport->get_device_type(dev) == TYPE_TAPE)
-		return (u32)(cdb[12] << 16) + (cdb[13] << 8) + cdb[14];
-
-type_disk:
-	return (u32)(cdb[10] << 24) + (cdb[11] << 16) +
-		    (cdb[12] << 8) + cdb[13];
-}
-
-/*
- * Used for VARIABLE_LENGTH_CDB WRITE_32 and READ_32 variants
- */
-static inline u32 pscsi_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 pscsi_get_lba_21(unsigned char *cdb)
-{
-	return ((cdb[1] & 0x1f) << 16) | (cdb[2] << 8) | cdb[3];
-}
-
-static inline u32 pscsi_get_lba_32(unsigned char *cdb)
-{
-	return (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
-}
-
-static inline unsigned long long pscsi_get_lba_64(unsigned char *cdb)
-{
-	unsigned int __v1, __v2;
-
-	__v1 = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
-	__v2 = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
-
-	return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
-}
-
-/*
- * For VARIABLE_LENGTH_CDB w/ 32 byte extended CDBs
- */
-static inline unsigned long long pscsi_get_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;
-}
-
-
-static inline u32 pscsi_get_size(
-	u32 sectors,
-	unsigned char *cdb,
-	struct se_cmd *cmd)
-{
-	struct se_device *dev = cmd->se_dev;
-
-	if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
-		if (cdb[1] & 1) { /* sectors */
-			return dev->se_sub_dev->se_dev_attrib.block_size * sectors;
-		} else /* bytes */
-			return sectors;
-	}
-
-	pr_debug("Returning block_size: %u, sectors: %u == %u for"
-		" %s object\n", dev->se_sub_dev->se_dev_attrib.block_size,
-		sectors, dev->se_sub_dev->se_dev_attrib.block_size * sectors,
-		dev->transport->name);
-
-	return dev->se_sub_dev->se_dev_attrib.block_size * sectors;
-}
-
-static int pscsi_parse_cdb(struct se_cmd *cmd, unsigned int *size)
+static int pscsi_parse_cdb(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	unsigned char *cdb = cmd->t_task_cdb;
-	int sector_ret = 0;
-	u32 sectors = 0;
-	u16 service_action;
+	unsigned int dummy_size;
 	int ret;
 
-	if (cmd->se_cmd_flags & SCF_BIDI)
-		goto out_unsupported_cdb;
+	if (cmd->se_cmd_flags & SCF_BIDI) {
+		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+		return -EINVAL;
+	}
 
+	/*
+	 * For REPORT LUNS we always need to emulate the respone, and for everything
+	 * related to persistent reservations and ALUA we might optionally use our
+	 * handlers before passing on the command to the physical hardware.
+	 */
 	switch (cdb[0]) {
-	case READ_6:
-		sectors = pscsi_get_sectors_6(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-		*size = pscsi_get_size(sectors, cdb, cmd);
-		cmd->t_task_lba = pscsi_get_lba_21(cdb);
-		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
-		break;
-	case READ_10:
-		sectors = pscsi_get_sectors_10(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-		*size = pscsi_get_size(sectors, cdb, cmd);
-		cmd->t_task_lba = pscsi_get_lba_32(cdb);
-		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
-		break;
-	case READ_12:
-		sectors = pscsi_get_sectors_12(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-		*size = pscsi_get_size(sectors, cdb, cmd);
-		cmd->t_task_lba = pscsi_get_lba_32(cdb);
-		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
-		break;
-	case READ_16:
-		sectors = pscsi_get_sectors_16(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-		*size = pscsi_get_size(sectors, cdb, cmd);
-		cmd->t_task_lba = pscsi_get_lba_64(cdb);
-		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
-		break;
-	case WRITE_6:
-		sectors = pscsi_get_sectors_6(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-		*size = pscsi_get_size(sectors, cdb, cmd);
-		cmd->t_task_lba = pscsi_get_lba_21(cdb);
-		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
-		break;
-	case WRITE_10:
-	case WRITE_VERIFY:
-		sectors = pscsi_get_sectors_10(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-		*size = pscsi_get_size(sectors, cdb, cmd);
-		cmd->t_task_lba = pscsi_get_lba_32(cdb);
-		if (cdb[1] & 0x8)
-			cmd->se_cmd_flags |= SCF_FUA;
-		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
-		break;
-	case WRITE_12:
-		sectors = pscsi_get_sectors_12(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-		*size = pscsi_get_size(sectors, cdb, cmd);
-		cmd->t_task_lba = pscsi_get_lba_32(cdb);
-		if (cdb[1] & 0x8)
-			cmd->se_cmd_flags |= SCF_FUA;
-		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
-		break;
-	case WRITE_16:
-		sectors = pscsi_get_sectors_16(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-		*size = pscsi_get_size(sectors, cdb, cmd);
-		cmd->t_task_lba = pscsi_get_lba_64(cdb);
-		if (cdb[1] & 0x8)
-			cmd->se_cmd_flags |= SCF_FUA;
-		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
-		break;
-	case VARIABLE_LENGTH_CMD:
-		service_action = get_unaligned_be16(&cdb[8]);
-		switch (service_action) {
-		case WRITE_SAME_32:
-			sectors = pscsi_get_sectors_32(cdb, cmd, &sector_ret);
-			if (sector_ret)
-				goto out_unsupported_cdb;
-
-			if (!sectors) {
-				pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
-				       " supported\n");
-				goto out_invalid_cdb_field;
-			}
-
-			*size = pscsi_get_size(1, cdb, cmd);
-			cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
-			break;
-		default:
-			pr_err("VARIABLE_LENGTH_CMD service action"
-				" 0x%04x not supported\n", service_action);
-			goto out_unsupported_cdb;
-		}
+	case REPORT_LUNS:
+	case PERSISTENT_RESERVE_IN:
+	case PERSISTENT_RESERVE_OUT:
+	case RELEASE:
+	case RELEASE_10:
+	case RESERVE:
+	case RESERVE_10:
+		ret = spc_parse_cdb(cmd, &dummy_size);
+		if (ret)
+			return ret;
 		break;
 	case MAINTENANCE_IN:
 		if (dev->transport->get_device_type(dev) != TYPE_ROM) {
@@ -1332,33 +1064,8 @@ static int pscsi_parse_cdb(struct se_cmd
 				cmd->execute_cmd =
 					target_emulate_report_target_port_groups;
 			}
-			*size = (cdb[6] << 24) | (cdb[7] << 16) |
-			       (cdb[8] << 8) | cdb[9];
-		} else {
-			/* GPCMD_SEND_KEY from multi media commands */
-			*size = (cdb[8] << 8) + cdb[9];
 		}
 		break;
-	case GPCMD_READ_BUFFER_CAPACITY:
-	case GPCMD_SEND_OPC:
-		*size = (cdb[7] << 8) + cdb[8];
-		break;
-	case READ_BLOCK_LIMITS:
-		*size = READ_BLOCK_LEN;
-		break;
-	case GPCMD_GET_CONFIGURATION:
-	case GPCMD_READ_FORMAT_CAPACITIES:
-	case GPCMD_READ_DISC_INFO:
-	case GPCMD_READ_TRACK_RZONE_INFO:
-		*size = (cdb[7] << 8) + cdb[8];
-		break;
-	case GPCMD_MECHANISM_STATUS:
-	case GPCMD_READ_DVD_STRUCTURE:
-		*size = (cdb[8] << 8) + cdb[9];
-		break;
-	case READ_POSITION:
-		*size = READ_POSITION_LEN;
-		break;
 	case MAINTENANCE_OUT:
 		if (dev->transport->get_device_type(dev) != TYPE_ROM) {
 			/* MAINTENANCE_OUT from SCC-2
@@ -1370,159 +1077,26 @@ static int pscsi_parse_cdb(struct se_cmd
 				cmd->execute_cmd =
 					target_emulate_set_target_port_groups;
 			}
-
-			*size = (cdb[6] << 24) | (cdb[7] << 16) |
-			       (cdb[8] << 8) | cdb[9];
-		} else  {
-			/* GPCMD_REPORT_KEY from multi media commands */
-			*size = (cdb[8] << 8) + cdb[9];
 		}
 		break;
-	case READ_BUFFER:
-		*size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
-		break;
-	case READ_CAPACITY:
-		*size = READ_CAP_LEN;
-		break;
-	case READ_MEDIA_SERIAL_NUMBER:
-	case SERVICE_ACTION_IN:
-	case ACCESS_CONTROL_IN:
-	case ACCESS_CONTROL_OUT:
-		*size = (cdb[10] << 24) | (cdb[11] << 16) |
-		       (cdb[12] << 8) | cdb[13];
-		break;
-	case READ_TOC:
-		*size = cdb[8];
-		break;
-	case READ_ELEMENT_STATUS:
-		*size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9];
-		break;
-	case SYNCHRONIZE_CACHE:
-	case SYNCHRONIZE_CACHE_16:
-		/*
-		 * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
-		 */
-		if (cdb[0] == SYNCHRONIZE_CACHE) {
-			sectors = pscsi_get_sectors_10(cdb, cmd, &sector_ret);
-			cmd->t_task_lba = pscsi_get_lba_32(cdb);
-		} else {
-			sectors = pscsi_get_sectors_16(cdb, cmd, &sector_ret);
-			cmd->t_task_lba = pscsi_get_lba_64(cdb);
-		}
-		if (sector_ret)
-			goto out_unsupported_cdb;
-
-		*size = pscsi_get_size(sectors, cdb, cmd);
-		break;
-	case UNMAP:
-		*size = get_unaligned_be16(&cdb[7]);
-		break;
-	case WRITE_SAME_16:
-		sectors = pscsi_get_sectors_16(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-
-		if (!sectors) {
-			pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
-			goto out_invalid_cdb_field;
-		}
-
-		*size = pscsi_get_size(1, cdb, cmd);
-		cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
-		break;
-	case WRITE_SAME:
-		sectors = pscsi_get_sectors_10(cdb, cmd, &sector_ret);
-		if (sector_ret)
-			goto out_unsupported_cdb;
-
-		if (!sectors) {
-			pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
-			goto out_invalid_cdb_field;
-		}
-
-		*size = pscsi_get_size(1, cdb, cmd);
-		cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
-		break;
-	case ALLOW_MEDIUM_REMOVAL:
-	case ERASE:
-	case REZERO_UNIT:
-	case SEEK_10:
-	case SPACE:
-	case START_STOP:
-	case VERIFY:
-	case WRITE_FILEMARKS:
-	case GPCMD_CLOSE_TRACK:
-	case INITIALIZE_ELEMENT_STATUS:
-	case GPCMD_LOAD_UNLOAD:
-	case GPCMD_SET_SPEED:
-	case MOVE_MEDIUM:
-		*size = 0;
-		break;
-	case GET_EVENT_STATUS_NOTIFICATION:
-		*size = (cdb[7] << 8) | cdb[8];
-		break;
-	case ATA_16:
-		switch (cdb[2] & 0x3) {		/* T_LENGTH */
-		case 0x0:
-			sectors = 0;
-			break;
-		case 0x1:
-			sectors = (((cdb[1] & 0x1) ? cdb[3] : 0) << 8) | cdb[4];
-			break;
-		case 0x2:
-			sectors = (((cdb[1] & 0x1) ? cdb[5] : 0) << 8) | cdb[6];
-			break;
-		case 0x3:
-			pr_err("T_LENGTH=0x3 not supported for ATA_16\n");
-			goto out_invalid_cdb_field;
-		}
-
-		/* BYTE_BLOCK */
-		if (cdb[2] & 0x4) {
-			/* BLOCK T_TYPE: 512 or sector */
-			*size = sectors * ((cdb[2] & 0x10) ?
-				dev->se_sub_dev->se_dev_attrib.block_size : 512);
-		} else {
-			/* BYTE */
-			*size = sectors;
-		}
+	case READ_6:
+	case READ_10:
+	case READ_12:
+	case READ_16:
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_12:
+	case WRITE_16:
+	case WRITE_VERIFY:
+		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
 		break;
 	default:
-		ret = spc_parse_cdb(cmd, size, true);
-		if (ret)
-			return ret;
-	}
-
-	if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
-		if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) {
-			printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
-				" big sectors %u exceeds fabric_max_sectors:"
-				" %u\n", cdb[0], sectors,
-				su_dev->se_dev_attrib.fabric_max_sectors);
-			goto out_invalid_cdb_field;
-		}
-		if (sectors > su_dev->se_dev_attrib.hw_max_sectors) {
-			printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
-				" big sectors %u exceeds backend hw_max_sectors:"
-				" %u\n", cdb[0], sectors,
-				su_dev->se_dev_attrib.hw_max_sectors);
-			goto out_invalid_cdb_field;
-		}
+		break;
 	}
 
 	return 0;
-
-out_unsupported_cdb:
-	cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-	cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-	return -EINVAL;
-out_invalid_cdb_field:
-	cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-	cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-	return -EINVAL;
 }
 
-
 static int pscsi_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
 		u32 sgl_nents, enum dma_data_direction data_direction)
 {
Index: lio-core/include/target/target_core_backend.h
===================================================================
--- lio-core.orig/include/target/target_core_backend.h	2012-05-20 16:52:16.000000000 +0200
+++ lio-core/include/target/target_core_backend.h	2012-05-20 16:53:28.098612029 +0200
@@ -25,7 +25,7 @@ struct se_subsystem_api {
 	void (*free_device)(void *);
 	int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *);
 
-	int (*parse_cdb)(struct se_cmd *cmd, unsigned int *size);
+	int (*parse_cdb)(struct se_cmd *cmd);
 	int (*execute_cmd)(struct se_cmd *, struct scatterlist *, u32,
 			enum dma_data_direction);
 	int (*do_discard)(struct se_device *, sector_t, u32);
@@ -51,8 +51,8 @@ struct se_device *transport_add_device_t
 
 void	target_complete_cmd(struct se_cmd *, u8);
 
-int	sbc_parse_cdb(struct se_cmd *cmd, unsigned int *size);
-int	spc_parse_cdb(struct se_cmd *cmd, unsigned int *size, bool passthrough);
+int	sbc_parse_cdb(struct se_cmd *cmd);
+int	spc_parse_cdb(struct se_cmd *cmd, unsigned int *size);
 
 void	transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
 int	transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
Index: lio-core/drivers/target/target_core_internal.h
===================================================================
--- lio-core.orig/drivers/target/target_core_internal.h	2012-05-20 16:52:19.000000000 +0200
+++ lio-core/drivers/target/target_core_internal.h	2012-05-20 16:53:28.098612029 +0200
@@ -103,6 +103,7 @@ int	transport_dump_vpd_ident(struct t10_
 bool	target_stop_cmd(struct se_cmd *cmd, unsigned long *flags);
 int	transport_clear_lun_from_sessions(struct se_lun *);
 void	transport_send_task_abort(struct se_cmd *);
+int	target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
 
 /* target_core_stat.c */
 void	target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
Index: lio-core/drivers/target/target_core_spc.c
===================================================================
--- lio-core.orig/drivers/target/target_core_spc.c	2012-05-20 16:52:19.000000000 +0200
+++ lio-core/drivers/target/target_core_spc.c	2012-05-20 16:53:28.102612027 +0200
@@ -938,7 +938,7 @@ static int spc_emulate_testunitready(str
 	return 0;
 }
 
-int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size, bool passthrough)
+int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 {
 	struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
 	unsigned char *cdb = cmd->t_task_cdb;
@@ -952,13 +952,11 @@ int spc_parse_cdb(struct se_cmd *cmd, un
 		break;
 	case MODE_SENSE:
 		*size = cdb[4];
-		if (!passthrough)
-			cmd->execute_cmd = spc_emulate_modesense;
+		cmd->execute_cmd = spc_emulate_modesense;
 		break;
 	case MODE_SENSE_10:
 		*size = (cdb[7] << 8) + cdb[8];
-		if (!passthrough)
-			cmd->execute_cmd = spc_emulate_modesense;
+		cmd->execute_cmd = spc_emulate_modesense;
 		break;
 	case LOG_SELECT:
 	case LOG_SENSE:
@@ -1007,8 +1005,7 @@ int spc_parse_cdb(struct se_cmd *cmd, un
 		break;
 	case REQUEST_SENSE:
 		*size = cdb[4];
-		if (!passthrough)
-			cmd->execute_cmd = spc_emulate_request_sense;
+		cmd->execute_cmd = spc_emulate_request_sense;
 		break;
 	case INQUIRY:
 		*size = (cdb[3] << 8) + cdb[4];
@@ -1019,8 +1016,7 @@ int spc_parse_cdb(struct se_cmd *cmd, un
 		 */
 		if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
 			cmd->sam_task_attr = MSG_HEAD_TAG;
-		if (!passthrough)
-			cmd->execute_cmd = spc_emulate_inquiry;
+		cmd->execute_cmd = spc_emulate_inquiry;
 		break;
 	case SECURITY_PROTOCOL_IN:
 	case SECURITY_PROTOCOL_OUT:
@@ -1051,9 +1047,8 @@ int spc_parse_cdb(struct se_cmd *cmd, un
 			cmd->sam_task_attr = MSG_HEAD_TAG;
 		break;
 	case TEST_UNIT_READY:
+		cmd->execute_cmd = spc_emulate_testunitready;
 		*size = 0;
-		if (!passthrough)
-			cmd->execute_cmd = spc_emulate_testunitready;
 		break;
 	default:
 		pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux