From cc5ab6df130b2cefc274ef2c5c92afee5a0b091e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 May 2012 11:59:10 -0400 Subject: target: move unrelated code out of transport_generic_cmd_sequencer Move all code not related to cdb parsing from transport_generic_cmd_sequencer into target_setup_cmd_from_cdb. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 143 +++++++++++++++------------------ 1 file changed, 66 insertions(+), 77 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index b05fdc0c05d3..907843f47a08 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1412,6 +1412,10 @@ int target_setup_cmd_from_cdb( struct se_cmd *cmd, unsigned char *cdb) { + struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; + u32 pr_reg_type = 0; + u8 alua_ascq = 0; + unsigned long flags; int ret; transport_generic_prepare_cdb(cdb); @@ -1451,6 +1455,58 @@ int target_setup_cmd_from_cdb( * Copy the original CDB into cmd-> */ memcpy(cmd->t_task_cdb, cdb, scsi_command_size(cdb)); + + /* + * Check for an existing UNIT ATTENTION condition + */ + if (core_scsi3_ua_check(cmd, cdb) < 0) { + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION; + return -EINVAL; + } + + ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq); + if (ret != 0) { + /* + * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; + * The ALUA additional sense code qualifier (ASCQ) is determined + * by the ALUA primary or secondary access state.. + */ + if (ret > 0) { + pr_debug("[%s]: ALUA TG Port not available, " + "SenseKey: NOT_READY, ASC/ASCQ: " + "0x04/0x%02x\n", + cmd->se_tfo->get_fabric_name(), alua_ascq); + + transport_set_sense_codes(cmd, 0x04, alua_ascq); + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY; + return -EINVAL; + } + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; + } + + /* + * Check status for SPC-3 Persistent Reservations + */ + if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) { + if (su_dev->t10_pr.pr_ops.t10_seq_non_holder( + cmd, cdb, pr_reg_type) != 0) { + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; + cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EBUSY; + } + /* + * This means the CDB is allowed for the SCSI Initiator port + * when said port is *NOT* holding the legacy SPC-2 or + * SPC-3 Persistent Reservation. + */ + } + /* * Setup the received CDB based on SCSI defined opcodes and * perform unit attention, persistent reservations and ALUA @@ -1460,6 +1516,11 @@ int target_setup_cmd_from_cdb( ret = transport_generic_cmd_sequencer(cmd, cdb); if (ret < 0) return ret; + + spin_lock_irqsave(&cmd->t_state_lock, flags); + cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + /* * Check for SAM Task Attribute Emulation */ @@ -1883,15 +1944,6 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; } -static void transport_set_supported_SAM_opcode(struct se_cmd *se_cmd) -{ - unsigned long flags; - - spin_lock_irqsave(&se_cmd->t_state_lock, flags); - se_cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); -} - /* * Called from Fabric Module context from transport_execute_tasks() * @@ -2364,74 +2416,15 @@ static int target_check_write_same_discard(unsigned char *flags, struct se_devic return 0; } -/* transport_generic_cmd_sequencer(): - * - * Generic Command Sequencer that should work for most DAS transport - * drivers. - * - * Called from target_setup_cmd_from_cdb() in the $FABRIC_MOD - * RX Thread. - * - * FIXME: Need to support other SCSI OPCODES where as well. - */ static int transport_generic_cmd_sequencer( struct se_cmd *cmd, unsigned char *cdb) { struct se_device *dev = cmd->se_dev; struct se_subsystem_dev *su_dev = dev->se_sub_dev; - int ret = 0, sector_ret = 0, passthrough; - u32 sectors = 0, size = 0, pr_reg_type = 0; + int sector_ret = 0, passthrough; + u32 sectors = 0, size = 0; u16 service_action; - u8 alua_ascq = 0; - /* - * Check for an existing UNIT ATTENTION condition - */ - if (core_scsi3_ua_check(cmd, cdb) < 0) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION; - return -EINVAL; - } - /* - * Check status of Asymmetric Logical Unit Assignment port - */ - ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq); - if (ret != 0) { - /* - * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; - * The ALUA additional sense code qualifier (ASCQ) is determined - * by the ALUA primary or secondary access state.. - */ - if (ret > 0) { - pr_debug("[%s]: ALUA TG Port not available," - " SenseKey: NOT_READY, ASC/ASCQ: 0x04/0x%02x\n", - cmd->se_tfo->get_fabric_name(), alua_ascq); - - transport_set_sense_codes(cmd, 0x04, alua_ascq); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY; - return -EINVAL; - } - goto out_invalid_cdb_field; - } - /* - * Check status for SPC-3 Persistent Reservations - */ - if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type) != 0) { - if (su_dev->t10_pr.pr_ops.t10_seq_non_holder( - cmd, cdb, pr_reg_type) != 0) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; - cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EBUSY; - } - /* - * This means the CDB is allowed for the SCSI Initiator port - * when said port is *NOT* holding the legacy SPC-2 or - * SPC-3 Persistent Reservation. - */ - } /* * If we operate in passthrough mode we skip most CDB emulation and @@ -2986,7 +2979,7 @@ static int transport_generic_cmd_sequencer( * Reject READ_* or WRITE_* with overflow/underflow for * type SCF_SCSI_DATA_SG_IO_CDB. */ - if (!ret && (dev->se_sub_dev->se_dev_attrib.block_size != 512)) { + if (dev->se_sub_dev->se_dev_attrib.block_size != 512) { pr_err("Failing OVERFLOW/UNDERFLOW for LBA op" " CDB on non 512-byte sector setup subsystem" " plugin: %s\n", dev->transport->name); @@ -3026,8 +3019,7 @@ static int transport_generic_cmd_sequencer( (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))) goto out_unsupported_cdb; - transport_set_supported_SAM_opcode(cmd); - return ret; + return 0; out_unsupported_cdb: cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; @@ -3961,10 +3953,7 @@ bool transport_wait_for_tasks(struct se_cmd *cmd) spin_unlock_irqrestore(&cmd->t_state_lock, flags); return false; } - /* - * Only perform a possible wait_for_tasks if SCF_SUPPORTED_SAM_OPCODE - * has been set in transport_set_supported_SAM_opcode(). - */ + if (!(cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) && !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) { spin_unlock_irqrestore(&cmd->t_state_lock, flags); -- cgit