Instead of calling into transport_emulate_control_cdb from __transport_execute_tasks for some CDBs always set up ->exectute_tasks in the command sequence and use it uniformly. Signed-off-by: Christoph Hellwig <hch@xxxxxx> Index: lio-core/drivers/target/target_core_transport.c =================================================================== --- lio-core.orig/drivers/target/target_core_transport.c 2011-11-03 14:13:19.077691237 +0100 +++ lio-core/drivers/target/target_core_transport.c 2011-11-03 14:13:21.241690809 +0100 @@ -52,6 +52,7 @@ #include <target/target_core_configfs.h> #include "target_core_alua.h" +#include "target_core_cdb.h" #include "target_core_hba.h" #include "target_core_stat.h" #include "target_core_pr.h" @@ -2153,31 +2154,11 @@ check_depth: atomic_set(&cmd->t_transport_sent, 1); spin_unlock_irqrestore(&cmd->t_state_lock, flags); - /* - * The struct se_cmd->execute_task() function pointer is used - * to grab REPORT_LUNS and other CDBs we want to handle before they hit the - * struct se_subsystem_api->do_task() caller below. - */ - if (cmd->execute_task) { - error = cmd->execute_task(task); - } else { - /* - * Currently for all virtual TCM plugins including IBLOCK, FILEIO and - * RAMDISK we use the internal transport_emulate_control_cdb() logic - * with struct se_subsystem_api callers for the primary SPC-3 TYPE_DISK - * LUN emulation code. - * - * For TCM/pSCSI and all other SCF_SCSI_DATA_SG_IO_CDB I/O tasks we - * call ->do_task() directly and let the underlying TCM subsystem plugin - * code handle the CDB emulation. - */ - if ((dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) && - (!(task->task_se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))) - error = transport_emulate_control_cdb(task); - else - error = dev->transport->do_task(task); - } + if (cmd->execute_task) + error = cmd->execute_task(task); + else + error = dev->transport->do_task(task); if (error != 0) { cmd->transport_error_status = error; spin_lock_irqsave(&cmd->t_state_lock, flags); @@ -2620,6 +2601,13 @@ static int transport_generic_cmd_sequenc */ } + /* + * If we operate in passthrough mode we skip most CDB emulation and + * instead hand the commands down to the physical SCSI device. + */ + passthrough = + (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV); + switch (cdb[0]) { case READ_6: sectors = transport_get_sectors_6(cdb, cmd, §or_ret); @@ -2699,9 +2687,12 @@ static int transport_generic_cmd_sequenc cmd->t_task_lba = transport_lba_32(cdb); cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; - if (dev->transport->transport_type == - TRANSPORT_PLUGIN_PHBA_PDEV) + /* + * Do now allow BIDI commands for passthrough mode. + */ + if (passthrough) goto out_unsupported_cdb; + /* * Setup BIDI XOR callback to be run after I/O completion. */ @@ -2710,13 +2701,6 @@ static int transport_generic_cmd_sequenc break; case VARIABLE_LENGTH_CMD: service_action = get_unaligned_be16(&cdb[8]); - /* - * Determine if this is TCM/PSCSI device and we should disable - * internal emulation for this CDB. - */ - passthrough = (dev->transport->transport_type == - TRANSPORT_PLUGIN_PHBA_PDEV); - switch (service_action) { case XDWRITEREAD_32: sectors = transport_get_sectors_32(cdb, cmd, §or_ret); @@ -2730,8 +2714,12 @@ static int transport_generic_cmd_sequenc cmd->t_task_lba = transport_lba_64_ext(cdb); cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; + /* + * Do now allow BIDI commands for passthrough mode. + */ if (passthrough) goto out_unsupported_cdb; + /* * Setup BIDI XOR callback to be run during after I/O * completion. @@ -2757,7 +2745,8 @@ static int transport_generic_cmd_sequenc if (target_check_write_same_discard(&cdb[10], dev) < 0) goto out_invalid_cdb_field; - + if (!passthrough) + cmd->execute_task = target_emulate_write_same; break; default: pr_err("VARIABLE_LENGTH_CMD service action" @@ -2795,8 +2784,15 @@ static int transport_generic_cmd_sequenc case MODE_SENSE: size = cdb[4]; cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; + if (!passthrough) + cmd->execute_task = target_emulate_modesense; break; case MODE_SENSE_10: + size = (cdb[7] << 8) + cdb[8]; + cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; + if (!passthrough) + cmd->execute_task = target_emulate_modesense; + break; case GPCMD_READ_BUFFER_CAPACITY: case GPCMD_SEND_OPC: case LOG_SELECT: @@ -2865,6 +2861,8 @@ static int transport_generic_cmd_sequenc if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) cmd->sam_task_attr = MSG_HEAD_TAG; cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; + if (!passthrough) + cmd->execute_task = target_emulate_inquiry; break; case READ_BUFFER: size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; @@ -2873,6 +2871,8 @@ static int transport_generic_cmd_sequenc case READ_CAPACITY: size = READ_CAP_LEN; cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; + if (!passthrough) + cmd->execute_task = target_emulate_readcapacity; break; case READ_MEDIA_SERIAL_NUMBER: case SECURITY_PROTOCOL_IN: @@ -2881,6 +2881,18 @@ static int transport_generic_cmd_sequenc cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case SERVICE_ACTION_IN: + switch (cmd->t_task_cdb[1] & 0x1f) { + case SAI_READ_CAPACITY_16: + if (!passthrough) + cmd->execute_task = + target_emulate_readcapacity_16; + break; + default: + pr_err("Unsupported SA: 0x%02x\n", + cmd->t_task_cdb[1] & 0x1f); + goto out_unsupported_cdb; + } + /*FALLTHROUGH*/ case ACCESS_CONTROL_IN: case ACCESS_CONTROL_OUT: case EXTENDED_COPY: @@ -2911,6 +2923,8 @@ static int transport_generic_cmd_sequenc case REQUEST_SENSE: size = cdb[4]; cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; + if (!passthrough) + cmd->execute_task = target_emulate_request_sense; break; case READ_ELEMENT_STATUS: size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9]; @@ -2975,8 +2989,9 @@ static int transport_generic_cmd_sequenc size = transport_get_size(sectors, cdb, cmd); cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; - if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + if (passthrough) break; + /* * Check to ensure that LBA + Range does not exceed past end of * device for IBLOCK and FILEIO ->do_sync_cache() backend calls @@ -2985,10 +3000,13 @@ static int transport_generic_cmd_sequenc if (transport_cmd_get_valid_sectors(cmd) < 0) goto out_invalid_cdb_field; } + cmd->execute_task = target_emulate_synchronize_cache; break; case UNMAP: size = get_unaligned_be16(&cdb[7]); cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; + if (!passthrough) + cmd->execute_task = target_emulate_unmap; break; case WRITE_SAME_16: sectors = transport_get_sectors_16(cdb, cmd, §or_ret); @@ -3007,6 +3025,8 @@ static int transport_generic_cmd_sequenc if (target_check_write_same_discard(&cdb[1], dev) < 0) goto out_invalid_cdb_field; + if (!passthrough) + cmd->execute_task = target_emulate_write_same; break; case WRITE_SAME: sectors = transport_get_sectors_10(cdb, cmd, §or_ret); @@ -3028,20 +3048,26 @@ static int transport_generic_cmd_sequenc */ if (target_check_write_same_discard(&cdb[1], dev) < 0) goto out_invalid_cdb_field; + if (!passthrough) + cmd->execute_task = target_emulate_write_same; break; case ALLOW_MEDIUM_REMOVAL: - case GPCMD_CLOSE_TRACK: case ERASE: - case INITIALIZE_ELEMENT_STATUS: - case GPCMD_LOAD_UNLOAD: case REZERO_UNIT: case SEEK_10: - case GPCMD_SET_SPEED: case SPACE: case START_STOP: case TEST_UNIT_READY: case VERIFY: case WRITE_FILEMARKS: + cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; + if (!passthrough) + cmd->execute_task = target_emulate_noop; + break; + case GPCMD_CLOSE_TRACK: + case INITIALIZE_ELEMENT_STATUS: + case GPCMD_LOAD_UNLOAD: + case GPCMD_SET_SPEED: case MOVE_MEDIUM: cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; break; @@ -3098,6 +3124,11 @@ static int transport_generic_cmd_sequenc cmd->data_length = size; } + /* reject any command that we don't have a handler for */ + if (!(passthrough || cmd->execute_task || + (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))) + goto out_unsupported_cdb; + /* Let's limit control cdbs to a page, for simplicity's sake. */ if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && size > PAGE_SIZE) Index: lio-core/drivers/target/target_core_cdb.c =================================================================== --- lio-core.orig/drivers/target/target_core_cdb.c 2011-11-03 14:13:19.077691237 +0100 +++ lio-core/drivers/target/target_core_cdb.c 2011-11-03 14:13:21.241690809 +0100 @@ -32,6 +32,7 @@ #include <target/target_core_transport.h> #include <target/target_core_fabric_ops.h> #include "target_core_ua.h" +#include "target_core_cdb.h" static void target_fill_alua_data(struct se_port *port, unsigned char *buf) @@ -679,8 +680,7 @@ target_emulate_evpd_00(struct se_cmd *cm return 0; } -static int -target_emulate_inquiry(struct se_task *task) +int target_emulate_inquiry(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; @@ -731,8 +731,7 @@ out: return ret; } -static int -target_emulate_readcapacity(struct se_task *task) +int target_emulate_readcapacity(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; @@ -768,8 +767,7 @@ target_emulate_readcapacity(struct se_ta return 0; } -static int -target_emulate_readcapacity_16(struct se_task *task) +int target_emulate_readcapacity_16(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; @@ -939,8 +937,7 @@ target_modesense_dpofua(unsigned char *b } } -static int -target_emulate_modesense(struct se_task *task) +int target_emulate_modesense(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; @@ -1019,8 +1016,7 @@ target_emulate_modesense(struct se_task return 0; } -static int -target_emulate_request_sense(struct se_task *task) +int target_emulate_request_sense(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; unsigned char *cdb = cmd->t_task_cdb; @@ -1090,8 +1086,7 @@ end: * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support. * Note this is not used for TCM/pSCSI passthrough */ -static int -target_emulate_unmap(struct se_task *task) +int target_emulate_unmap(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; @@ -1150,8 +1145,7 @@ err: * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support. * Note this is not used for TCM/pSCSI passthrough */ -static int -target_emulate_write_same(struct se_task *task) +int target_emulate_write_same(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; @@ -1196,8 +1190,7 @@ target_emulate_write_same(struct se_task return 0; } -static int -target_emulate_synchronize_cache(struct se_task *task) +int target_emulate_synchronize_cache(struct se_task *task) { struct se_device *dev = task->task_se_cmd->se_dev; @@ -1211,97 +1204,13 @@ target_emulate_synchronize_cache(struct return 0; } -static int -target_emulate_noop(struct se_task *task) +int target_emulate_noop(struct se_task *task) { task->task_scsi_status = GOOD; transport_complete_task(task, 1); return 0; } -int -transport_emulate_control_cdb(struct se_task *task) -{ - struct se_cmd *cmd = task->task_se_cmd; - struct se_device *dev = cmd->se_dev; - unsigned short service_action; - int ret = 0; - - switch (cmd->t_task_cdb[0]) { - case INQUIRY: - ret = target_emulate_inquiry(task); - break; - case READ_CAPACITY: - ret = target_emulate_readcapacity(task); - break; - case MODE_SENSE: - ret = target_emulate_modesense(task); - break; - case MODE_SENSE_10: - ret = target_emulate_modesense(task); - break; - case SERVICE_ACTION_IN: - switch (cmd->t_task_cdb[1] & 0x1f) { - case SAI_READ_CAPACITY_16: - ret = target_emulate_readcapacity_16(task); - break; - default: - pr_err("Unsupported SA: 0x%02x\n", - cmd->t_task_cdb[1] & 0x1f); - return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; - } - break; - case REQUEST_SENSE: - ret = target_emulate_request_sense(task); - break; - case UNMAP: - ret = target_emulate_unmap(task); - break; - case WRITE_SAME: - ret = target_emulate_write_same(task); - break; - case WRITE_SAME_16: - ret = target_emulate_write_same(task); - break; - case VARIABLE_LENGTH_CMD: - service_action = - get_unaligned_be16(&cmd->t_task_cdb[8]); - switch (service_action) { - case WRITE_SAME_32: - ret = target_emulate_write_same(task); - break; - default: - pr_err("Unsupported VARIABLE_LENGTH_CMD SA:" - " 0x%02x\n", service_action); - break; - } - break; - case SYNCHRONIZE_CACHE: - case 0x91: /* SYNCHRONIZE_CACHE_16: */ - ret = target_emulate_synchronize_cache(task); - break; - case ALLOW_MEDIUM_REMOVAL: - case ERASE: - case REZERO_UNIT: - case SEEK_10: - case SPACE: - case START_STOP: - case TEST_UNIT_READY: - case VERIFY: - case WRITE_FILEMARKS: - ret = target_emulate_noop(task); - break; - default: - pr_err("Unsupported SCSI Opcode: 0x%02x for %s\n", - cmd->t_task_cdb[0], dev->transport->name); - return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; - } - - if (ret < 0) - return ret; - return PYX_TRANSPORT_SENT_TO_TRANSPORT; -} - /* * Write a CDB into @cdb that is based on the one the intiator sent us, * but updated to only cover the sectors that the current task handles. Index: lio-core/drivers/target/target_core_cdb.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ lio-core/drivers/target/target_core_cdb.h 2011-11-03 14:13:21.245691107 +0100 @@ -0,0 +1,14 @@ +#ifndef TARGET_CORE_CDB_H +#define TARGET_CORE_CDB_H + +int target_emulate_inquiry(struct se_task *task); +int target_emulate_readcapacity(struct se_task *task); +int target_emulate_readcapacity_16(struct se_task *task); +int target_emulate_modesense(struct se_task *task); +int target_emulate_request_sense(struct se_task *task); +int target_emulate_unmap(struct se_task *task); +int target_emulate_write_same(struct se_task *task); +int target_emulate_synchronize_cache(struct se_task *task); +int target_emulate_noop(struct se_task *task); + +#endif /* TARGET_CORE_CDB_H */ -- 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