diff options
author | Christoph Hellwig <hch@lst.de> | 2012-11-06 12:24:09 -0800 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-11-06 20:55:46 -0800 |
commit | de103c93aff0bed0ae984274e5dc8b95899badab (patch) | |
tree | 7db9bba755fa95772052e8d31285a38ba48f1a84 /drivers/target | |
parent | fecae40abb1ae9218bdbaa8b8e30bfb5ae43f522 (diff) |
target: pass sense_reason as a return value
Pass the sense reason as an explicit return value from the I/O submission
path instead of storing it in struct se_cmd and using negative return
values. This cleans up a lot of the code pathes, and with the sparse
annotations for the new sense_reason_t type allows for much better
error checking.
(nab: Convert spc_emulate_modesense + spc_emulate_modeselect to use
sense_reason_t with Roland's MODE SELECT changes)
Signed-off-by: Christoph Hellwig <hch@lst.de>
Cc: Roland Dreier <roland@purestorage.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 80 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_core.h | 2 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_erl1.c | 11 | ||||
-rw-r--r-- | drivers/target/target_core_alua.c | 98 | ||||
-rw-r--r-- | drivers/target/target_core_alua.h | 6 | ||||
-rw-r--r-- | drivers/target/target_core_device.c | 31 | ||||
-rw-r--r-- | drivers/target/target_core_file.c | 22 | ||||
-rw-r--r-- | drivers/target/target_core_iblock.c | 55 | ||||
-rw-r--r-- | drivers/target/target_core_internal.h | 2 | ||||
-rw-r--r-- | drivers/target/target_core_pr.c | 918 | ||||
-rw-r--r-- | drivers/target/target_core_pr.h | 10 | ||||
-rw-r--r-- | drivers/target/target_core_pscsi.c | 51 | ||||
-rw-r--r-- | drivers/target/target_core_rd.c | 10 | ||||
-rw-r--r-- | drivers/target/target_core_sbc.c | 87 | ||||
-rw-r--r-- | drivers/target/target_core_spc.c | 126 | ||||
-rw-r--r-- | drivers/target/target_core_transport.c | 252 | ||||
-rw-r--r-- | drivers/target/target_core_ua.c | 11 | ||||
-rw-r--r-- | drivers/target/target_core_ua.h | 2 |
18 files changed, 783 insertions, 991 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 035c2c76253..093fb601027 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -767,9 +767,8 @@ static int iscsit_handle_scsi_cmd( struct iscsi_conn *conn, unsigned char *buf) { - int data_direction, cmdsn_ret = 0, immed_ret, ret, transport_ret; - int dump_immediate_data = 0, send_check_condition = 0, payload_length; - struct iscsi_cmd *cmd = NULL; + int data_direction, payload_length, cmdsn_ret = 0, immed_ret; + struct iscsi_cmd *cmd = NULL; struct iscsi_scsi_req *hdr; int iscsi_task_attr; int sam_task_attr; @@ -956,38 +955,26 @@ done: " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, hdr->cmdsn, hdr->data_length, payload_length, conn->cid); - /* - * The CDB is going to an se_device_t. - */ - ret = transport_lookup_cmd_lun(&cmd->se_cmd, - scsilun_to_int(&hdr->lun)); - if (ret < 0) { - if (cmd->se_cmd.scsi_sense_reason == TCM_NON_EXISTENT_LUN) { - pr_debug("Responding to non-acl'ed," - " non-existent or non-exported iSCSI LUN:" - " 0x%016Lx\n", get_unaligned_le64(&hdr->lun)); + cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, + scsilun_to_int(&hdr->lun)); + if (cmd->sense_reason) + goto attach_cmd; + + cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); + if (cmd->sense_reason) { + if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { + return iscsit_add_reject_from_cmd( + ISCSI_REASON_BOOKMARK_NO_RESOURCES, + 1, 1, buf, cmd); } - send_check_condition = 1; + goto attach_cmd; } - transport_ret = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); - if (transport_ret == -ENOMEM) { + if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) { return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); - } else if (transport_ret < 0) { - /* - * Unsupported SAM Opcode. CHECK_CONDITION will be sent - * in iscsit_execute_cmd() during the CmdSN OOO Execution - * Mechinism. - */ - send_check_condition = 1; - } else { - if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + ISCSI_REASON_BOOKMARK_NO_RESOURCES, + 1, 1, buf, cmd); } attach_cmd: @@ -1000,11 +987,12 @@ attach_cmd: */ core_alua_check_nonop_delay(&cmd->se_cmd); - ret = iscsit_allocate_iovecs(cmd); - if (ret < 0) + if (iscsit_allocate_iovecs(cmd) < 0) { return iscsit_add_reject_from_cmd( ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1, 0, buf, cmd); + } + /* * Check the CmdSN against ExpCmdSN/MaxCmdSN here if * the Immediate Bit is not set, and no Immediate @@ -1031,10 +1019,7 @@ attach_cmd: * If no Immediate Data is attached, it's OK to return now. */ if (!cmd->immediate_data) { - if (send_check_condition) - return 0; - - if (cmd->unsolicited_data) { + if (!cmd->sense_reason && cmd->unsolicited_data) { iscsit_set_dataout_sequence_values(cmd); spin_lock_bh(&cmd->dataout_timeout_lock); @@ -1050,19 +1035,17 @@ attach_cmd: * thread. They are processed in CmdSN order by * iscsit_check_received_cmdsn() below. */ - if (send_check_condition) { + if (cmd->sense_reason) { immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; - dump_immediate_data = 1; goto after_immediate_data; } /* * Call directly into transport_generic_new_cmd() to perform * the backend memory allocation. */ - ret = transport_generic_new_cmd(&cmd->se_cmd); - if (ret < 0) { + cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); + if (cmd->sense_reason) { immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; - dump_immediate_data = 1; goto after_immediate_data; } @@ -1079,7 +1062,7 @@ after_immediate_data: * Special case for Unsupported SAM WRITE Opcodes * and ImmediateData=Yes. */ - if (dump_immediate_data) { + if (cmd->sense_reason) { if (iscsit_dump_data_payload(conn, payload_length, 1) < 0) return -1; } else if (cmd->unsolicited_data) { @@ -1272,8 +1255,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); spin_lock_irqsave(&se_cmd->t_state_lock, flags); - if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) || - (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) + if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE)) dump_unsolicited_data = 1; spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); @@ -1742,7 +1724,6 @@ static int iscsit_handle_task_mgt_cmd( ret = transport_lookup_tmr_lun(&cmd->se_cmd, scsilun_to_int(&hdr->lun)); if (ret < 0) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_NO_LUN; goto attach; } @@ -1751,10 +1732,8 @@ static int iscsit_handle_task_mgt_cmd( switch (function) { case ISCSI_TM_FUNC_ABORT_TASK: se_tmr->response = iscsit_tmr_abort_task(cmd, buf); - if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + if (se_tmr->response) goto attach; - } break; case ISCSI_TM_FUNC_ABORT_TASK_SET: case ISCSI_TM_FUNC_CLEAR_ACA: @@ -1763,14 +1742,12 @@ static int iscsit_handle_task_mgt_cmd( break; case ISCSI_TM_FUNC_TARGET_WARM_RESET: if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; goto attach; } break; case ISCSI_TM_FUNC_TARGET_COLD_RESET: if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; goto attach; } @@ -1781,7 +1758,7 @@ static int iscsit_handle_task_mgt_cmd( * Perform sanity checks on the ExpDataSN only if the * TASK_REASSIGN was successful. */ - if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) + if (se_tmr->response) break; if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) @@ -1792,7 +1769,6 @@ static int iscsit_handle_task_mgt_cmd( default: pr_err("Unknown TMR function: 0x%02x, protocol" " error.\n", function); - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED; goto attach; } diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 21048dbf7d1..7a333d28d9a 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -474,7 +474,7 @@ struct iscsi_cmd { struct scatterlist *first_data_sg; u32 first_data_sg_off; u32 kmapped_nents; - + sense_reason_t sense_reason; } ____cacheline_aligned; struct iscsi_tmr_req { diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 21f29d91a8c..0b52a237130 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -929,11 +929,10 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) case ISCSI_OP_SCSI_CMD: /* * Go ahead and send the CHECK_CONDITION status for - * any SCSI CDB exceptions that may have occurred, also - * handle the SCF_SCSI_RESERVATION_CONFLICT case here as well. + * any SCSI CDB exceptions that may have occurred. */ - if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { - if (se_cmd->scsi_sense_reason == TCM_RESERVATION_CONFLICT) { + if (cmd->sense_reason) { + if (cmd->sense_reason == TCM_RESERVATION_CONFLICT) { cmd->i_state = ISTATE_SEND_STATUS; spin_unlock_bh(&cmd->istate_lock); iscsit_add_cmd_to_response_queue(cmd, cmd->conn, @@ -956,7 +955,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) * exception */ return transport_send_check_condition_and_sense(se_cmd, - se_cmd->scsi_sense_reason, 0); + cmd->sense_reason, 0); } /* * Special case for delayed CmdSN with Immediate @@ -1013,7 +1012,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); break; case ISCSI_OP_SCSI_TMFUNC: - if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { + if (cmd->se_cmd.se_tmr_req->response) { spin_unlock_bh(&cmd->istate_lock); iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index b3302a9200a..e62dc529e51 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -41,7 +41,7 @@ #include "target_core_alua.h" #include "target_core_ua.h" -static int core_alua_check_transition(int state, int *primary); +static sense_reason_t core_alua_check_transition(int state, int *primary); static int core_alua_set_tg_pt_secondary_state( struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, struct se_port *port, int explict, int offline); @@ -59,7 +59,8 @@ struct t10_alua_lu_gp *default_lu_gp; * * See spc4r17 section 6.27 */ -int target_emulate_report_target_port_groups(struct se_cmd *cmd) +sense_reason_t +target_emulate_report_target_port_groups(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_port *port; @@ -68,6 +69,7 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) unsigned char *buf; u32 rd_len = 0, off; int ext_hdr = (cmd->t_task_cdb[1] & 0x20); + /* * Skip over RESERVED area to first Target port group descriptor * depending on the PARAMETER DATA FORMAT type.. @@ -81,10 +83,11 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) pr_warn("REPORT TARGET PORT GROUPS allocation length %u too" " small for %s header\n", cmd->data_length, (ext_hdr) ? "extended" : "normal"); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; spin_lock(&dev->t10_alua.tg_pt_gps_lock); list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, @@ -200,7 +203,8 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) * * See spc4r17 section 6.35 */ -int target_emulate_set_target_port_groups(struct se_cmd *cmd) +sense_reason_t +target_emulate_set_target_port_groups(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_port *port, *l_port = cmd->se_lun->lun_sep; @@ -209,22 +213,23 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; unsigned char *buf; unsigned char *ptr; + sense_reason_t rc; u32 len = 4; /* Skip over RESERVED area in header */ - int alua_access_state, primary = 0, rc; + int alua_access_state, primary = 0; u16 tg_pt_id, rtpi; - if (!l_port) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; - } + if (!l_port) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (cmd->data_length < 4) { pr_warn("SET TARGET PORT GROUPS parameter list length %u too" " small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; /* * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed @@ -233,8 +238,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; if (!l_tg_pt_gp_mem) { pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - rc = -EINVAL; + rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); @@ -242,24 +246,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) if (!l_tg_pt_gp) { spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - rc = -EINVAL; + rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } - rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA); spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); - if (!rc) { + if (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA) { pr_debug("Unable to process SET_TARGET_PORT_GROUPS" " while TPGS_EXPLICT_ALUA is disabled\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - rc = -EINVAL; + rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } ptr = &buf[4]; /* Skip over RESERVED area in header */ while (len < cmd->data_length) { + bool found = false; alua_access_state = (ptr[0] & 0x0f); /* * Check the received ALUA access state, and determine if @@ -267,7 +269,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) * access state. */ rc = core_alua_check_transition(alua_access_state, &primary); - if (rc != 0) { + if (rc) { /* * If the SET TARGET PORT GROUPS attempts to establish * an invalid combination of target port asymmetric @@ -278,11 +280,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) * REQUEST, and the additional sense code set to INVALID * FIELD IN PARAMETER LIST. */ - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - rc = -EINVAL; goto out; } - rc = -1; + /* * If the ASYMMETRIC ACCESS STATE field (see table 267) * specifies a primary target port asymmetric access state, @@ -314,11 +314,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); smp_mb__after_atomic_inc(); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); - rc = core_alua_do_port_transition(tg_pt_gp, + if (!core_alua_do_port_transition(tg_pt_gp, dev, l_port, nacl, - alua_access_state, 1); + alua_access_state, 1)) + found = true; spin_lock(&dev->t10_alua.tg_pt_gps_lock); atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); @@ -326,15 +328,6 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) break; } spin_unlock(&dev->t10_alua.tg_pt_gps_lock); - /* - * If not matching target port group ID can be located - * throw an exception with ASCQ: INVALID_PARAMETER_LIST - */ - if (rc != 0) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - rc = -EINVAL; - goto out; - } } else { /* * Extact the RELATIVE TARGET PORT IDENTIFIER to identify @@ -353,25 +346,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) continue; tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; + spin_unlock(&dev->se_port_lock); - rc = core_alua_set_tg_pt_secondary_state( - tg_pt_gp_mem, port, 1, 1); + if (!core_alua_set_tg_pt_secondary_state( + tg_pt_gp_mem, port, 1, 1)) + found = true; spin_lock(&dev->se_port_lock); break; } spin_unlock(&dev->se_port_lock); - /* - * If not matching relative target port identifier can - * be located, throw an exception with ASCQ: - * INVALID_PARAMETER_LIST - */ - if (rc != 0) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - rc = -EINVAL; - goto out; - } + } + + if (!found) { + rc = TCM_INVALID_PARAMETER_LIST; + goto out; } ptr += 4; @@ -526,7 +516,8 @@ static inline int core_alua_state_transition( * return 0: Used to signal success * reutrn -1: Used to signal failure, and invalid cdb field */ -int target_alua_state_check(struct se_cmd *cmd) +sense_reason_t +target_alua_state_check(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; @@ -599,8 +590,7 @@ int target_alua_state_check(struct se_cmd *cmd) default: pr_err("Unknown ALUA access state: 0x%02x\n", out_alua_state); - ret = -EINVAL; - break; + return TCM_INVALID_CDB_FIELD; } out: @@ -617,15 +607,17 @@ out: cmd->scsi_asc = 0x04; cmd->scsi_ascq = alua_ascq; + return TCM_CHECK_CONDITION_NOT_READY; } - return ret; + return 0; } /* * Check implict and explict ALUA state change request. */ -static int core_alua_check_transition(int state, int *primary) +static sense_reason_t +core_alua_check_transition(int state, int *primary) { switch (state) { case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: @@ -647,7 +639,7 @@ static int core_alua_check_transition(int state, int *primary) break; default: pr_err("Unknown ALUA access state: 0x%02x\n", state); - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } return 0; diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index a2af8aa15b9..e539c3e7f4a 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h @@ -72,8 +72,8 @@ extern struct kmem_cache *t10_alua_lu_gp_mem_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; -extern int target_emulate_report_target_port_groups(struct se_cmd *); -extern int target_emulate_set_target_port_groups(struct se_cmd *); +extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *); +extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *); extern int core_alua_check_nonop_delay(struct se_cmd *); extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *, struct se_device *, struct se_port *, @@ -132,6 +132,6 @@ extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *, extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *, const char *, size_t); extern int core_setup_alua(struct se_device *); -extern int target_alua_state_check(struct se_cmd *cmd); +extern sense_reason_t target_alua_state_check(struct se_cmd *cmd); #endif /* TARGET_CORE_ALUA_H */ diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 066e8159afc..599374e6d24 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -54,18 +54,16 @@ static struct se_hba *lun0_hba; /* not static, needed by tpg.c */ struct se_device *g_lun0_dev; -int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) +sense_reason_t +transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) { struct se_lun *se_lun = NULL; struct se_session *se_sess = se_cmd->se_sess; struct se_device *dev; unsigned long flags; - if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - return -ENODEV; - } + if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) + return TCM_NON_EXISTENT_LUN; spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; @@ -77,14 +75,12 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) if ((se_cmd->data_direction == DMA_TO_DEVICE) && (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) { - se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN" " Access for 0x%08x\n", se_cmd->se_tfo->get_fabric_name(), unpacked_lun); spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags); - return -EACCES; + return TCM_WRITE_PROTECTED; } if (se_cmd->data_direction == DMA_TO_DEVICE) @@ -109,23 +105,18 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) * MappedLUN=0 exists for this Initiator Port. */ if (unpacked_lun != 0) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN" " Access for 0x%08x\n", se_cmd->se_tfo->get_fabric_name(), unpacked_lun); - return -ENODEV; + return TCM_NON_EXISTENT_LUN; } /* * Force WRITE PROTECT for virtual LUN 0 */ if ((se_cmd->data_direction != DMA_FROM_DEVICE) && - (se_cmd->data_direction != DMA_NONE)) { - se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - return -EACCES; - } + (se_cmd->data_direction != DMA_NONE)) + return TCM_WRITE_PROTECTED; se_lun = &se_sess->se_tpg->tpg_virt_lun0; se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0; @@ -162,11 +153,8 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; unsigned long flags; - if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) return -ENODEV; - } spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; @@ -186,7 +174,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) " Access for 0x%08x\n", se_cmd->se_tfo->get_fabric_name(), unpacked_lun); - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return -ENODEV; } diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 342a6a6dcca..3ccef831a64 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -309,7 +309,8 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, return 1; } -static int fd_execute_sync_cache(struct se_cmd *cmd) +static sense_reason_t +fd_execute_sync_cache(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct fd_dev *fd_dev = FD_DEV(dev); @@ -345,17 +346,16 @@ static int fd_execute_sync_cache(struct se_cmd *cmd) if (immed) return 0; - if (ret) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (ret) target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); - } else { + else target_complete_cmd(cmd, SAM_STAT_GOOD); - } return 0; } -static int fd_execute_rw(struct se_cmd *cmd) +static sense_reason_t +fd_execute_rw(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -388,10 +388,9 @@ static int fd_execute_rw(struct se_cmd *cmd) } } - if (ret < 0) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return ret; - } + if (ret < 0) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (ret) target_complete_cmd(cmd, SAM_STAT_GOOD); return 0; @@ -515,7 +514,8 @@ static struct sbc_ops fd_sbc_ops = { .execute_sync_cache = fd_execute_sync_cache, }; -static int fd_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +fd_parse_cdb(struct se_cmd *cmd) { return sbc_parse_cdb(cmd, &fd_sbc_ops); } diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 17fc01d6bae..53f4501819f 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -261,13 +261,10 @@ static void iblock_end_io_flush(struct bio *bio, int err) pr_err("IBLOCK: cache flush failed: %d\n", err); if (cmd) { - if (err) { - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (err) target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); - } else { + else target_complete_cmd(cmd, SAM_STAT_GOOD); - } } bio_put(bio); @@ -277,7 +274,8 @@ static void iblock_end_io_flush(struct bio *bio, int err) * Implement SYCHRONIZE CACHE. Note that we can't handle lba ranges and must * always flush the whole cache. */ -static int iblock_execute_sync_cache(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_sync_cache(struct se_cmd *cmd) { struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); int immed = (cmd->t_task_cdb[1] & 0x2); @@ -299,7 +297,8 @@ static int iblock_execute_sync_cache(struct se_cmd *cmd) return 0; } -static int iblock_execute_unmap(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_unmap(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct iblock_dev *ib_dev = IBLOCK_DEV(dev); @@ -307,17 +306,18 @@ static int iblock_execute_unmap(struct se_cmd *cmd) sector_t lba; int size; u32 range; - int ret = 0; - int dl, bd_dl; + sense_reason_t ret = 0; + int dl, bd_dl, err; if (cmd->data_length < 8) { pr_warn("UNMAP parameter list length %u too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; dl = get_unaligned_be16(&buf[0]); bd_dl = get_unaligned_be16(&buf[2]); @@ -330,8 +330,7 @@ static int iblock_execute_unmap(struct se_cmd *cmd) size = bd_dl; if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto err; } @@ -347,22 +346,21 @@ static int iblock_execute_unmap(struct se_cmd *cmd) (unsigned long long)lba, range); if (range > dev->dev_attrib.max_unmap_lba_count) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto err; } if (lba + range > dev->transport->get_blocks(dev) + 1) { - cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE; - ret = -EINVAL; + ret = TCM_ADDRESS_OUT_OF_RANGE; goto err; } - ret = blkdev_issue_discard(ib_dev->ibd_bd, lba, range, + err = blkdev_issue_discard(ib_dev->ibd_bd, lba, range, GFP_KERNEL, 0); - if (ret < 0) { + if (err < 0) { pr_err("blkdev_issue_discard() failed: %d\n", - ret); + err); + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto err; } @@ -377,7 +375,8 @@ err: return ret; } -static int iblock_execute_write_same(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_write_same(struct se_cmd *cmd) { struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); int ret; @@ -387,7 +386,7 @@ static int iblock_execute_write_same(struct se_cmd *cmd) 0); if (ret < 0) { pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n"); - return ret; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } target_complete_cmd(cmd, GOOD); @@ -552,7 +551,8 @@ static void iblock_submit_bios(struct bio_list *list, int rw) blk_finish_plug(&plug); } -static int iblock_execute_rw(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_rw(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -598,8 +598,7 @@ static int iblock_execute_rw(struct se_cmd *cmd) else { pr_err("Unsupported SCSI -> BLOCK LBA conversion:" " %u\n", dev->dev_attrib.block_size); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOSYS; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); @@ -659,9 +658,8 @@ fail_put_bios: bio_put(bio); fail_free_ibr: kfree(ibr); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; fail: - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } static sector_t iblock_get_blocks(struct se_device *dev) @@ -706,7 +704,8 @@ static struct sbc_ops iblock_sbc_ops = { .execute_unmap = iblock_execute_unmap, }; -static int iblock_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +iblock_parse_cdb(struct se_cmd *cmd) { return sbc_parse_cdb(cmd, &iblock_sbc_ops); } diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 2f37720c4db..bc9c5228484 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -101,7 +101,7 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); 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); +sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); void target_qf_do_work(struct work_struct *work); /* target_core_stat.c */ diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index f561a08ff8e..ffbe0ea9bba 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -68,7 +68,8 @@ int core_pr_dump_initiator_port( static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, struct t10_pr_registration *, int); -static int target_scsi2_reservation_check(struct se_cmd *cmd) +static sense_reason_t +target_scsi2_reservation_check(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; @@ -86,11 +87,11 @@ static int target_scsi2_reservation_check(struc |