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, §or_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, §or_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, §or_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, §or_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, §or_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, §or_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, §or_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, §or_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, §or_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, §or_ret); - cmd->t_task_lba = pscsi_get_lba_32(cdb); - } else { - sectors = pscsi_get_sectors_16(cdb, cmd, §or_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, §or_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, §or_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