Commit de103c93 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Nicholas Bellinger

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: default avatarChristoph Hellwig <hch@lst.de>
Cc: Roland Dreier <roland@purestorage.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent fecae40a
...@@ -1730,7 +1730,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, ...@@ -1730,7 +1730,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
uint64_t unpacked_lun; uint64_t unpacked_lun;
u64 data_len; u64 data_len;
enum dma_data_direction dir; enum dma_data_direction dir;
int ret; sense_reason_t ret;
BUG_ON(!send_ioctx); BUG_ON(!send_ioctx);
...@@ -1755,12 +1755,10 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, ...@@ -1755,12 +1755,10 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
break; break;
} }
ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len); if (srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len)) {
if (ret) {
printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n", printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n",
srp_cmd->tag); srp_cmd->tag);
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; ret = TCM_INVALID_CDB_FIELD;
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
goto send_sense; goto send_sense;
} }
...@@ -1769,26 +1767,26 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, ...@@ -1769,26 +1767,26 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
cmd->data_direction = dir; cmd->data_direction = dir;
unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun, unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun,
sizeof(srp_cmd->lun)); sizeof(srp_cmd->lun));
if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) { ret = transport_lookup_cmd_lun(cmd, unpacked_lun);
if (ret) {
kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
goto send_sense; goto send_sense;
} }
ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb); ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb);
if (ret < 0) { if (ret) {
kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) { if (ret == TCM_RESERVATION_CONFLICT) {
srpt_queue_status(cmd); srpt_queue_status(cmd);
return 0; return 0;
} else }
goto send_sense; goto send_sense;
} }
transport_handle_cdb_direct(cmd); transport_handle_cdb_direct(cmd);
return 0; return 0;
send_sense: send_sense:
transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason, transport_send_check_condition_and_sense(cmd, ret, 0);
0);
return -1; return -1;
} }
...@@ -1882,16 +1880,14 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, ...@@ -1882,16 +1880,14 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
send_ioctx->tag = srp_tsk->tag; send_ioctx->tag = srp_tsk->tag;
tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func);
if (tcm_tmr < 0) { if (tcm_tmr < 0) {
send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
send_ioctx->cmd.se_tmr_req->response = send_ioctx->cmd.se_tmr_req->response =
TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
goto process_tmr; goto fail;
} }
res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL); res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL);
if (res < 0) { if (res < 0) {
send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;
goto process_tmr; goto fail;
} }
unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun, unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun,
...@@ -1899,22 +1895,19 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, ...@@ -1899,22 +1895,19 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun); res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun);
if (res) { if (res) {
pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun); pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun);
send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
goto process_tmr; goto fail;
} }
if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK)
srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);
process_tmr:
kref_get(&send_ioctx->kref); kref_get(&send_ioctx->kref);
if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) transport_generic_handle_tmr(&send_ioctx->cmd);
transport_generic_handle_tmr(&send_ioctx->cmd); return;
else fail:
transport_send_check_condition_and_sense(cmd, kref_get(&send_ioctx->kref);
cmd->scsi_sense_reason, 0); transport_send_check_condition_and_sense(cmd, 0, 0); // XXX:
} }
/** /**
......
...@@ -620,8 +620,8 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work) ...@@ -620,8 +620,8 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
return; return;
} }
cmd->se_cmd.scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD; transport_generic_request_failure(&cmd->se_cmd,
transport_generic_request_failure(&cmd->se_cmd); TCM_CHECK_CONDITION_ABORT_CMD);
return; return;
} }
......
...@@ -767,9 +767,8 @@ static int iscsit_handle_scsi_cmd( ...@@ -767,9 +767,8 @@ static int iscsit_handle_scsi_cmd(
struct iscsi_conn *conn, struct iscsi_conn *conn,
unsigned char *buf) unsigned char *buf)
{ {
int data_direction, cmdsn_ret = 0, immed_ret, ret, transport_ret; int data_direction, payload_length, cmdsn_ret = 0, immed_ret;
int dump_immediate_data = 0, send_check_condition = 0, payload_length; struct iscsi_cmd *cmd = NULL;
struct iscsi_cmd *cmd = NULL;
struct iscsi_scsi_req *hdr; struct iscsi_scsi_req *hdr;
int iscsi_task_attr; int iscsi_task_attr;
int sam_task_attr; int sam_task_attr;
...@@ -956,38 +955,26 @@ static int iscsit_handle_scsi_cmd( ...@@ -956,38 +955,26 @@ static int iscsit_handle_scsi_cmd(
" ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
hdr->cmdsn, hdr->data_length, payload_length, conn->cid); hdr->cmdsn, hdr->data_length, payload_length, conn->cid);
/* cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
* The CDB is going to an se_device_t. scsilun_to_int(&hdr->lun));
*/ if (cmd->sense_reason)
ret = transport_lookup_cmd_lun(&cmd->se_cmd, goto attach_cmd;
scsilun_to_int(&hdr->lun));
if (ret < 0) { cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);
if (cmd->se_cmd.scsi_sense_reason == TCM_NON_EXISTENT_LUN) { if (cmd->sense_reason) {
pr_debug("Responding to non-acl'ed," if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
" non-existent or non-exported iSCSI LUN:" return iscsit_add_reject_from_cmd(
" 0x%016Lx\n", get_unaligned_le64(&hdr->lun)); ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1, 1, buf, cmd);
} }
send_check_condition = 1;
goto attach_cmd; goto attach_cmd;
} }
transport_ret = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) {
if (transport_ret == -ENOMEM) {
return iscsit_add_reject_from_cmd( return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES, ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1, 1, buf, cmd); 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);
} }
attach_cmd: attach_cmd:
...@@ -1000,11 +987,12 @@ static int iscsit_handle_scsi_cmd( ...@@ -1000,11 +987,12 @@ static int iscsit_handle_scsi_cmd(
*/ */
core_alua_check_nonop_delay(&cmd->se_cmd); core_alua_check_nonop_delay(&cmd->se_cmd);
ret = iscsit_allocate_iovecs(cmd); if (iscsit_allocate_iovecs(cmd) < 0) {
if (ret < 0)
return iscsit_add_reject_from_cmd( return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES, ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1, 0, buf, cmd); 1, 0, buf, cmd);
}
/* /*
* Check the CmdSN against ExpCmdSN/MaxCmdSN here if * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
* the Immediate Bit is not set, and no Immediate * the Immediate Bit is not set, and no Immediate
...@@ -1031,10 +1019,7 @@ static int iscsit_handle_scsi_cmd( ...@@ -1031,10 +1019,7 @@ static int iscsit_handle_scsi_cmd(
* If no Immediate Data is attached, it's OK to return now. * If no Immediate Data is attached, it's OK to return now.
*/ */
if (!cmd->immediate_data) { if (!cmd->immediate_data) {
if (send_check_condition) if (!cmd->sense_reason && cmd->unsolicited_data) {
return 0;
if (cmd->unsolicited_data) {
iscsit_set_dataout_sequence_values(cmd); iscsit_set_dataout_sequence_values(cmd);
spin_lock_bh(&cmd->dataout_timeout_lock); spin_lock_bh(&cmd->dataout_timeout_lock);
...@@ -1050,19 +1035,17 @@ static int iscsit_handle_scsi_cmd( ...@@ -1050,19 +1035,17 @@ static int iscsit_handle_scsi_cmd(
* thread. They are processed in CmdSN order by * thread. They are processed in CmdSN order by
* iscsit_check_received_cmdsn() below. * iscsit_check_received_cmdsn() below.
*/ */
if (send_check_condition) { if (cmd->sense_reason) {
immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
dump_immediate_data = 1;
goto after_immediate_data; goto after_immediate_data;
} }
/* /*
* Call directly into transport_generic_new_cmd() to perform * Call directly into transport_generic_new_cmd() to perform
* the backend memory allocation. * the backend memory allocation.
*/ */
ret = transport_generic_new_cmd(&cmd->se_cmd); cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
if (ret < 0) { if (cmd->sense_reason) {
immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
dump_immediate_data = 1;
goto after_immediate_data; goto after_immediate_data;
} }
...@@ -1079,7 +1062,7 @@ static int iscsit_handle_scsi_cmd( ...@@ -1079,7 +1062,7 @@ static int iscsit_handle_scsi_cmd(
* Special case for Unsupported SAM WRITE Opcodes * Special case for Unsupported SAM WRITE Opcodes
* and ImmediateData=Yes. * and ImmediateData=Yes.
*/ */
if (dump_immediate_data) { if (cmd->sense_reason) {
if (iscsit_dump_data_payload(conn, payload_length, 1) < 0) if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
return -1; return -1;
} else if (cmd->unsolicited_data) { } else if (cmd->unsolicited_data) {
...@@ -1272,8 +1255,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) ...@@ -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_unlock_irqrestore(&se_cmd->t_state_lock, flags);
spin_lock_irqsave(&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) || if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE))
(se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION))
dump_unsolicited_data = 1; dump_unsolicited_data = 1;
spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
...@@ -1742,7 +1724,6 @@ static int iscsit_handle_task_mgt_cmd( ...@@ -1742,7 +1724,6 @@ static int iscsit_handle_task_mgt_cmd(
ret = transport_lookup_tmr_lun(&cmd->se_cmd, ret = transport_lookup_tmr_lun(&cmd->se_cmd,
scsilun_to_int(&hdr->lun)); scsilun_to_int(&hdr->lun));
if (ret < 0) { if (ret < 0) {
cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
se_tmr->response = ISCSI_TMF_RSP_NO_LUN; se_tmr->response = ISCSI_TMF_RSP_NO_LUN;
goto attach; goto attach;
} }
...@@ -1751,10 +1732,8 @@ static int iscsit_handle_task_mgt_cmd( ...@@ -1751,10 +1732,8 @@ static int iscsit_handle_task_mgt_cmd(
switch (function) { switch (function) {
case ISCSI_TM_FUNC_ABORT_TASK: case ISCSI_TM_FUNC_ABORT_TASK:
se_tmr->response = iscsit_tmr_abort_task(cmd, buf); se_tmr->response = iscsit_tmr_abort_task(cmd, buf);
if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) { if (se_tmr->response)
cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
goto attach; goto attach;
}
break; break;
case ISCSI_TM_FUNC_ABORT_TASK_SET: case ISCSI_TM_FUNC_ABORT_TASK_SET:
case ISCSI_TM_FUNC_CLEAR_ACA: case ISCSI_TM_FUNC_CLEAR_ACA:
...@@ -1763,14 +1742,12 @@ static int iscsit_handle_task_mgt_cmd( ...@@ -1763,14 +1742,12 @@ static int iscsit_handle_task_mgt_cmd(
break; break;
case ISCSI_TM_FUNC_TARGET_WARM_RESET: case ISCSI_TM_FUNC_TARGET_WARM_RESET:
if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) { 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; se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
goto attach; goto attach;
} }
break; break;
case ISCSI_TM_FUNC_TARGET_COLD_RESET: case ISCSI_TM_FUNC_TARGET_COLD_RESET:
if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) { 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; se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
goto attach; goto attach;
} }
...@@ -1781,7 +1758,7 @@ static int iscsit_handle_task_mgt_cmd( ...@@ -1781,7 +1758,7 @@ static int iscsit_handle_task_mgt_cmd(
* Perform sanity checks on the ExpDataSN only if the * Perform sanity checks on the ExpDataSN only if the
* TASK_REASSIGN was successful. * TASK_REASSIGN was successful.
*/ */
if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) if (se_tmr->response)
break; break;
if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0)
...@@ -1792,7 +1769,6 @@ static int iscsit_handle_task_mgt_cmd( ...@@ -1792,7 +1769,6 @@ static int iscsit_handle_task_mgt_cmd(
default: default:
pr_err("Unknown TMR function: 0x%02x, protocol" pr_err("Unknown TMR function: 0x%02x, protocol"
" error.\n", function); " error.\n", function);
cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED; se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED;
goto attach; goto attach;
} }
......
...@@ -474,7 +474,7 @@ struct iscsi_cmd { ...@@ -474,7 +474,7 @@ struct iscsi_cmd {
struct scatterlist *first_data_sg; struct scatterlist *first_data_sg;
u32 first_data_sg_off; u32 first_data_sg_off;
u32 kmapped_nents; u32 kmapped_nents;
sense_reason_t sense_reason;
} ____cacheline_aligned; } ____cacheline_aligned;
struct iscsi_tmr_req { struct iscsi_tmr_req {
......
...@@ -929,11 +929,10 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) ...@@ -929,11 +929,10 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
case ISCSI_OP_SCSI_CMD: case ISCSI_OP_SCSI_CMD:
/* /*
* Go ahead and send the CHECK_CONDITION status for * Go ahead and send the CHECK_CONDITION status for
* any SCSI CDB exceptions that may have occurred, also * any SCSI CDB exceptions that may have occurred.
* handle the SCF_SCSI_RESERVATION_CONFLICT case here as well.
*/ */
if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { if (cmd->sense_reason) {
if (se_cmd->scsi_sense_reason == TCM_RESERVATION_CONFLICT) { if (cmd->sense_reason == TCM_RESERVATION_CONFLICT) {
cmd->i_state = ISTATE_SEND_STATUS; cmd->i_state = ISTATE_SEND_STATUS;
spin_unlock_bh(&cmd->istate_lock); spin_unlock_bh(&cmd->istate_lock);
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, iscsit_add_cmd_to_response_queue(cmd, cmd->conn,
...@@ -956,7 +955,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) ...@@ -956,7 +955,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
* exception * exception
*/ */
return transport_send_check_condition_and_sense(se_cmd, 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 * Special case for delayed CmdSN with Immediate
...@@ -1013,7 +1012,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) ...@@ -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); iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
break; break;
case ISCSI_OP_SCSI_TMFUNC: 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); spin_unlock_bh(&cmd->istate_lock);
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, iscsit_add_cmd_to_response_queue(cmd, cmd->conn,
cmd->i_state); cmd->i_state);
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#include "target_core_alua.h" #include "target_core_alua.h"
#include "target_core_ua.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( static int core_alua_set_tg_pt_secondary_state(
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
struct se_port *port, int explict, int offline); struct se_port *port, int explict, int offline);
...@@ -59,7 +59,8 @@ struct t10_alua_lu_gp *default_lu_gp; ...@@ -59,7 +59,8 @@ struct t10_alua_lu_gp *default_lu_gp;
* *
* See spc4r17 section 6.27 * 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_device *dev = cmd->se_dev;
struct se_port *port; struct se_port *port;
...@@ -68,6 +69,7 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) ...@@ -68,6 +69,7 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd)
unsigned char *buf; unsigned char *buf;
u32 rd_len = 0, off; u32 rd_len = 0, off;
int ext_hdr = (cmd->t_task_cdb[1] & 0x20); int ext_hdr = (cmd->t_task_cdb[1] & 0x20);
/* /*
* Skip over RESERVED area to first Target port group descriptor * Skip over RESERVED area to first Target port group descriptor
* depending on the PARAMETER DATA FORMAT type.. * depending on the PARAMETER DATA FORMAT type..
...@@ -81,10 +83,11 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) ...@@ -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" pr_warn("REPORT TARGET PORT GROUPS allocation length %u too"
" small for %s header\n", cmd->data_length, " small for %s header\n", cmd->data_length,
(ext_hdr) ? "extended" : "normal"); (ext_hdr) ? "extended" : "normal");
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
spin_lock(&dev->t10_alua.tg_pt_gps_lock); spin_lock(&dev->t10_alua.tg_pt_gps_lock);
list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, 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) ...@@ -200,7 +203,8 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd)
* *
* See spc4r17 section 6.35 * 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_device *dev = cmd->se_dev;
struct se_port *port, *l_port = cmd->se_lun->lun_sep; 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) ...@@ -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; struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem;
unsigned char *buf; unsigned char *buf;
unsigned char *ptr; unsigned char *ptr;
sense_reason_t rc;
u32 len = 4; /* Skip over RESERVED area in header */ 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; u16 tg_pt_id, rtpi;
if (!l_port) { if (!l_port)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
}
if (cmd->data_length < 4) { if (cmd->data_length < 4) {
pr_warn("SET TARGET PORT GROUPS parameter list length %u too" pr_warn("SET TARGET PORT GROUPS parameter list length %u too"
" small\n", cmd->data_length); " small\n", cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; return TCM_INVALID_PARAMETER_LIST;
return -EINVAL;
} }
buf = transport_kmap_data_sg(cmd); 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 * 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) ...@@ -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; l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem;
if (!l_tg_pt_gp_mem) { if (!l_tg_pt_gp_mem) {
pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n");
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; rc = TCM_UNSUPPORTED_SCSI_OPCODE;
rc = -EINVAL;
goto out; goto out;
} }
spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 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) ...@@ -242,24 +246,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
if (!l_tg_pt_gp) { if (!l_tg_pt_gp) {
spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 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"); pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n");
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; rc = TCM_UNSUPPORTED_SCSI_OPCODE;
rc = -EINVAL;
goto out; 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); 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" pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
" while TPGS_EXPLICT_ALUA is disabled\n"); " while TPGS_EXPLICT_ALUA is disabled\n");
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; rc = TCM_UNSUPPORTED_SCSI_OPCODE;
rc = -EINVAL;
goto out; goto out;
} }
ptr = &buf[4]; /* Skip over RESERVED area in header */ ptr = &buf[4]; /* Skip over RESERVED area in header */
while (len < cmd->data_length) { while (len < cmd->data_length) {
bool found = false;
alua_access_state = (ptr[0] & 0x0f); alua_access_state = (ptr[0] & 0x0f);
/* /*
* Check the received ALUA access state, and determine if * Check the received ALUA access state, and determine if
...@@ -267,7 +269,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) ...@@ -267,7 +269,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
* access state. * access state.
*/ */
rc = core_alua_check_transition(alua_access_state, &primary); rc = core_alua_check_transition(alua_access_state, &primary);
if (rc != 0) { if (rc) {
/* /*
* If the SET TARGET PORT GROUPS attempts to establish * If the SET TARGET PORT GROUPS attempts to establish
* an invalid combination of target port asymmetric * an invalid combination of target port asymmetric
...@@ -278,11 +280,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) ...@@ -278,11 +280,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
* REQUEST, and the additional sense code set to INVALID * REQUEST, and the additional sense code set to INVALID
* FIELD IN PARAMETER LIST. * FIELD IN PARAMETER LIST.
*/ */
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
rc = -EINVAL;
goto out; goto out;
} }
rc = -1;
/* /*
* If the ASYMMETRIC ACCESS STATE field (see table 267) * If the ASYMMETRIC ACCESS STATE field (see table 267)
* specifies a primary target port asymmetric access state, * specifies a primary target port asymmetric access state,
...@@ -314,11 +314,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) ...@@ -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); atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
smp_mb__after_atomic_inc(); smp_mb__after_atomic_inc();
spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 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, dev, l_port, nacl,
alua_access_state, 1); alua_access_state, 1))
found = true;
spin_lock(&dev->t10_alua.tg_pt_gps_lock); spin_lock(&dev->t10_alua.tg_pt_gps_lock);
atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 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) ...@@ -326,15 +328,6 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
break; break;
} }
spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 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 { } else {
/* /*
* Extact the RELATIVE TARGET PORT IDENTIFIER to identify * Extact the RELATIVE TARGET PORT IDENTIFIER to identify
...@@ -353,25 +346,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) ...@@ -353,25 +346,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
continue; continue;
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
spin_unlock(&dev->se_port_lock); spin_unlock(&dev->se_port_lock);
rc = core_alua_set_tg_pt_secondary_state( if (!core_alua_set_tg_pt_secondary_state(
tg_pt_gp_mem, port, 1, 1); tg_pt_gp_mem, port, 1, 1))
found = true;
spin_lock(&dev->se_port_lock); spin_lock(&dev->se_port_lock);
break; break;
} }
spin_unlock(&dev->se_port_lock); spin_unlock(&dev->se_port_lock);
/* }
* If not matching relative target port identifier can
* be located, throw an exception with ASCQ: if (!found) {
* INVALID_PARAMETER_LIST rc = TCM_INVALID_PARAMETER_LIST;
*/ goto out;
if (rc != 0) {
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
rc = -EINVAL;
goto out;
}
} }
ptr += 4; ptr += 4;
...@@ -526,7 +516,8 @@ static inline int core_alua_state_transition( ...@@ -526,7 +516,8 @@ static inline int core_alua_state_transition(
* return 0: Used to signal success * return 0: Used to signal success
* reutrn -1: Used to signal failure, and invalid cdb field * 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; struct se_device *dev = cmd->se_dev;
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
...@@ -599,8 +590,7 @@ int target_alua_state_check(struct se_cmd *cmd) ...@@ -599,8 +590,7 @@ int target_alua_state_check(struct se_cmd *cmd)
default: default:
pr_err("Unknown ALUA access state: 0x%02x\n", pr_err("Unknown ALUA access state: 0x%02x\n",
out_alua_state); out_alua_state);
ret = -EINVAL; return TCM_INVALID_CDB_FIELD;
break;
} }
out: out:
...@@ -617,15 +607,17 @@ int target_alua_state_check(struct se_cmd *cmd) ...@@ -617,15 +607,17 @@ int target_alua_state_check(struct se_cmd *cmd)
cmd->scsi_asc = 0x04; cmd->scsi_asc = 0x04;
cmd->scsi_ascq = alua_ascq; cmd->scsi_ascq = alua_ascq;
return TCM_CHECK_CONDITION_NOT_READY;
} }
return ret; return 0;
} }
/* /*
* Check implict and explict ALUA state change request. * 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) { switch (state) {
case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED:
...@@ -647,7 +639,7 @@ static int core_alua_check_transition(int state, int *primary) ...@@ -647,7 +639,7 @@ static int core_alua_check_transition(int state, int *primary)
break; break;
default: default:
pr_err("Unknown ALUA access state: 0x%02x\n", state); pr_err("Unknown ALUA access state: 0x%02x\n", state);
return -EINVAL; return TCM_INVALID_PARAMETER_LIST;
} }
return 0; return 0;
......
...@@ -72,8 +72,8 @@ extern struct kmem_cache *t10_alua_lu_gp_mem_cache; ...@@ -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_cache;
extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
extern int target_emulate_report_target_port_groups(struct se_cmd *); extern sense_reason_t 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_set_target_port_groups(struct se_cmd *);
extern int core_alua_check_nonop_delay(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 *, extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *,
struct se_device *, struct se_port *, struct se_device *, struct se_port *,
...@@ -132,6 +132,6 @@ extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *, ...@@ -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 *, extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *,
const char *, size_t); const char *, size_t);
extern int core_setup_alua(struct se_device *); 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 */ #endif /* TARGET_CORE_ALUA_H */
...@@ -54,18 +54,16 @@ static struct se_hba *lun0_hba; ...@@ -54,18 +54,16 @@ static struct se_hba *lun0_hba;
/* not static, needed by tpg.c */ /* not static, needed by tpg.c */
struct se_device *g_lun0_dev; 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_lun *se_lun = NULL;
struct se_session *se_sess = se_cmd->se_sess; struct se_session *se_sess = se_cmd->se_sess;
struct se_device *dev; struct se_device *dev;
unsigned long flags; unsigned long flags;
if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG)
se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; return TCM_NON_EXISTENT_LUN;
se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
return -ENODEV;
}
spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); 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]; 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) ...@@ -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) && if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
(deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) { (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" pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
" Access for 0x%08x\n", " Access for 0x%08x\n",
se_cmd->se_tfo->get_fabric_name(), se_cmd->se_tfo->get_fabric_name(),
unpacked_lun); unpacked_lun);
spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags); 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) 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) ...@@ -109,23 +105,18 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
* MappedLUN=0 exists for this Initiator Port. * MappedLUN=0 exists for this Initiator Port.
*/ */
if (unpacked_lun != 0) { 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" pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN"
" Access for 0x%08x\n", " Access for 0x%08x\n",
se_cmd->se_tfo->get_fabric_name(), se_cmd->se_tfo->get_fabric_name(),
unpacked_lun); unpacked_lun);
return -ENODEV; return TCM_NON_EXISTENT_LUN;
} }
/* /*
* Force WRITE PROTECT for virtual LUN 0 * Force WRITE PROTECT for virtual LUN 0
*/ */
if ((se_cmd->data_direction != DMA_FROM_DEVICE) && if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
(se_cmd->data_direction != DMA_NONE)) { (se_cmd->data_direction != DMA_NONE))
se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; return TCM_WRITE_PROTECTED;
se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
return -EACCES;
}
se_lun = &se_sess->se_tpg->tpg_virt_lun0; se_lun = &se_sess->se_tpg->tpg_virt_lun0;
se_cmd->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) ...@@ -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; struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
unsigned long flags; unsigned long flags;
if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { 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; return -ENODEV;
}
spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); 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]; 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) ...@@ -186,7 +174,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
" Access for 0x%08x\n", " Access for 0x%08x\n",
se_cmd->se_tfo->get_fabric_name(), se_cmd->se_tfo->get_fabric_name(),
unpacked_lun); unpacked_lun);
se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
return -ENODEV; return -ENODEV;
} }
......
...@@ -309,7 +309,8 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, ...@@ -309,7 +309,8 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl,
return 1; 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 se_device *dev = cmd->se_dev;
struct fd_dev *fd_dev = FD_DEV(dev); struct fd_dev *fd_dev = FD_DEV(dev);
...@@ -345,17 +346,16 @@ static int fd_execute_sync_cache(struct se_cmd *cmd) ...@@ -345,17 +346,16 @@ static int fd_execute_sync_cache(struct se_cmd *cmd)
if (immed) if (immed)
return 0; return 0;
if (ret) { if (ret)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
} else { else
target_complete_cmd(cmd, SAM_STAT_GOOD); target_complete_cmd(cmd, SAM_STAT_GOOD);
}
return 0; 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; struct scatterlist *sgl = cmd->t_data_sg;
u32 sgl_nents = cmd->t_data_nents; u32 sgl_nents = cmd->t_data_nents;
...@@ -388,10 +388,9 @@ static int fd_execute_rw(struct se_cmd *cmd) ...@@ -388,10 +388,9 @@ static int fd_execute_rw(struct se_cmd *cmd)
} }
} }
if (ret < 0) { if (ret < 0)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return ret;
}
if (ret) if (ret)
target_complete_cmd(cmd, SAM_STAT_GOOD); target_complete_cmd(cmd, SAM_STAT_GOOD);
return 0; return 0;
...@@ -515,7 +514,8 @@ static struct sbc_ops fd_sbc_ops = { ...@@ -515,7 +514,8 @@ static struct sbc_ops fd_sbc_ops = {
.execute_sync_cache = fd_execute_sync_cache, .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); return sbc_parse_cdb(cmd, &fd_sbc_ops);
} }
......
...@@ -261,13 +261,10 @@ static void iblock_end_io_flush(struct bio *bio, int err) ...@@ -261,13 +261,10 @@ static void iblock_end_io_flush(struct bio *bio, int err)
pr_err("IBLOCK: cache flush failed: %d\n", err); pr_err("IBLOCK: cache flush failed: %d\n", err);
if (cmd) { if (cmd) {
if (err) { if (err)
cmd->scsi_sense_reason =
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
} else { else
target_complete_cmd(cmd, SAM_STAT_GOOD); target_complete_cmd(cmd, SAM_STAT_GOOD);
}
} }
bio_put(bio); bio_put(bio);
...@@ -277,7 +274,8 @@ static void iblock_end_io_flush(struct bio *bio, int err) ...@@ -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 * Implement SYCHRONIZE CACHE. Note that we can't handle lba ranges and must
* always flush the whole cache. * 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); struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev);
int immed = (cmd->t_task_cdb[1] & 0x2); int immed = (cmd->t_task_cdb[1] & 0x2);
...@@ -299,7 +297,8 @@ static int iblock_execute_sync_cache(struct se_cmd *cmd) ...@@ -299,7 +297,8 @@ static int iblock_execute_sync_cache(struct se_cmd *cmd)
return 0; 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 se_device *dev = cmd->se_dev;
struct iblock_dev *ib_dev = IBLOCK_DEV(dev); struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
...@@ -307,17 +306,18 @@ static int iblock_execute_unmap(struct se_cmd *cmd) ...@@ -307,17 +306,18 @@ static int iblock_execute_unmap(struct se_cmd *cmd)
sector_t lba; sector_t lba;
int size; int size;
u32 range; u32 range;
int ret = 0; sense_reason_t ret = 0;
int dl, bd_dl; int dl, bd_dl, err;
if (cmd->data_length < 8) { if (cmd->data_length < 8) {
pr_warn("UNMAP parameter list length %u too small\n", pr_warn("UNMAP parameter list length %u too small\n",
cmd->data_length); cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; return TCM_INVALID_PARAMETER_LIST;
return -EINVAL;
} }
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
dl = get_unaligned_be16(&buf[0]); dl = get_unaligned_be16(&buf[0]);
bd_dl = get_unaligned_be16(&buf[2]); bd_dl = get_unaligned_be16(&buf[2]);
...@@ -330,8 +330,7 @@ static int iblock_execute_unmap(struct se_cmd *cmd) ...@@ -330,8 +330,7 @@ static int iblock_execute_unmap(struct se_cmd *cmd)
size = bd_dl; size = bd_dl;
if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) {
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto err; goto err;
} }
...@@ -347,22 +346,21 @@ static int iblock_execute_unmap(struct se_cmd *cmd) ...@@ -347,22 +346,21 @@ static int iblock_execute_unmap(struct se_cmd *cmd)
(unsigned long long)lba, range); (unsigned long long)lba, range);
if (range > dev->dev_attrib.max_unmap_lba_count) { if (range > dev->dev_attrib.max_unmap_lba_count) {
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto err; goto err;
} }
if (lba + range > dev->transport->get_blocks(dev) + 1) { if (lba + range > dev->transport->get_blocks(dev) + 1) {
cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE; ret = TCM_ADDRESS_OUT_OF_RANGE;
ret = -EINVAL;
goto err; 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); GFP_KERNEL, 0);
if (ret < 0) { if (err < 0) {
pr_err("blkdev_issue_discard() failed: %d\n", pr_err("blkdev_issue_discard() failed: %d\n",
ret); err);
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto err; goto err;
} }
...@@ -377,7 +375,8 @@ static int iblock_execute_unmap(struct se_cmd *cmd) ...@@ -377,7 +375,8 @@ static int iblock_execute_unmap(struct se_cmd *cmd)
return ret; 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); struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev);
int ret; int ret;
...@@ -387,7 +386,7 @@ static int iblock_execute_write_same(struct se_cmd *cmd) ...@@ -387,7 +386,7 @@ static int iblock_execute_write_same(struct se_cmd *cmd)
0); 0);
if (ret < 0) { if (ret < 0) {
pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n"); pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
return ret; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
target_complete_cmd(cmd, GOOD); target_complete_cmd(cmd, GOOD);
...@@ -552,7 +551,8 @@ static void iblock_submit_bios(struct bio_list *list, int rw) ...@@ -552,7 +551,8 @@ static void iblock_submit_bios(struct bio_list *list, int rw)
blk_finish_plug(&plug); 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; struct scatterlist *sgl = cmd->t_data_sg;
u32 sgl_nents = cmd->t_data_nents; u32 sgl_nents = cmd->t_data_nents;
...@@ -598,8 +598,7 @@ static int iblock_execute_rw(struct se_cmd *cmd) ...@@ -598,8 +598,7 @@ static int iblock_execute_rw(struct se_cmd *cmd)
else { else {
pr_err("Unsupported SCSI -> BLOCK LBA conversion:" pr_err("Unsupported SCSI -> BLOCK LBA conversion:"
" %u\n", dev->dev_attrib.block_size); " %u\n", dev->dev_attrib.block_size);
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -ENOSYS;
} }
ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
...@@ -659,9 +658,8 @@ static int iblock_execute_rw(struct se_cmd *cmd) ...@@ -659,9 +658,8 @@ static int iblock_execute_rw(struct se_cmd *cmd)
bio_put(bio); bio_put(bio);
fail_free_ibr: fail_free_ibr:
kfree(ibr); kfree(ibr);
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
fail: fail:
return -ENOMEM; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
static sector_t iblock_get_blocks(struct se_device *dev) static sector_t iblock_get_blocks(struct se_device *dev)
...@@ -706,7 +704,8 @@ static struct sbc_ops iblock_sbc_ops = { ...@@ -706,7 +704,8 @@ static struct sbc_ops iblock_sbc_ops = {
.execute_unmap = iblock_execute_unmap, .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); return sbc_parse_cdb(cmd, &iblock_sbc_ops);
} }
......
...@@ -101,7 +101,7 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); ...@@ -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); bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags);
int transport_clear_lun_from_sessions(struct se_lun *); int transport_clear_lun_from_sessions(struct se_lun *);
void transport_send_task_abort(struct se_cmd *); 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); void target_qf_do_work(struct work_struct *work);
/* target_core_stat.c */ /* target_core_stat.c */
......
...@@ -68,7 +68,8 @@ int core_pr_dump_initiator_port( ...@@ -68,7 +68,8 @@ int core_pr_dump_initiator_port(
static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *,
struct t10_pr_registration *, int); 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_device *dev = cmd->se_dev;
struct se_session *sess = cmd->se_sess; struct se_session *sess = cmd->se_sess;
...@@ -86,11 +87,11 @@ static int target_scsi2_reservation_check(struct se_cmd *cmd) ...@@ -86,11 +87,11 @@ static int target_scsi2_reservation_check(struct se_cmd *cmd)
return 0; return 0;
if (dev->dev_reserved_node_acl != sess->se_node_acl) if (dev->dev_reserved_node_acl != sess->se_node_acl)
return -EBUSY; return TCM_RESERVATION_CONFLICT;
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) {
if (dev->dev_res_bin_isid != sess->sess_bin_isid) if (dev->dev_res_bin_isid != sess->sess_bin_isid)
return -EBUSY; return TCM_RESERVATION_CONFLICT;
} }
return 0; return 0;
...@@ -165,32 +166,28 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) ...@@ -165,32 +166,28 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd)
pr_err("Received legacy SPC-2 RESERVE/RELEASE" pr_err("Received legacy SPC-2 RESERVE/RELEASE"
" while active SPC-3 registrations exist," " while active SPC-3 registrations exist,"
" returning RESERVATION_CONFLICT\n"); " returning RESERVATION_CONFLICT\n");
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
return -EBUSY; return -EBUSY;
} }
return 0; return 0;
} }
int target_scsi2_reservation_release(struct se_cmd *cmd) sense_reason_t
target_scsi2_reservation_release(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_session *sess = cmd->se_sess; struct se_session *sess = cmd->se_sess;
struct se_portal_group *tpg; struct se_portal_group *tpg;
int ret = 0, rc; int rc;
if (!sess || !sess->se_tpg) if (!sess || !sess->se_tpg)
goto out; goto out;
rc = target_check_scsi2_reservation_conflict(cmd); rc = target_check_scsi2_reservation_conflict(cmd);
if (rc == 1) if (rc == 1)
goto out; goto out;
else if (rc < 0) { if (rc < 0)
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
ret = -EINVAL;
goto out;
}
ret = 0;
spin_lock(&dev->dev_reservation_lock); spin_lock(&dev->dev_reservation_lock);
if (!dev->dev_reserved_node_acl || !sess) if (!dev->dev_reserved_node_acl || !sess)
goto out_unlock; goto out_unlock;
...@@ -216,25 +213,24 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) ...@@ -216,25 +213,24 @@ int target_scsi2_reservation_release(struct se_cmd *cmd)
out_unlock: out_unlock:
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
out: out:
if (!ret) target_complete_cmd(cmd, GOOD);
target_complete_cmd(cmd, GOOD); return 0;
return ret;
} }
int target_scsi2_reservation_reserve(struct se_cmd *cmd) sense_reason_t
target_scsi2_reservation_reserve(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_session *sess = cmd->se_sess; struct se_session *sess = cmd->se_sess;
struct se_portal_group *tpg; struct se_portal_group *tpg;
int ret = 0, rc; sense_reason_t ret = 0;
int rc;
if ((cmd->t_task_cdb[1] & 0x01) && if ((cmd->t_task_cdb[1] & 0x01) &&
(cmd->t_task_cdb[1] & 0x02)) { (cmd->t_task_cdb[1] & 0x02)) {
pr_err("LongIO and Obselete Bits set, returning" pr_err("LongIO and Obselete Bits set, returning"
" ILLEGAL_REQUEST\n"); " ILLEGAL_REQUEST\n");
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; return TCM_UNSUPPORTED_SCSI_OPCODE;
ret = -EINVAL;
goto out;
} }
/* /*
* This is currently the case for target_core_mod passthrough struct se_cmd * This is currently the case for target_core_mod passthrough struct se_cmd
...@@ -245,13 +241,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) ...@@ -245,13 +241,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd)
rc = target_check_scsi2_reservation_conflict(cmd); rc = target_check_scsi2_reservation_conflict(cmd);
if (rc == 1) if (rc == 1)
goto out; goto out;
else if (rc < 0) {
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
ret = -EINVAL;
goto out;
}
ret = 0; if (rc < 0)
return TCM_RESERVATION_CONFLICT;
tpg = sess->se_tpg; tpg = sess->se_tpg;
spin_lock(&dev->dev_reservation_lock); spin_lock(&dev->dev_reservation_lock);
if (dev->dev_reserved_node_acl && if (dev->dev_reserved_node_acl &&
...@@ -265,8 +258,7 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) ...@@ -265,8 +258,7 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd)
" from %s \n", cmd->se_lun->unpacked_lun, " from %s \n", cmd->se_lun->unpacked_lun,
cmd->se_deve->mapped_lun, cmd->se_deve->mapped_lun,
sess->se_node_acl->initiatorname); sess->se_node_acl->initiatorname);
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; ret = TCM_RESERVATION_CONFLICT;
ret = -EINVAL;
goto out_unlock; goto out_unlock;
} }
...@@ -536,7 +528,8 @@ static int core_scsi3_pr_seq_non_holder( ...@@ -536,7 +528,8 @@ static int core_scsi3_pr_seq_non_holder(
return 1; /* Conflict by default */ return 1; /* Conflict by default */
} }
static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) static sense_reason_t
target_scsi3_pr_reservation_check(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_session *sess = cmd->se_sess; struct se_session *sess = cmd->se_sess;
...@@ -562,7 +555,7 @@ static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) ...@@ -562,7 +555,7 @@ static int target_scsi3_pr_reservation_check(struct se_cmd *cmd)
check_nonholder: check_nonholder:
if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type))
return -EBUSY; return TCM_RESERVATION_CONFLICT;
return 0; return 0;
} }
...@@ -1435,7 +1428,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve) ...@@ -1435,7 +1428,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
smp_mb__after_atomic_dec(); smp_mb__after_atomic_dec();
} }
static int core_scsi3_decode_spec_i_port( static sense_reason_t
core_scsi3_decode_spec_i_port(
struct se_cmd *cmd, struct se_cmd *cmd,
struct se_portal_group *tpg, struct se_portal_group *tpg,
unsigned char *l_isid, unsigned char *l_isid,
...@@ -1457,8 +1451,9 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1457,8 +1451,9 @@ static int core_scsi3_decode_spec_i_port(
unsigned char *buf; unsigned char *buf;
unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident; unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident;
char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN];
sense_reason_t ret;
u32 tpdl, tid_len = 0; u32 tpdl, tid_len = 0;
int ret, dest_local_nexus, prf_isid; int dest_local_nexus, prf_isid;
u32 dest_rtpi = 0; u32 dest_rtpi = 0;
memset(dest_iport, 0, 64); memset(dest_iport, 0, 64);
...@@ -1473,8 +1468,7 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1473,8 +1468,7 @@ static int core_scsi3_decode_spec_i_port(
tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL);
if (!tidh_new) { if (!tidh_new) {
pr_err("Unable to allocate tidh_new\n"); pr_err("Unable to allocate tidh_new\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
} }
INIT_LIST_HEAD(&tidh_new->dest_list); INIT_LIST_HEAD(&tidh_new->dest_list);
tidh_new->dest_tpg = tpg; tidh_new->dest_tpg = tpg;
...@@ -1486,8 +1480,7 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1486,8 +1480,7 @@ static int core_scsi3_decode_spec_i_port(
sa_res_key, all_tg_pt, aptpl); sa_res_key, all_tg_pt, aptpl);
if (!local_pr_reg) { if (!local_pr_reg) {
kfree(tidh_new); kfree(tidh_new);
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -ENOMEM;
} }
tidh_new->dest_pr_reg = local_pr_reg; tidh_new->dest_pr_reg = local_pr_reg;
/* /*
...@@ -1501,12 +1494,16 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1501,12 +1494,16 @@ static int core_scsi3_decode_spec_i_port(
if (cmd->data_length < 28) { if (cmd->data_length < 28) {
pr_warn("SPC-PR: Received PR OUT parameter list" pr_warn("SPC-PR: Received PR OUT parameter list"
" length too small: %u\n", cmd->data_length); " length too small: %u\n", cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out; goto out;
} }
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf) {
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto out;
}
/* /*
* For a PERSISTENT RESERVE OUT specify initiator ports payload, * For a PERSISTENT RESERVE OUT specify initiator ports payload,
* first extract TransportID Parameter Data Length, and make sure * first extract TransportID Parameter Data Length, and make sure
...@@ -1521,9 +1518,8 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1521,9 +1518,8 @@ static int core_scsi3_decode_spec_i_port(
pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header" pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header"
" does not equal CDB data_length: %u\n", tpdl, " does not equal CDB data_length: %u\n", tpdl,
cmd->data_length); cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL; goto out_unmap;
goto out;
} }
/* /*
* Start processing the received transport IDs using the * Start processing the received transport IDs using the
...@@ -1566,16 +1562,13 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1566,16 +1562,13 @@ static int core_scsi3_decode_spec_i_port(
smp_mb__after_atomic_inc(); smp_mb__after_atomic_inc();
spin_unlock(&dev->se_port_lock); spin_unlock(&dev->se_port_lock);
ret = core_scsi3_tpg_depend_item(tmp_tpg); if (core_scsi3_tpg_depend_item(tmp_tpg)) {
if (ret != 0) {
pr_err(" core_scsi3_tpg_depend_item()" pr_err(" core_scsi3_tpg_depend_item()"
" for tmp_tpg\n"); " for tmp_tpg\n");
atomic_dec(&tmp_tpg->tpg_pr_ref_count); atomic_dec(&tmp_tpg->tpg_pr_ref_count);
smp_mb__after_atomic_dec(); smp_mb__after_atomic_dec();
cmd->scsi_sense_reason = ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out_unmap;
ret = -EINVAL;
goto out;
} }
/* /*
* Locate the destination initiator ACL to be registered * Locate the destination initiator ACL to be registered
...@@ -1597,17 +1590,14 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1597,17 +1590,14 @@ static int core_scsi3_decode_spec_i_port(
continue; continue;
} }
ret = core_scsi3_nodeacl_depend_item(dest_node_acl); if (core_scsi3_nodeacl_depend_item(dest_node_acl)) {
if (ret != 0) {
pr_err("configfs_depend_item() failed" pr_err("configfs_depend_item() failed"
" for dest_node_acl->acl_group\n"); " for dest_node_acl->acl_group\n");
atomic_dec(&dest_node_acl->acl_pr_ref_count); atomic_dec(&dest_node_acl->acl_pr_ref_count);
smp_mb__after_atomic_dec(); smp_mb__after_atomic_dec();
core_scsi3_tpg_undepend_item(tmp_tpg); core_scsi3_tpg_undepend_item(tmp_tpg);
cmd->scsi_sense_reason = ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out_unmap;
ret = -EINVAL;
goto out;
} }
dest_tpg = tmp_tpg; dest_tpg = tmp_tpg;
...@@ -1624,9 +1614,8 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1624,9 +1614,8 @@ static int core_scsi3_decode_spec_i_port(
if (!dest_tpg) { if (!dest_tpg) {
pr_err("SPC-3 PR SPEC_I_PT: Unable to locate" pr_err("SPC-3 PR SPEC_I_PT: Unable to locate"
" dest_tpg\n"); " dest_tpg\n");
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL; goto out_unmap;
goto out;
} }
pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u" pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u"
...@@ -1639,9 +1628,8 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1639,9 +1628,8 @@ static int core_scsi3_decode_spec_i_port(
" %u for Transport ID: %s\n", tid_len, ptr); " %u for Transport ID: %s\n", tid_len, ptr);
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
core_scsi3_tpg_undepend_item(dest_tpg); core_scsi3_tpg_undepend_item(dest_tpg);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL; goto out_unmap;
goto out;
} }
/* /*
* Locate the desintation struct se_dev_entry pointer for matching * Locate the desintation struct se_dev_entry pointer for matching
...@@ -1658,23 +1646,19 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1658,23 +1646,19 @@ static int core_scsi3_decode_spec_i_port(
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
core_scsi3_tpg_undepend_item(dest_tpg); core_scsi3_tpg_undepend_item(dest_tpg);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL; goto out_unmap;
goto out;
} }
ret = core_scsi3_lunacl_depend_item(dest_se_deve); if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
if (ret < 0) {
pr_err("core_scsi3_lunacl_depend_item()" pr_err("core_scsi3_lunacl_depend_item()"
" failed\n"); " failed\n");
atomic_dec(&dest_se_deve->pr_ref_count); atomic_dec(&dest_se_deve->pr_ref_count);
smp_mb__after_atomic_dec(); smp_mb__after_atomic_dec();
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
core_scsi3_tpg_undepend_item(dest_tpg); core_scsi3_tpg_undepend_item(dest_tpg);
cmd->scsi_sense_reason = ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out_unmap;
ret = -EINVAL;
goto out;
} }
pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s" pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s"
...@@ -1710,10 +1694,8 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1710,10 +1694,8 @@ static int core_scsi3_decode_spec_i_port(
core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_lunacl_undepend_item(dest_se_deve);
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
core_scsi3_tpg_undepend_item(dest_tpg); core_scsi3_tpg_undepend_item(dest_tpg);
cmd->scsi_sense_reason = ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out_unmap;
ret = -ENOMEM;
goto out;
} }
INIT_LIST_HEAD(&tidh_new->dest_list); INIT_LIST_HEAD(&tidh_new->dest_list);
tidh_new->dest_tpg = dest_tpg; tidh_new->dest_tpg = dest_tpg;
...@@ -1744,9 +1726,8 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1744,9 +1726,8 @@ static int core_scsi3_decode_spec_i_port(
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
core_scsi3_tpg_undepend_item(dest_tpg); core_scsi3_tpg_undepend_item(dest_tpg);
kfree(tidh_new); kfree(tidh_new);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL; goto out_unmap;
goto out;
} }
tidh_new->dest_pr_reg = dest_pr_reg; tidh_new->dest_pr_reg = dest_pr_reg;
list_add_tail(&tidh_new->dest_list, &tid_dest_list); list_add_tail(&tidh_new->dest_list, &tid_dest_list);
...@@ -1804,8 +1785,9 @@ static int core_scsi3_decode_spec_i_port( ...@@ -1804,8 +1785,9 @@ static int core_scsi3_decode_spec_i_port(
} }
return 0; return 0;
out: out_unmap:
transport_kunmap_data_sg(cmd); transport_kunmap_data_sg(cmd);
out:
/* /*
* For the failure case, release everything from tid_dest_list * For the failure case, release everything from tid_dest_list
* including *dest_pr_reg and the configfs dependances.. * including *dest_pr_reg and the configfs dependances..
...@@ -2020,14 +2002,15 @@ static int __core_scsi3_write_aptpl_to_file( ...@@ -2020,14 +2002,15 @@ static int __core_scsi3_write_aptpl_to_file(
return 0; return 0;
} }
static int core_scsi3_update_and_write_aptpl( static int
struct se_device *dev, core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf,
unsigned char *in_buf, u32 in_pr_aptpl_buf_len)
u32 in_pr_aptpl_buf_len)
{ {
unsigned char null_buf[64], *buf; unsigned char null_buf[64], *buf;
u32 pr_aptpl_buf_len; u32 pr_aptpl_buf_len;
int ret, clear_aptpl_metadata = 0; int clear_aptpl_metadata = 0;
int ret;
/* /*
* Can be called with a NULL pointer from PROUT service action CLEAR * Can be called with a NULL pointer from PROUT service action CLEAR
*/ */
...@@ -2049,25 +2032,17 @@ static int core_scsi3_update_and_write_aptpl( ...@@ -2049,25 +2032,17 @@ static int core_scsi3_update_and_write_aptpl(
clear_aptpl_metadata); clear_aptpl_metadata);
if (ret != 0) if (ret != 0)
return ret; return ret;
/* /*
* __core_scsi3_write_aptpl_to_file() will call strlen() * __core_scsi3_write_aptpl_to_file() will call strlen()
* on the passed buf to determine pr_aptpl_buf_len. * on the passed buf to determine pr_aptpl_buf_len.
*/ */
ret = __core_scsi3_write_aptpl_to_file(dev, buf, 0); return __core_scsi3_write_aptpl_to_file(dev, buf, 0);
if (ret != 0)
return ret;
return ret;
} }
static int core_scsi3_emulate_pro_register( static sense_reason_t
struct se_cmd *cmd, core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
u64 res_key, int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key)
u64 sa_res_key,
int aptpl,
int all_tg_pt,
int spec_i_pt,
int ignore_key)
{ {
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
...@@ -2079,12 +2054,12 @@ static int core_scsi3_emulate_pro_register( ...@@ -2079,12 +2054,12 @@ static int core_scsi3_emulate_pro_register(
/* Used for APTPL metadata w/ UNREGISTER */ /* Used for APTPL metadata w/ UNREGISTER */
unsigned char *pr_aptpl_buf = NULL; unsigned char *pr_aptpl_buf = NULL;
unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
int pr_holder = 0, ret = 0, type; sense_reason_t ret;
int pr_holder = 0, type;
if (!se_sess || !se_lun) { if (!se_sess || !se_lun) {
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
} }
se_tpg = se_sess->se_tpg; se_tpg = se_sess->se_tpg;
se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
...@@ -2103,8 +2078,7 @@ static int core_scsi3_emulate_pro_register( ...@@ -2103,8 +2078,7 @@ static int core_scsi3_emulate_pro_register(
if (res_key) { if (res_key) {
pr_warn("SPC-3 PR: Reservation Key non-zero" pr_warn("SPC-3 PR: Reservation Key non-zero"
" for SA REGISTER, returning CONFLICT\n"); " for SA REGISTER, returning CONFLICT\n");
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
return -EINVAL;
} }
/* /*
* Do nothing but return GOOD status. * Do nothing but return GOOD status.
...@@ -2118,15 +2092,13 @@ static int core_scsi3_emulate_pro_register( ...@@ -2118,15 +2092,13 @@ static int core_scsi3_emulate_pro_register(
* Port Endpoint that the PRO was received from on the * Port Endpoint that the PRO was received from on the
* Logical Unit of the SCSI device server. * Logical Unit of the SCSI device server.
*/ */
ret = core_scsi3_alloc_registration(cmd->se_dev, if (core_scsi3_alloc_registration(cmd->se_dev,
se_sess->se_node_acl, se_deve, isid_ptr, se_sess->se_node_acl, se_deve, isid_ptr,
sa_res_key, all_tg_pt, aptpl, sa_res_key, all_tg_pt, aptpl,
ignore_key, 0); ignore_key, 0)) {
if (ret != 0) {
pr_err("Unable to allocate" pr_err("Unable to allocate"
" struct t10_pr_registration\n"); " struct t10_pr_registration\n");
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; return TCM_INVALID_PARAMETER_LIST;
return -EINVAL;
} }
} else { } else {
/* /*
...@@ -2160,201 +2132,192 @@ static int core_scsi3_emulate_pro_register( ...@@ -2160,201 +2132,192 @@ static int core_scsi3_emulate_pro_register(
pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev,
se_sess->se_node_acl, se_sess); se_sess->se_node_acl, se_sess);
ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, if (core_scsi3_update_and_write_aptpl(cmd->se_dev,
&pr_reg->pr_aptpl_buf[0], &pr_reg->pr_aptpl_buf[0],
pr_tmpl->pr_aptpl_buf_len); pr_tmpl->pr_aptpl_buf_len)) {
if (!ret) {
pr_tmpl->pr_aptpl_active = 1; pr_tmpl->pr_aptpl_active = 1;
pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n");
} }
core_scsi3_put_pr_reg(pr_reg); goto out_put_pr_reg;
return ret; }
} else {
/* /*
* Locate the existing *pr_reg via struct se_node_acl pointers * Locate the existing *pr_reg via struct se_node_acl pointers
*/ */
pr_reg = pr_reg_e; pr_reg = pr_reg_e;
type = pr_reg->pr_res_type; type = pr_reg->pr_res_type;
if (!ignore_key) { if (!ignore_key) {
if (res_key != pr_reg->pr_res_key) { if (res_key != pr_reg->pr_res_key) {
pr_err("SPC-3 PR REGISTER: Received" pr_err("SPC-3 PR REGISTER: Received"
" res_key: 0x%016Lx does not match" " res_key: 0x%016Lx does not match"
" existing SA REGISTER res_key:" " existing SA REGISTER res_key:"
" 0x%016Lx\n", res_key, " 0x%016Lx\n", res_key,
pr_reg->pr_res_key); pr_reg->pr_res_key);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_RESERVATION_CONFLICT;
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; goto out_put_pr_reg;
return -EINVAL;
}
} }
if (spec_i_pt) { }
pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT"
" set while sa_res_key=0\n"); if (spec_i_pt) {
core_scsi3_put_pr_reg(pr_reg); pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT"
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; " set while sa_res_key=0\n");
return -EINVAL; ret = TCM_INVALID_PARAMETER_LIST;
goto out_put_pr_reg;
}
/*
* An existing ALL_TG_PT=1 registration being released
* must also set ALL_TG_PT=1 in the incoming PROUT.
*/
if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) {
pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1"
" registration exists, but ALL_TG_PT=1 bit not"
" present in received PROUT\n");
ret = TCM_INVALID_CDB_FIELD;
goto out_put_pr_reg;
}
/*
* Allocate APTPL metadata buffer used for UNREGISTER ops
*/
if (aptpl) {
pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len,
GFP_KERNEL);
if (!pr_aptpl_buf) {
pr_err("Unable to allocate"
" pr_aptpl_buf\n");
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto out_put_pr_reg;
} }
/* }
* An existing ALL_TG_PT=1 registration being released
* must also set ALL_TG_PT=1 in the incoming PROUT. /*
*/ * sa_res_key=0 Unregister Reservation Key for registered I_T
if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { * Nexus sa_res_key=1 Change Reservation Key for registered I_T
pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" * Nexus.
" registration exists, but ALL_TG_PT=1 bit not" */
" present in received PROUT\n"); if (!sa_res_key) {
core_scsi3_put_pr_reg(pr_reg); pr_holder = core_scsi3_check_implict_release(
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; cmd->se_dev, pr_reg);
return -EINVAL; if (pr_holder < 0) {
kfree(pr_aptpl_buf);
ret = TCM_RESERVATION_CONFLICT;
goto out_put_pr_reg;
} }
spin_lock(&pr_tmpl->registration_lock);
/* /*
* Allocate APTPL metadata buffer used for UNREGISTER ops * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port
* and matching pr_res_key.
*/ */
if (aptpl) { if (pr_reg->pr_reg_all_tg_pt) {
pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, list_for_each_entry_safe(pr_reg_p, pr_reg_tmp,
GFP_KERNEL); &pr_tmpl->registration_list,
if (!pr_aptpl_buf) { pr_reg_list) {
pr_err("Unable to allocate"
" pr_aptpl_buf\n"); if (!pr_reg_p->pr_reg_all_tg_pt)
core_scsi3_put_pr_reg(pr_reg); continue;
cmd->scsi_sense_reason = if (pr_reg_p->pr_res_key != res_key)
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; continue;
return -EINVAL; if (pr_reg == pr_reg_p)
continue;
if (strcmp(pr_reg->pr_reg_nacl->initiatorname,
pr_reg_p->pr_reg_nacl->initiatorname))
continue;
__core_scsi3_free_registration(dev,
pr_reg_p, NULL, 0);
} }
} }
/* /*
* sa_res_key=0 Unregister Reservation Key for registered I_T * Release the calling I_T Nexus registration now..
* Nexus sa_res_key=1 Change Reservation Key for registered I_T
* Nexus.
*/ */
if (!sa_res_key) { __core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1);
pr_holder = core_scsi3_check_implict_release(
cmd->se_dev, pr_reg);
if (pr_holder < 0) {
kfree(pr_aptpl_buf);
core_scsi3_put_pr_reg(pr_reg);
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
return -EINVAL;
}
spin_lock(&pr_tmpl->registration_lock);
/*
* Release all ALL_TG_PT=1 for the matching SCSI Initiator Port
* and matching pr_res_key.
*/
if (pr_reg->pr_reg_all_tg_pt) {
list_for_each_entry_safe(pr_reg_p, pr_reg_tmp,
&pr_tmpl->registration_list,
pr_reg_list) {
if (!pr_reg_p->pr_reg_all_tg_pt)
continue;
if (pr_reg_p->pr_res_key != res_key) /*
continue; * From spc4r17, section 5.7.11.3 Unregistering
*
if (pr_reg == pr_reg_p) * If the persistent reservation is a registrants only
continue; * type, the device server shall establish a unit
* attention condition for the initiator port associated
if (strcmp(pr_reg->pr_reg_nacl->initiatorname, * with every registered I_T nexus except for the I_T
pr_reg_p->pr_reg_nacl->initiatorname)) * nexus on which the PERSISTENT RESERVE OUT command was
continue; * received, with the additional sense code set to
* RESERVATIONS RELEASED.
__core_scsi3_free_registration(dev, */
pr_reg_p, NULL, 0); if (pr_holder &&
} (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY ||
} type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) {
/* list_for_each_entry(pr_reg_p,
* Release the calling I_T Nexus registration now.. &pr_tmpl->registration_list,
*/ pr_reg_list) {
__core_scsi3_free_registration(cmd->se_dev, pr_reg,
NULL, 1); core_scsi3_ua_allocate(
/* pr_reg_p->pr_reg_nacl,
* From spc4r17, section 5.7.11.3 Unregistering pr_reg_p->pr_res_mapped_lun,
* 0x2A,
* If the persistent reservation is a registrants only ASCQ_2AH_RESERVATIONS_RELEASED);
* type, the device server shall establish a unit
* attention condition for the initiator port associated
* with every registered I_T nexus except for the I_T
* nexus on which the PERSISTENT RESERVE OUT command was
* received, with the additional sense code set to
* RESERVATIONS RELEASED.
*/
if (pr_holder &&
((type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) ||
(type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY))) {
list_for_each_entry(pr_reg_p,
&pr_tmpl->registration_list,
pr_reg_list) {
core_scsi3_ua_allocate(
pr_reg_p->pr_reg_nacl,
pr_reg_p->pr_res_mapped_lun,
0x2A,
ASCQ_2AH_RESERVATIONS_RELEASED);
}
} }
spin_unlock(&pr_tmpl->registration_lock); }
spin_unlock(&pr_tmpl->registration_lock);
if (!aptpl) { if (!aptpl) {
pr_tmpl->pr_aptpl_active = 0; pr_tmpl->pr_aptpl_active = 0;
core_scsi3_update_and_write_aptpl(dev, NULL, 0); core_scsi3_update_and_write_aptpl(dev, NULL, 0);
pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
" for UNREGISTER\n"); " for UNREGISTER\n");
return 0; return 0;
} }
ret = core_scsi3_update_and_write_aptpl(dev, if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0],
&pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) {
pr_tmpl->pr_aptpl_buf_len); pr_tmpl->pr_aptpl_active = 1;
if (!ret) { pr_debug("SPC-3 PR: Set APTPL Bit Activated"
pr_tmpl->pr_aptpl_active = 1; " for UNREGISTER\n");
pr_debug("SPC-3 PR: Set APTPL Bit Activated" }
" for UNREGISTER\n");
}
kfree(pr_aptpl_buf); goto out_free_aptpl_buf;
return ret; }
} else {
/*
* Increment PRgeneration counter for struct se_device"
* upon a successful REGISTER, see spc4r17 section 6.3.2
* READ_KEYS service action.
*/
pr_reg->pr_res_generation = core_scsi3_pr_generation(
cmd->se_dev);
pr_reg->pr_res_key = sa_res_key;
pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
" Key for %s to: 0x%016Lx PRgeneration:"
" 0x%08x\n", cmd->se_tfo->get_fabric_name(),
(ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "",
pr_reg->pr_reg_nacl->initiatorname,
pr_reg->pr_res_key, pr_reg->pr_res_generation);
if (!aptpl) {
pr_tmpl->pr_aptpl_active = 0;
core_scsi3_update_and_write_aptpl(dev, NULL, 0);
core_scsi3_put_pr_reg(pr_reg);
pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
" for REGISTER\n");
return 0;
}
ret = core_scsi3_update_and_write_aptpl(dev, /*
&pr_aptpl_buf[0], * Increment PRgeneration counter for struct se_device"
pr_tmpl->pr_aptpl_buf_len); * upon a successful REGISTER, see spc4r17 section 6.3.2
if (!ret) { * READ_KEYS service action.
pr_tmpl->pr_aptpl_active = 1; */
pr_debug("SPC-3 PR: Set APTPL Bit Activated" pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev);
" for REGISTER\n"); pr_reg->pr_res_key = sa_res_key;
} pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
" Key for %s to: 0x%016Lx PRgeneration:"
" 0x%08x\n", cmd->se_tfo->get_fabric_name(),
(ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "",
pr_reg->pr_reg_nacl->initiatorname,
pr_reg->pr_res_key, pr_reg->pr_res_generation);
kfree(pr_aptpl_buf); if (!aptpl) {
core_scsi3_put_pr_reg(pr_reg); pr_tmpl->pr_aptpl_active = 0;
} core_scsi3_update_and_write_aptpl(dev, NULL, 0);
pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
" for REGISTER\n");
ret = 0;
goto out_put_pr_reg;
} }
return 0;
if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0],
pr_tmpl->pr_aptpl_buf_len)) {
pr_tmpl->pr_aptpl_active = 1;
pr_debug("SPC-3 PR: Set APTPL Bit Activated"
" for REGISTER\n");
}
out_free_aptpl_buf:
kfree(pr_aptpl_buf);
ret = 0;
out_put_pr_reg:
core_scsi3_put_pr_reg(pr_reg);
return ret;
} }
unsigned char *core_scsi3_pr_dump_type(int type) unsigned char *core_scsi3_pr_dump_type(int type)
...@@ -2379,26 +2342,23 @@ unsigned char *core_scsi3_pr_dump_type(int type) ...@@ -2379,26 +2342,23 @@ unsigned char *core_scsi3_pr_dump_type(int type)
return "Unknown SPC-3 PR Type"; return "Unknown SPC-3 PR Type";
} }
static int core_scsi3_pro_reserve( static sense_reason_t
struct se_cmd *cmd, core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
struct se_device *dev,
int type,
int scope,
u64 res_key)
{ {
struct se_device *dev = cmd->se_dev;
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
struct se_lun *se_lun = cmd->se_lun; struct se_lun *se_lun = cmd->se_lun;
struct t10_pr_registration *pr_reg, *pr_res_holder; struct t10_pr_registration *pr_reg, *pr_res_holder;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
char i_buf[PR_REG_ISID_ID_LEN]; char i_buf[PR_REG_ISID_ID_LEN];
int ret, prf_isid; sense_reason_t ret;
int prf_isid;
memset(i_buf, 0, PR_REG_ISID_ID_LEN); memset(i_buf, 0, PR_REG_ISID_ID_LEN);
if (!se_sess || !se_lun) { if (!se_sess || !se_lun) {
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
} }
/* /*
* Locate the existing *pr_reg via struct se_node_acl pointers * Locate the existing *pr_reg via struct se_node_acl pointers
...@@ -2408,8 +2368,7 @@ static int core_scsi3_pro_reserve( ...@@ -2408,8 +2368,7 @@ static int core_scsi3_pro_reserve(
if (!pr_reg) { if (!pr_reg) {
pr_err("SPC-3 PR: Unable to locate" pr_err("SPC-3 PR: Unable to locate"
" PR_REGISTERED *pr_reg for RESERVE\n"); " PR_REGISTERED *pr_reg for RESERVE\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
} }
/* /*
* From spc4r17 Section 5.7.9: Reserving: * From spc4r17 Section 5.7.9: Reserving:
...@@ -2424,9 +2383,8 @@ static int core_scsi3_pro_reserve( ...@@ -2424,9 +2383,8 @@ static int core_scsi3_pro_reserve(
pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx" pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx"
" does not match existing SA REGISTER res_key:" " does not match existing SA REGISTER res_key:"
" 0x%016Lx\n", res_key, pr_reg->pr_res_key); " 0x%016Lx\n", res_key, pr_reg->pr_res_key);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_RESERVATION_CONFLICT;
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; goto out_put_pr_reg;
return -EINVAL;
} }
/* /*
* From spc4r17 Section 5.7.9: Reserving: * From spc4r17 Section 5.7.9: Reserving:
...@@ -2440,9 +2398,8 @@ static int core_scsi3_pro_reserve( ...@@ -2440,9 +2398,8 @@ static int core_scsi3_pro_reserve(
*/ */
if (scope != PR_SCOPE_LU_SCOPE) { if (scope != PR_SCOPE_LU_SCOPE) {
pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_INVALID_PARAMETER_LIST;
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; goto out_put_pr_reg;
return -EINVAL;
} }
/* /*
* See if we have an existing PR reservation holder pointer at * See if we have an existing PR reservation holder pointer at
...@@ -2473,9 +2430,8 @@ static int core_scsi3_pro_reserve( ...@@ -2473,9 +2430,8 @@ static int core_scsi3_pro_reserve(
pr_res_holder->pr_reg_nacl->initiatorname); pr_res_holder->pr_reg_nacl->initiatorname);
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_RESERVATION_CONFLICT;
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; goto out_put_pr_reg;
return -EINVAL;
} }
/* /*
* From spc4r17 Section 5.7.9: Reserving: * From spc4r17 Section 5.7.9: Reserving:
...@@ -2497,9 +2453,8 @@ static int core_scsi3_pro_reserve( ...@@ -2497,9 +2453,8 @@ static int core_scsi3_pro_reserve(
pr_res_holder->pr_reg_nacl->initiatorname); pr_res_holder->pr_reg_nacl->initiatorname);
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_RESERVATION_CONFLICT;
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; goto out_put_pr_reg;
return -EINVAL;
} }
/* /*
* From spc4r17 Section 5.7.9: Reserving: * From spc4r17 Section 5.7.9: Reserving:
...@@ -2512,8 +2467,8 @@ static int core_scsi3_pro_reserve( ...@@ -2512,8 +2467,8 @@ static int core_scsi3_pro_reserve(
* shall completethe command with GOOD status. * shall completethe command with GOOD status.
*/ */
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg); ret = 0;
return 0; goto out_put_pr_reg;
} }
/* /*
* Otherwise, our *pr_reg becomes the PR reservation holder for said * Otherwise, our *pr_reg becomes the PR reservation holder for said
...@@ -2537,27 +2492,24 @@ static int core_scsi3_pro_reserve( ...@@ -2537,27 +2492,24 @@ static int core_scsi3_pro_reserve(
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
if (pr_tmpl->pr_aptpl_active) { if (pr_tmpl->pr_aptpl_active) {
ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
&pr_reg->pr_aptpl_buf[0], &pr_reg->pr_aptpl_buf[0],
pr_tmpl->pr_aptpl_buf_len); pr_tmpl->pr_aptpl_buf_len)) {
if (!ret)
pr_debug("SPC-3 PR: Updated APTPL metadata" pr_debug("SPC-3 PR: Updated APTPL metadata"
" for RESERVE\n"); " for RESERVE\n");
}
} }
ret = 0;
out_put_pr_reg:
core_scsi3_put_pr_reg(pr_reg); core_scsi3_put_pr_reg(pr_reg);
return 0; return ret;
} }
static int core_scsi3_emulate_pro_reserve( static sense_reason_t
struct se_cmd *cmd, core_scsi3_emulate_pro_reserve(struct se_cmd *cmd, int type, int scope,
int type, u64 res_key)
int scope,
u64 res_key)
{ {
struct se_device *dev = cmd->se_dev;
int ret = 0;
switch (type) { switch (type) {
case PR_TYPE_WRITE_EXCLUSIVE: case PR_TYPE_WRITE_EXCLUSIVE:
case PR_TYPE_EXCLUSIVE_ACCESS: case PR_TYPE_EXCLUSIVE_ACCESS:
...@@ -2565,16 +2517,12 @@ static int core_scsi3_emulate_pro_reserve( ...@@ -2565,16 +2517,12 @@ static int core_scsi3_emulate_pro_reserve(
case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY:
case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG:
ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key); return core_scsi3_pro_reserve(cmd, type, scope, res_key);
break;
default: default:
pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:" pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:"
" 0x%02x\n", type); " 0x%02x\n", type);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
return ret;
} }
/* /*
...@@ -2612,23 +2560,21 @@ static void __core_scsi3_complete_pro_release( ...@@ -2612,23 +2560,21 @@ static void __core_scsi3_complete_pro_release(
pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0; pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0;
} }
static int core_scsi3_emulate_pro_release( static sense_reason_t
struct se_cmd *cmd, core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
int type, u64 res_key)
int scope,
u64 res_key)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
struct se_lun *se_lun = cmd->se_lun; struct se_lun *se_lun = cmd->se_lun;
struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
int ret, all_reg = 0; int all_reg = 0;
sense_reason_t ret = 0;
if (!se_sess || !se_lun) { if (!se_sess || !se_lun) {
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
} }
/* /*
* Locate the existing *pr_reg via struct se_node_acl pointers * Locate the existing *pr_reg via struct se_node_acl pointers
...@@ -2637,8 +2583,7 @@ static int core_scsi3_emulate_pro_release( ...@@ -2637,8 +2583,7 @@ static int core_scsi3_emulate_pro_release(
if (!pr_reg) { if (!pr_reg) {
pr_err("SPC-3 PR: Unable to locate" pr_err("SPC-3 PR: Unable to locate"
" PR_REGISTERED *pr_reg for RELEASE\n"); " PR_REGISTERED *pr_reg for RELEASE\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
} }
/* /*
* From spc4r17 Section 5.7.11.2 Releasing: * From spc4r17 Section 5.7.11.2 Releasing:
...@@ -2659,7 +2604,6 @@ static int core_scsi3_emulate_pro_release( ...@@ -2659,7 +2604,6 @@ static int core_scsi3_emulate_pro_release(
* No persistent reservation, return GOOD status. * No persistent reservation, return GOOD status.
*/ */
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg);
return 0; return 0;
} }
if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
...@@ -2673,9 +2617,9 @@ static int core_scsi3_emulate_pro_release( ...@@ -2673,9 +2617,9 @@ static int core_scsi3_emulate_pro_release(
* persistent reservation holder. return GOOD status. * persistent reservation holder. return GOOD status.
*/ */
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg); goto out_put_pr_reg;
return 0;
} }
/* /*
* From spc4r17 Section 5.7.11.2 Releasing: * From spc4r17 Section 5.7.11.2 Releasing:
* *
...@@ -2695,9 +2639,8 @@ static int core_scsi3_emulate_pro_release( ...@@ -2695,9 +2639,8 @@ static int core_scsi3_emulate_pro_release(
" does not match existing SA REGISTER res_key:" " does not match existing SA REGISTER res_key:"
" 0x%016Lx\n", res_key, pr_reg->pr_res_key); " 0x%016Lx\n", res_key, pr_reg->pr_res_key);
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_RESERVATION_CONFLICT;
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; goto out_put_pr_reg;
return -EINVAL;
} }
/* /*
* From spc4r17 Section 5.7.11.2 Releasing and above: * From spc4r17 Section 5.7.11.2 Releasing and above:
...@@ -2718,9 +2661,8 @@ static int core_scsi3_emulate_pro_release( ...@@ -2718,9 +2661,8 @@ static int core_scsi3_emulate_pro_release(
pr_res_holder->pr_reg_nacl->initiatorname); pr_res_holder->pr_reg_nacl->initiatorname);
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_RESERVATION_CONFLICT;
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; goto out_put_pr_reg;
return -EINVAL;
} }
/* /*
* In response to a persistent reservation release request from the * In response to a persistent reservation release request from the
...@@ -2773,20 +2715,18 @@ static int core_scsi3_emulate_pro_release( ...@@ -2773,20 +2715,18 @@ static int core_scsi3_emulate_pro_release(
write_aptpl: write_aptpl:
if (pr_tmpl->pr_aptpl_active) { if (pr_tmpl->pr_aptpl_active) {
ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
&pr_reg->pr_aptpl_buf[0], &pr_reg->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) {
pr_tmpl->pr_aptpl_buf_len);
if (!ret)
pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n");
}
} }
out_put_pr_reg:
core_scsi3_put_pr_reg(pr_reg); core_scsi3_put_pr_reg(pr_reg);
return 0; return ret;
} }
static int core_scsi3_emulate_pro_clear( static sense_reason_t
struct se_cmd *cmd, core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
u64 res_key)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_node_acl *pr_reg_nacl; struct se_node_acl *pr_reg_nacl;
...@@ -2803,8 +2743,7 @@ static int core_scsi3_emulate_pro_clear( ...@@ -2803,8 +2743,7 @@ static int core_scsi3_emulate_pro_clear(
if (!pr_reg_n) { if (!pr_reg_n) {
pr_err("SPC-3 PR: Unable to locate" pr_err("SPC-3 PR: Unable to locate"
" PR_REGISTERED *pr_reg for CLEAR\n"); " PR_REGISTERED *pr_reg for CLEAR\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
} }
/* /*
* From spc4r17 section 5.7.11.6, Clearing: * From spc4r17 section 5.7.11.6, Clearing:
...@@ -2823,8 +2762,7 @@ static int core_scsi3_emulate_pro_clear( ...@@ -2823,8 +2762,7 @@ static int core_scsi3_emulate_pro_clear(
" existing SA REGISTER res_key:" " existing SA REGISTER res_key:"
" 0x%016Lx\n", res_key, pr_reg_n->pr_res_key); " 0x%016Lx\n", res_key, pr_reg_n->pr_res_key);
core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_put_pr_reg(pr_reg_n);
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
return -EINVAL;
} }
/* /*
* a) Release the persistent reservation, if any; * a) Release the persistent reservation, if any;
...@@ -2948,13 +2886,9 @@ static void core_scsi3_release_preempt_and_abort( ...@@ -2948,13 +2886,9 @@ static void core_scsi3_release_preempt_and_abort(
} }
} }
static int core_scsi3_pro_preempt( static sense_reason_t
struct se_cmd *cmd, core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
int type, u64 sa_res_key, int abort)
int scope,
u64 res_key,
u64 sa_res_key,
int abort)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_node_acl *pr_reg_nacl; struct se_node_acl *pr_reg_nacl;
...@@ -2964,12 +2898,10 @@ static int core_scsi3_pro_preempt( ...@@ -2964,12 +2898,10 @@ static int core_scsi3_pro_preempt(
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
u32 pr_res_mapped_lun = 0; u32 pr_res_mapped_lun = 0;
int all_reg = 0, calling_it_nexus = 0, released_regs = 0; int all_reg = 0, calling_it_nexus = 0, released_regs = 0;
int prh_type = 0, prh_scope = 0, ret; int prh_type = 0, prh_scope = 0;
if (!se_sess) { if (!se_sess)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
}
pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
se_sess); se_sess);
...@@ -2977,19 +2909,16 @@ static int core_scsi3_pro_preempt( ...@@ -2977,19 +2909,16 @@ static int core_scsi3_pro_preempt(
pr_err("SPC-3 PR: Unable to locate" pr_err("SPC-3 PR: Unable to locate"
" PR_REGISTERED *pr_reg for PREEMPT%s\n", " PR_REGISTERED *pr_reg for PREEMPT%s\n",
(abort) ? "_AND_ABORT" : ""); (abort) ? "_AND_ABORT" : "");
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
return -EINVAL;
} }
if (pr_reg_n->pr_res_key != res_key) { if (pr_reg_n->pr_res_key != res_key) {
core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_put_pr_reg(pr_reg_n);
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
return -EINVAL;
} }
if (scope != PR_SCOPE_LU_SCOPE) { if (scope != PR_SCOPE_LU_SCOPE) {
pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_put_pr_reg(pr_reg_n);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; return TCM_INVALID_PARAMETER_LIST;
return -EINVAL;
} }
spin_lock(&dev->dev_reservation_lock); spin_lock(&dev->dev_reservation_lock);
...@@ -3002,8 +2931,7 @@ static int core_scsi3_pro_preempt( ...@@ -3002,8 +2931,7 @@ static int core_scsi3_pro_preempt(
if (!all_reg && !sa_res_key) { if (!all_reg && !sa_res_key) {
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_put_pr_reg(pr_reg_n);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; return TCM_INVALID_PARAMETER_LIST;
return -EINVAL;
} }
/* /*
* From spc4r17, section 5.7.11.4.4 Removing Registrations: * From spc4r17, section 5.7.11.4.4 Removing Registrations:
...@@ -3097,8 +3025,7 @@ static int core_scsi3_pro_preempt( ...@@ -3097,8 +3025,7 @@ static int core_scsi3_pro_preempt(
if (!released_regs) { if (!released_regs) {
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_put_pr_reg(pr_reg_n);
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
return -EINVAL;
} }
/* /*
* For an existing all registrants type reservation * For an existing all registrants type reservation
...@@ -3117,13 +3044,13 @@ static int core_scsi3_pro_preempt( ...@@ -3117,13 +3044,13 @@ static int core_scsi3_pro_preempt(
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
if (pr_tmpl->pr_aptpl_active) { if (pr_tmpl->pr_aptpl_active) {
ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
&pr_reg_n->pr_aptpl_buf[0], &pr_reg_n->pr_aptpl_buf[0],
pr_tmpl->pr_aptpl_buf_len); pr_tmpl->pr_aptpl_buf_len)) {
if (!ret)
pr_debug("SPC-3 PR: Updated APTPL" pr_debug("SPC-3 PR: Updated APTPL"
" metadata for PREEMPT%s\n", (abort) ? " metadata for PREEMPT%s\n", (abort) ?
"_AND_ABORT" : ""); "_AND_ABORT" : "");
}
} }
core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_put_pr_reg(pr_reg_n);
...@@ -3253,12 +3180,12 @@ static int core_scsi3_pro_preempt( ...@@ -3253,12 +3180,12 @@ static int core_scsi3_pro_preempt(
} }
if (pr_tmpl->pr_aptpl_active) { if (pr_tmpl->pr_aptpl_active) {
ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
&pr_reg_n->pr_aptpl_buf[0], &pr_reg_n->pr_aptpl_buf[0],
pr_tmpl->pr_aptpl_buf_len); pr_tmpl->pr_aptpl_buf_len)) {
if (!ret)
pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT"
"%s\n", (abort) ? "_AND_ABORT" : ""); "%s\n", abort ? "_AND_ABORT" : "");
}
} }
core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_put_pr_reg(pr_reg_n);
...@@ -3266,16 +3193,10 @@ static int core_scsi3_pro_preempt( ...@@ -3266,16 +3193,10 @@ static int core_scsi3_pro_preempt(
return 0; return 0;
} }
static int core_scsi3_emulate_pro_preempt( static sense_reason_t
struct se_cmd *cmd, core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope,
int type, u64 res_key, u64 sa_res_key, int abort)
int scope,
u64 res_key,
u64 sa_res_key,
int abort)
{ {
int ret = 0;
switch (type) { switch (type) {
case PR_TYPE_WRITE_EXCLUSIVE: case PR_TYPE_WRITE_EXCLUSIVE:
case PR_TYPE_EXCLUSIVE_ACCESS: case PR_TYPE_EXCLUSIVE_ACCESS:
...@@ -3283,26 +3204,19 @@ static int core_scsi3_emulate_pro_preempt( ...@@ -3283,26 +3204,19 @@ static int core_scsi3_emulate_pro_preempt(
case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY:
case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG:
ret = core_scsi3_pro_preempt(cmd, type, scope, return core_scsi3_pro_preempt(cmd, type, scope, res_key,
res_key, sa_res_key, abort); sa_res_key, abort);
break;
default: default:
pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s"
" Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
return ret;
} }
static int core_scsi3_emulate_pro_register_and_move( static sense_reason_t
struct se_cmd *cmd, core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
u64 res_key, u64 sa_res_key, int aptpl, int unreg)
u64 sa_res_key,
int aptpl,
int unreg)
{ {
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
...@@ -3318,15 +3232,16 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3318,15 +3232,16 @@ static int core_scsi3_emulate_pro_register_and_move(
unsigned char *initiator_str; unsigned char *initiator_str;
char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN];
u32 tid_len, tmp_tid_len; u32 tid_len, tmp_tid_len;
int new_reg = 0, type, scope, ret, matching_iname, prf_isid; int new_reg = 0, type, scope, matching_iname, prf_isid;
sense_reason_t ret;
unsigned short rtpi; unsigned short rtpi;
unsigned char proto_ident; unsigned char proto_ident;
if (!se_sess || !se_lun) { if (!se_sess || !se_lun) {
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
} }
memset(dest_iport, 0, 64); memset(dest_iport, 0, 64);
memset(i_buf, 0, PR_REG_ISID_ID_LEN); memset(i_buf, 0, PR_REG_ISID_ID_LEN);
se_tpg = se_sess->se_tpg; se_tpg = se_sess->se_tpg;
...@@ -3342,8 +3257,7 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3342,8 +3257,7 @@ static int core_scsi3_emulate_pro_register_and_move(
if (!pr_reg) { if (!pr_reg) {
pr_err("SPC-3 PR: Unable to locate PR_REGISTERED" pr_err("SPC-3 PR: Unable to locate PR_REGISTERED"
" *pr_reg for REGISTER_AND_MOVE\n"); " *pr_reg for REGISTER_AND_MOVE\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
} }
/* /*
* The provided reservation key much match the existing reservation key * The provided reservation key much match the existing reservation key
...@@ -3353,9 +3267,8 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3353,9 +3267,8 @@ static int core_scsi3_emulate_pro_register_and_move(
pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received" pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received"
" res_key: 0x%016Lx does not match existing SA REGISTER" " res_key: 0x%016Lx does not match existing SA REGISTER"
" res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key); " res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_RESERVATION_CONFLICT;
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; goto out_put_pr_reg;
return -EINVAL;
} }
/* /*
* The service active reservation key needs to be non zero * The service active reservation key needs to be non zero
...@@ -3363,9 +3276,8 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3363,9 +3276,8 @@ static int core_scsi3_emulate_pro_register_and_move(
if (!sa_res_key) { if (!sa_res_key) {
pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero" pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero"
" sa_res_key\n"); " sa_res_key\n");
core_scsi3_put_pr_reg(pr_reg); ret = TCM_INVALID_PARAMETER_LIST;
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; goto out_put_pr_reg;
return -EINVAL;
} }
/* /*
...@@ -3374,6 +3286,11 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3374,6 +3286,11 @@ static int core_scsi3_emulate_pro_register_and_move(
* information. * information.
*/ */
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf) {
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto out_put_pr_reg;
}
rtpi = (buf[18] & 0xff) << 8; rtpi = (buf[18] & 0xff) << 8;
rtpi |= buf[19] & 0xff; rtpi |= buf[19] & 0xff;
tid_len = (buf[20] & 0xff) << 24; tid_len = (buf[20] & 0xff) << 24;
...@@ -3387,9 +3304,8 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3387,9 +3304,8 @@ static int core_scsi3_emulate_pro_register_and_move(
pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header" pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header"
" does not equal CDB data_length: %u\n", tid_len, " does not equal CDB data_length: %u\n", tid_len,
cmd->data_length); cmd->data_length);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_INVALID_PARAMETER_LIST;
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; goto out_put_pr_reg;
return -EINVAL;
} }
spin_lock(&dev->se_port_lock); spin_lock(&dev->se_port_lock);
...@@ -3407,15 +3323,13 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3407,15 +3323,13 @@ static int core_scsi3_emulate_pro_register_and_move(
smp_mb__after_atomic_inc(); smp_mb__after_atomic_inc();
spin_unlock(&dev->se_port_lock); spin_unlock(&dev->se_port_lock);
ret = core_scsi3_tpg_depend_item(dest_se_tpg); if (core_scsi3_tpg_depend_item(dest_se_tpg)) {
if (ret != 0) {
pr_err("core_scsi3_tpg_depend_item() failed" pr_err("core_scsi3_tpg_depend_item() failed"
" for dest_se_tpg\n"); " for dest_se_tpg\n");
atomic_dec(&dest_se_tpg->tpg_pr_ref_count); atomic_dec(&dest_se_tpg->tpg_pr_ref_count);
smp_mb__after_atomic_dec(); smp_mb__after_atomic_dec();
core_scsi3_put_pr_reg(pr_reg); ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out_put_pr_reg;
return -EINVAL;
} }
spin_lock(&dev->se_port_lock); spin_lock(&dev->se_port_lock);
...@@ -3427,12 +3341,15 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3427,12 +3341,15 @@ static int core_scsi3_emulate_pro_register_and_move(
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
" fabric ops from Relative Target Port Identifier:" " fabric ops from Relative Target Port Identifier:"
" %hu\n", rtpi); " %hu\n", rtpi);
core_scsi3_put_pr_reg(pr_reg); ret = TCM_INVALID_PARAMETER_LIST;
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; goto out_put_pr_reg;
return -EINVAL;
} }
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf) {
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto out_put_pr_reg;
}
proto_ident = (buf[24] & 0x0f); proto_ident = (buf[24] & 0x0f);
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
...@@ -3444,16 +3361,14 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3444,16 +3361,14 @@ static int core_scsi3_emulate_pro_register_and_move(
" from fabric: %s\n", proto_ident, " from fabric: %s\n", proto_ident,
dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), dest_tf_ops->get_fabric_proto_ident(dest_se_tpg),
dest_tf_ops->get_fabric_name()); dest_tf_ops->get_fabric_name());
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out; goto out;
} }
if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) {
pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not" pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not"
" containg a valid tpg_parse_pr_out_transport_id" " containg a valid tpg_parse_pr_out_transport_id"
" function pointer\n"); " function pointer\n");
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
ret = -EINVAL;
goto out; goto out;
} }
initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg, initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg,
...@@ -3461,8 +3376,7 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3461,8 +3376,7 @@ static int core_scsi3_emulate_pro_register_and_move(
if (!initiator_str) { if (!initiator_str) {
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
" initiator_str from Transport ID\n"); " initiator_str from Transport ID\n");
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out; goto out;
} }
...@@ -3491,8 +3405,7 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3491,8 +3405,7 @@ static int core_scsi3_emulate_pro_register_and_move(
pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s" pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s"
" matches: %s on received I_T Nexus\n", initiator_str, " matches: %s on received I_T Nexus\n", initiator_str,
pr_reg_nacl->initiatorname); pr_reg_nacl->initiatorname);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out; goto out;
} }
if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) { if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) {
...@@ -3500,8 +3413,7 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3500,8 +3413,7 @@ static int core_scsi3_emulate_pro_register_and_move(
" matches: %s %s on received I_T Nexus\n", " matches: %s %s on received I_T Nexus\n",
initiator_str, iport_ptr, pr_reg_nacl->initiatorname, initiator_str, iport_ptr, pr_reg_nacl->initiatorname,
pr_reg->pr_reg_isid); pr_reg->pr_reg_isid);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out; goto out;
} }
after_iport_check: after_iport_check:
...@@ -3521,19 +3433,17 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3521,19 +3433,17 @@ static int core_scsi3_emulate_pro_register_and_move(
pr_err("Unable to locate %s dest_node_acl for" pr_err("Unable to locate %s dest_node_acl for"
" TransportID%s\n", dest_tf_ops->get_fabric_name(), " TransportID%s\n", dest_tf_ops->get_fabric_name(),
initiator_str); initiator_str);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out; goto out;
} }
ret = core_scsi3_nodeacl_depend_item(dest_node_acl);
if (ret != 0) { if (core_scsi3_nodeacl_depend_item(dest_node_acl)) {
pr_err("core_scsi3_nodeacl_depend_item() for" pr_err("core_scsi3_nodeacl_depend_item() for"
" dest_node_acl\n"); " dest_node_acl\n");
atomic_dec(&dest_node_acl->acl_pr_ref_count); atomic_dec(&dest_node_acl->acl_pr_ref_count);
smp_mb__after_atomic_dec(); smp_mb__after_atomic_dec();
dest_node_acl = NULL; dest_node_acl = NULL;
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out; goto out;
} }
...@@ -3549,19 +3459,16 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3549,19 +3459,16 @@ static int core_scsi3_emulate_pro_register_and_move(
if (!dest_se_deve) { if (!dest_se_deve) {
pr_err("Unable to locate %s dest_se_deve from RTPI:" pr_err("Unable to locate %s dest_se_deve from RTPI:"
" %hu\n", dest_tf_ops->get_fabric_name(), rtpi); " %hu\n", dest_tf_ops->get_fabric_name(), rtpi);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out; goto out;
} }
ret = core_scsi3_lunacl_depend_item(dest_se_deve); if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
if (ret < 0) {
pr_err("core_scsi3_lunacl_depend_item() failed\n"); pr_err("core_scsi3_lunacl_depend_item() failed\n");
atomic_dec(&dest_se_deve->pr_ref_count); atomic_dec(&dest_se_deve->pr_ref_count);
smp_mb__after_atomic_dec(); smp_mb__after_atomic_dec();
dest_se_deve = NULL; dest_se_deve = NULL;
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
ret = -EINVAL;
goto out; goto out;
} }
...@@ -3580,8 +3487,7 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3580,8 +3487,7 @@ static int core_scsi3_emulate_pro_register_and_move(
pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation" pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation"
" currently held\n"); " currently held\n");
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; ret = TCM_INVALID_CDB_FIELD;
ret = -EINVAL;
goto out; goto out;
} }
/* /*
...@@ -3594,8 +3500,7 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3594,8 +3500,7 @@ static int core_scsi3_emulate_pro_register_and_move(
pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T" pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T"
" Nexus is not reservation holder\n"); " Nexus is not reservation holder\n");
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; ret = TCM_RESERVATION_CONFLICT;
ret = -EINVAL;
goto out; goto out;
} }
/* /*
...@@ -3613,8 +3518,7 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3613,8 +3518,7 @@ static int core_scsi3_emulate_pro_register_and_move(
" reservation for type: %s\n", " reservation for type: %s\n",
core_scsi3_pr_dump_type(pr_res_holder->pr_res_type)); core_scsi3_pr_dump_type(pr_res_holder->pr_res_type));
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; ret = TCM_RESERVATION_CONFLICT;
ret = -EINVAL;
goto out; goto out;
} }
pr_res_nacl = pr_res_holder->pr_reg_nacl; pr_res_nacl = pr_res_holder->pr_reg_nacl;
...@@ -3646,13 +3550,11 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3646,13 +3550,11 @@ static int core_scsi3_emulate_pro_register_and_move(
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
iport_ptr); iport_ptr);
if (!dest_pr_reg) { if (!dest_pr_reg) {
ret = core_scsi3_alloc_registration(cmd->se_dev, if (core_scsi3_alloc_registration(cmd->se_dev,
dest_node_acl, dest_se_deve, iport_ptr, dest_node_acl, dest_se_deve, iport_ptr,
sa_res_key, 0, aptpl, 2, 1); sa_res_key, 0, aptpl, 2, 1)) {
if (ret != 0) {
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out; goto out;
} }
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
...@@ -3723,12 +3625,12 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3723,12 +3625,12 @@ static int core_scsi3_emulate_pro_register_and_move(
" REGISTER_AND_MOVE\n"); " REGISTER_AND_MOVE\n");
} else { } else {
pr_tmpl->pr_aptpl_active = 1; pr_tmpl->pr_aptpl_active = 1;
ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
&dest_pr_reg->pr_aptpl_buf[0], &dest_pr_reg->pr_aptpl_buf[0],
pr_tmpl->pr_aptpl_buf_len); pr_tmpl->pr_aptpl_buf_len)) {
if (!ret)
pr_debug("SPC-3 PR: Set APTPL Bit Activated for" pr_debug("SPC-3 PR: Set APTPL Bit Activated for"
" REGISTER_AND_MOVE\n"); " REGISTER_AND_MOVE\n");
}
} }
transport_kunmap_data_sg(cmd); transport_kunmap_data_sg(cmd);
...@@ -3743,6 +3645,8 @@ static int core_scsi3_emulate_pro_register_and_move( ...@@ -3743,6 +3645,8 @@ static int core_scsi3_emulate_pro_register_and_move(
if (dest_node_acl) if (dest_node_acl)
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
core_scsi3_tpg_undepend_item(dest_se_tpg); core_scsi3_tpg_undepend_item(dest_se_tpg);
out_put_pr_reg:
core_scsi3_put_pr_reg(pr_reg); core_scsi3_put_pr_reg(pr_reg);
return ret; return ret;
} }
...@@ -3760,14 +3664,15 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb) ...@@ -3760,14 +3664,15 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb)
/* /*
* See spc4r17 section 6.14 Table 170 * See spc4r17 section 6.14 Table 170
*/ */
int target_scsi3_emulate_pr_out(struct se_cmd *cmd) sense_reason_t
target_scsi3_emulate_pr_out(struct se_cmd *cmd)
{ {
unsigned char *cdb = &cmd->t_task_cdb[0]; unsigned char *cdb = &cmd->t_task_cdb[0];
unsigned char *buf; unsigned char *buf;
u64 res_key, sa_res_key; u64 res_key, sa_res_key;
int sa, scope, type, aptpl; int sa, scope, type, aptpl;
int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; int spec_i_pt = 0, all_tg_pt = 0, unreg = 0;
int ret; sense_reason_t ret;
/* /*
* Following spc2r20 5.5.1 Reservations overview: * Following spc2r20 5.5.1 Reservations overview:
...@@ -3782,28 +3687,22 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) ...@@ -3782,28 +3687,22 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
pr_err("Received PERSISTENT_RESERVE CDB while legacy" pr_err("Received PERSISTENT_RESERVE CDB while legacy"
" SPC-2 reservation is held, returning" " SPC-2 reservation is held, returning"
" RESERVATION_CONFLICT\n"); " RESERVATION_CONFLICT\n");
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
ret = -EINVAL;
goto out;
} }
/* /*
* FIXME: A NULL struct se_session pointer means an this is not coming from * FIXME: A NULL struct se_session pointer means an this is not coming from
* a $FABRIC_MOD's nexus, but from internal passthrough ops. * a $FABRIC_MOD's nexus, but from internal passthrough ops.
*/ */
if (!cmd->se_sess) { if (!cmd->se_sess)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
ret = -EINVAL;
goto out;
}
if (cmd->data_length < 24) { if (cmd->data_length < 24) {
pr_warn("SPC-PR: Received PR OUT parameter list" pr_warn("SPC-PR: Received PR OUT parameter list"
" length too small: %u\n", cmd->data_length); " length too small: %u\n", cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; return TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out;
} }
/* /*
* From the PERSISTENT_RESERVE_OUT command descriptor block (CDB) * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB)
*/ */
...@@ -3812,6 +3711,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) ...@@ -3812,6 +3711,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
type = (cdb[2] & 0x0f); type = (cdb[2] & 0x0f);
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
/* /*
* From PERSISTENT_RESERVE_OUT parameter list (payload) * From PERSISTENT_RESERVE_OUT parameter list (payload)
*/ */
...@@ -3835,11 +3737,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) ...@@ -3835,11 +3737,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
/* /*
* SPEC_I_PT=1 is only valid for Service action: REGISTER * SPEC_I_PT=1 is only valid for Service action: REGISTER
*/ */
if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) { if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER))
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; return TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out;
}
/* /*
* From spc4r17 section 6.14: * From spc4r17 section 6.14:
...@@ -3854,10 +3753,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) ...@@ -3854,10 +3753,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
(cmd->data_length != 24)) { (cmd->data_length != 24)) {
pr_warn("SPC-PR: Received PR OUT illegal parameter" pr_warn("SPC-PR: Received PR OUT illegal parameter"
" list length: %u\n", cmd->data_length); " list length: %u\n", cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; return TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
goto out;
} }
/* /*
* (core_scsi3_emulate_pro_* function parameters * (core_scsi3_emulate_pro_* function parameters
* are defined by spc4r17 Table 174: * are defined by spc4r17 Table 174:
...@@ -3896,12 +3794,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) ...@@ -3896,12 +3794,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
default: default:
pr_err("Unknown PERSISTENT_RESERVE_OUT service" pr_err("Unknown PERSISTENT_RESERVE_OUT service"
" action: 0x%02x\n", cdb[1] & 0x1f); " action: 0x%02x\n", cdb[1] & 0x1f);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
ret = -EINVAL;
break;
} }
out:
if (!ret) if (!ret)
target_complete_cmd(cmd, GOOD); target_complete_cmd(cmd, GOOD);
return ret; return ret;
...@@ -3912,7 +3807,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) ...@@ -3912,7 +3807,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
* *
* See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160 * See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160
*/ */
static int core_scsi3_pri_read_keys(struct se_cmd *cmd) static sense_reason_t
core_scsi3_pri_read_keys(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct t10_pr_registration *pr_reg; struct t10_pr_registration *pr_reg;
...@@ -3922,11 +3818,13 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) ...@@ -3922,11 +3818,13 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
if (cmd->data_length < 8) { if (cmd->data_length < 8) {
pr_err("PRIN SA READ_KEYS SCSI Data Length: %u" pr_err("PRIN SA READ_KEYS SCSI Data Length: %u"
" too small\n", cmd->data_length); " too small\n", cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff);
buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff);
buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
...@@ -3970,7 +3868,8 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) ...@@ -3970,7 +3868,8 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
* *
* See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162 * See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162
*/ */
static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) static sense_reason_t
core_scsi3_pri_read_reservation(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct t10_pr_registration *pr_reg; struct t10_pr_registration *pr_reg;
...@@ -3981,11 +3880,13 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) ...@@ -3981,11 +3880,13 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
if (cmd->data_length < 8) { if (cmd->data_length < 8) {
pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u"
" too small\n", cmd->data_length); " too small\n", cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff);
buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff);
buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
...@@ -4054,7 +3955,8 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) ...@@ -4054,7 +3955,8 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
* *
* See spc4r17 section 6.13.4 Table 165 * See spc4r17 section 6.13.4 Table 165
*/ */
static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) static sense_reason_t
core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
...@@ -4064,11 +3966,12 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) ...@@ -4064,11 +3966,12 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
if (cmd->data_length < 6) { if (cmd->data_length < 6) {
pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:"
" %u too small\n", cmd->data_length); " %u too small\n", cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
buf[0] = ((add_len << 8) & 0xff); buf[0] = ((add_len << 8) & 0xff);
buf[1] = (add_len & 0xff); buf[1] = (add_len & 0xff);
...@@ -4110,7 +4013,8 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) ...@@ -4110,7 +4013,8 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
* *
* See spc4r17 section 6.13.5 Table 168 and 169 * See spc4r17 section 6.13.5 Table 168 and 169
*/ */
static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) static sense_reason_t
core_scsi3_pri_read_full_status(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_node_acl *se_nacl; struct se_node_acl *se_nacl;
...@@ -4125,11 +4029,12 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) ...@@ -4125,11 +4029,12 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
if (cmd->data_length < 8) { if (cmd->data_length < 8) {
pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u"
" too small\n", cmd->data_length); " too small\n", cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff);
buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff);
...@@ -4255,9 +4160,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) ...@@ -4255,9 +4160,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
return 0; return 0;
} }
int target_scsi3_emulate_pr_in(struct se_cmd *cmd) sense_reason_t
target_scsi3_emulate_pr_in(struct se_cmd *cmd)
{ {
int ret; sense_reason_t ret;
/* /*
* Following spc2r20 5.5.1 Reservations overview: * Following spc2r20 5.5.1 Reservations overview:
...@@ -4272,8 +4178,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) ...@@ -4272,8 +4178,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
pr_err("Received PERSISTENT_RESERVE CDB while legacy" pr_err("Received PERSISTENT_RESERVE CDB while legacy"
" SPC-2 reservation is held, returning" " SPC-2 reservation is held, returning"
" RESERVATION_CONFLICT\n"); " RESERVATION_CONFLICT\n");
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
return -EINVAL;
} }
switch (cmd->t_task_cdb[1] & 0x1f) { switch (cmd->t_task_cdb[1] & 0x1f) {
...@@ -4292,9 +4197,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) ...@@ -4292,9 +4197,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
default: default:
pr_err("Unknown PERSISTENT_RESERVE_IN service" pr_err("Unknown PERSISTENT_RESERVE_IN service"
" action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
ret = -EINVAL;
break;
} }
if (!ret) if (!ret)
...@@ -4302,10 +4205,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) ...@@ -4302,10 +4205,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
return ret; return ret;
} }
int target_check_reservation(struct se_cmd *cmd) sense_reason_t
target_check_reservation(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
int ret; sense_reason_t ret;
if (!cmd->se_sess) if (!cmd->se_sess)
return 0; return 0;
......
...@@ -47,8 +47,8 @@ extern struct kmem_cache *t10_pr_reg_cache; ...@@ -47,8 +47,8 @@ extern struct kmem_cache *t10_pr_reg_cache;
extern int core_pr_dump_initiator_port(struct t10_pr_registration *, extern int core_pr_dump_initiator_port(struct t10_pr_registration *,
char *, u32); char *, u32);
extern int target_scsi2_reservation_release(struct se_cmd *); extern sense_reason_t target_scsi2_reservation_release(struct se_cmd *);
extern int target_scsi2_reservation_reserve(struct se_cmd *); extern sense_reason_t target_scsi2_reservation_reserve(struct se_cmd *);
extern int core_scsi3_alloc_aptpl_registration( extern int core_scsi3_alloc_aptpl_registration(
struct t10_reservation *, u64, struct t10_reservation *, u64,
unsigned char *, unsigned char *, u32, unsigned char *, unsigned char *, u32,
...@@ -61,8 +61,8 @@ extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *, ...@@ -61,8 +61,8 @@ extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *,
extern void core_scsi3_free_all_registrations(struct se_device *); extern void core_scsi3_free_all_registrations(struct se_device *);
extern unsigned char *core_scsi3_pr_dump_type(int); extern unsigned char *core_scsi3_pr_dump_type(int);
extern int target_scsi3_emulate_pr_in(struct se_cmd *); extern sense_reason_t target_scsi3_emulate_pr_in(struct se_cmd *);
extern int target_scsi3_emulate_pr_out(struct se_cmd *); extern sense_reason_t target_scsi3_emulate_pr_out(struct se_cmd *);
extern int target_check_reservation(struct se_cmd *cmd); extern sense_reason_t target_check_reservation(struct se_cmd *);
#endif /* TARGET_CORE_PR_H */ #endif /* TARGET_CORE_PR_H */
...@@ -60,7 +60,7 @@ static inline struct pscsi_dev_virt *PSCSI_DEV(struct se_device *dev) ...@@ -60,7 +60,7 @@ static inline struct pscsi_dev_virt *PSCSI_DEV(struct se_device *dev)
static struct se_subsystem_api pscsi_template; static struct se_subsystem_api pscsi_template;
static int pscsi_execute_cmd(struct se_cmd *cmd); static sense_reason_t pscsi_execute_cmd(struct se_cmd *cmd);
static void pscsi_req_done(struct request *, int); static void pscsi_req_done(struct request *, int);
/* pscsi_attach_hba(): /* pscsi_attach_hba():
...@@ -642,7 +642,11 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, ...@@ -642,7 +642,11 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg,
if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) &&
(status_byte(result) << 1) == SAM_STAT_GOOD) { (status_byte(result) << 1) == SAM_STAT_GOOD) {
if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) {
unsigned char *buf = transport_kmap_data_sg(cmd); unsigned char *buf;
buf = transport_kmap_data_sg(cmd);
if (!buf)
; /* XXX: TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE */
if (cdb[0] == MODE_SENSE_10) { if (cdb[0] == MODE_SENSE_10) {
if (!(buf[3] & 0x80)) if (!(buf[3] & 0x80))
...@@ -856,9 +860,9 @@ static inline struct bio *pscsi_get_bio(int sg_num) ...@@ -856,9 +860,9 @@ static inline struct bio *pscsi_get_bio(int sg_num)
return bio; return bio;
} }
static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, static sense_reason_t
u32 sgl_nents, enum dma_data_direction data_direction, pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
struct bio **hbio) enum dma_data_direction data_direction, struct bio **hbio)
{ {
struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev);
struct bio *bio = NULL, *tbio = NULL; struct bio *bio = NULL, *tbio = NULL;
...@@ -946,7 +950,7 @@ static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, ...@@ -946,7 +950,7 @@ static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl,
} }
} }
return sgl_nents; return 0;
fail: fail:
while (*hbio) { while (*hbio) {
bio = *hbio; bio = *hbio;
...@@ -954,8 +958,7 @@ static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, ...@@ -954,8 +958,7 @@ static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl,
bio->bi_next = NULL; bio->bi_next = NULL;
bio_endio(bio, 0); /* XXX: should be error */ bio_endio(bio, 0); /* XXX: should be error */
} }
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -ENOMEM;
} }
/* /*
...@@ -982,15 +985,13 @@ static inline void pscsi_clear_cdb_lun(unsigned char *cdb) ...@@ -982,15 +985,13 @@ static inline void pscsi_clear_cdb_lun(unsigned char *cdb)
} }
} }
static int pscsi_parse_cdb(struct se_cmd *cmd) static sense_reason_t
pscsi_parse_cdb(struct se_cmd *cmd)
{ {
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
if (cmd->se_cmd_flags & SCF_BIDI) { if (cmd->se_cmd_flags & SCF_BIDI)
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return TCM_UNSUPPORTED_SCSI_OPCODE;
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
return -EINVAL;
}
pscsi_clear_cdb_lun(cdb); pscsi_clear_cdb_lun(cdb);
...@@ -1020,7 +1021,8 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) ...@@ -1020,7 +1021,8 @@ static int pscsi_parse_cdb(struct se_cmd *cmd)
} }
} }
static int pscsi_execute_cmd(struct se_cmd *cmd) static sense_reason_t
pscsi_execute_cmd(struct se_cmd *cmd)
{ {
struct scatterlist *sgl = cmd->t_data_sg; struct scatterlist *sgl = cmd->t_data_sg;
u32 sgl_nents = cmd->t_data_nents; u32 sgl_nents = cmd->t_data_nents;
...@@ -1029,7 +1031,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) ...@@ -1029,7 +1031,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd)
struct pscsi_plugin_task *pt; struct pscsi_plugin_task *pt;
struct request *req; struct request *req;
struct bio *hbio; struct bio *hbio;
int ret; sense_reason_t ret;
/* /*
* Dynamically alloc cdb space, since it may be larger than * Dynamically alloc cdb space, since it may be larger than
...@@ -1037,8 +1039,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) ...@@ -1037,8 +1039,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd)
*/ */
pt = kzalloc(sizeof(*pt) + scsi_command_size(cmd->t_task_cdb), GFP_KERNEL); pt = kzalloc(sizeof(*pt) + scsi_command_size(cmd->t_task_cdb), GFP_KERNEL);
if (!pt) { if (!pt) {
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -ENOMEM;
} }
cmd->priv = pt; cmd->priv = pt;
...@@ -1052,24 +1053,21 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) ...@@ -1052,24 +1053,21 @@ static int pscsi_execute_cmd(struct se_cmd *cmd)
if (!req || IS_ERR(req)) { if (!req || IS_ERR(req)) {
pr_err("PSCSI: blk_get_request() failed: %ld\n", pr_err("PSCSI: blk_get_request() failed: %ld\n",
req ? IS_ERR(req) : -ENOMEM); req ? IS_ERR(req) : -ENOMEM);
cmd->scsi_sense_reason = ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto fail; goto fail;
} }
} else { } else {
BUG_ON(!cmd->data_length); BUG_ON(!cmd->data_length);
ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio); ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio);
if (ret < 0) { if (ret)
cmd->scsi_sense_reason =
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto fail; goto fail;
}
req = blk_make_request(pdv->pdv_sd->request_queue, hbio, req = blk_make_request(pdv->pdv_sd->request_queue, hbio,
GFP_KERNEL); GFP_KERNEL);
if (IS_ERR(req)) { if (IS_ERR(req)) {
pr_err("pSCSI: blk_make_request() failed\n"); pr_err("pSCSI: blk_make_request() failed\n");
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto fail_free_bio; goto fail_free_bio;
} }
} }
...@@ -1100,10 +1098,10 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) ...@@ -1100,10 +1098,10 @@ static int pscsi_execute_cmd(struct se_cmd *cmd)
bio->bi_next = NULL; bio->bi_next = NULL;
bio_endio(bio, 0); /* XXX: should be error */ bio_endio(bio, 0); /* XXX: should be error */
} }
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
fail: fail:
kfree(pt); kfree(pt);
return -ENOMEM; return ret;
} }
/* pscsi_get_device_type(): /* pscsi_get_device_type():
...@@ -1152,7 +1150,6 @@ static void pscsi_req_done(struct request *req, int uptodate) ...@@ -1152,7 +1150,6 @@ static void pscsi_req_done(struct request *req, int uptodate)
pr_debug("PSCSI Host Byte exception at cmd: %p CDB:" pr_debug("PSCSI Host Byte exception at cmd: %p CDB:"
" 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0], " 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0],
pt->pscsi_result); pt->pscsi_result);
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
break; break;
} }
......
...@@ -275,7 +275,8 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page) ...@@ -275,7 +275,8 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
return NULL; return NULL;
} }
static int rd_execute_rw(struct se_cmd *cmd) static sense_reason_t
rd_execute_rw(struct se_cmd *cmd)
{ {
struct scatterlist *sgl = cmd->t_data_sg; struct scatterlist *sgl = cmd->t_data_sg;
u32 sgl_nents = cmd->t_data_nents; u32 sgl_nents = cmd->t_data_nents;
...@@ -298,7 +299,7 @@ static int rd_execute_rw(struct se_cmd *cmd) ...@@ -298,7 +299,7 @@ static int rd_execute_rw(struct se_cmd *cmd)
table = rd_get_sg_table(dev, rd_page); table = rd_get_sg_table(dev, rd_page);
if (!table) if (!table)
return -EINVAL; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
rd_sg = &table->sg_table[rd_page - table->page_start_offset]; rd_sg = &table->sg_table[rd_page - table->page_start_offset];
...@@ -348,7 +349,7 @@ static int rd_execute_rw(struct se_cmd *cmd) ...@@ -348,7 +349,7 @@ static int rd_execute_rw(struct se_cmd *cmd)
table = rd_get_sg_table(dev, rd_page); table = rd_get_sg_table(dev, rd_page);
if (!table) { if (!table) {
sg_miter_stop(&m); sg_miter_stop(&m);
return -EINVAL; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
/* since we increment, the first sg entry is correct */ /* since we increment, the first sg entry is correct */
...@@ -431,7 +432,8 @@ static struct sbc_ops rd_sbc_ops = { ...@@ -431,7 +432,8 @@ static struct sbc_ops rd_sbc_ops = {
.execute_rw = rd_execute_rw, .execute_rw = rd_execute_rw,
}; };
static int rd_parse_cdb(struct se_cmd *cmd) static sense_reason_t
rd_parse_cdb(struct se_cmd *cmd)
{ {
return sbc_parse_cdb(cmd, &rd_sbc_ops); return sbc_parse_cdb(cmd, &rd_sbc_ops);
} }
......
...@@ -37,7 +37,8 @@ ...@@ -37,7 +37,8 @@
#include "target_core_ua.h" #include "target_core_ua.h"
static int sbc_emulate_readcapacity(struct se_cmd *cmd) static sense_reason_t
sbc_emulate_readcapacity(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned long long blocks_long = dev->transport->get_blocks(dev); unsigned long long blocks_long = dev->transport->get_blocks(dev);
...@@ -60,16 +61,18 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd) ...@@ -60,16 +61,18 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd)
buf[7] = dev->dev_attrib.block_size & 0xff; buf[7] = dev->dev_attrib.block_size & 0xff;
rbuf = transport_kmap_data_sg(cmd); rbuf = transport_kmap_data_sg(cmd);
if (rbuf) { if (!rbuf)
memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
transport_kunmap_data_sg(cmd);
} memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
transport_kunmap_data_sg(cmd);
target_complete_cmd(cmd, GOOD); target_complete_cmd(cmd, GOOD);
return 0; return 0;
} }
static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) static sense_reason_t
sbc_emulate_readcapacity_16(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned char *rbuf; unsigned char *rbuf;
...@@ -97,10 +100,11 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) ...@@ -97,10 +100,11 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd)
buf[14] = 0x80; buf[14] = 0x80;
rbuf = transport_kmap_data_sg(cmd); rbuf = transport_kmap_data_sg(cmd);
if (rbuf) { if (!rbuf)
memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
transport_kunmap_data_sg(cmd);
} memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
transport_kunmap_data_sg(cmd);
target_complete_cmd(cmd, GOOD); target_complete_cmd(cmd, GOOD);
return 0; return 0;
...@@ -129,7 +133,8 @@ int spc_get_write_same_sectors(struct se_cmd *cmd) ...@@ -129,7 +133,8 @@ int spc_get_write_same_sectors(struct se_cmd *cmd)
} }
EXPORT_SYMBOL(spc_get_write_same_sectors); EXPORT_SYMBOL(spc_get_write_same_sectors);
static int sbc_emulate_verify(struct se_cmd *cmd) static sense_reason_t
sbc_emulate_verify(struct se_cmd *cmd)
{ {
target_complete_cmd(cmd, GOOD); target_complete_cmd(cmd, GOOD);
return 0; return 0;
...@@ -313,13 +318,14 @@ static void xdreadwrite_callback(struct se_cmd *cmd) ...@@ -313,13 +318,14 @@ static void xdreadwrite_callback(struct se_cmd *cmd)
kfree(buf); kfree(buf);
} }
int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) sense_reason_t
sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
unsigned int size; unsigned int size;
u32 sectors = 0; u32 sectors = 0;
int ret; sense_reason_t ret;
switch (cdb[0]) { switch (cdb[0]) {
case READ_6: case READ_6:
...@@ -378,9 +384,9 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -378,9 +384,9 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
cmd->execute_cmd = ops->execute_rw; cmd->execute_cmd = ops->execute_rw;
break; break;
case XDWRITEREAD_10: case XDWRITEREAD_10:
if ((cmd->data_direction != DMA_TO_DEVICE) || if (cmd->data_direction != DMA_TO_DEVICE ||
!(cmd->se_cmd_flags & SCF_BIDI)) !(cmd->se_cmd_flags & SCF_BIDI))
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
sectors = transport_get_sectors_10(cdb); sectors = transport_get_sectors_10(cdb);
cmd->t_task_lba = transport_lba_32(cdb); cmd->t_task_lba = transport_lba_32(cdb);
...@@ -419,26 +425,26 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -419,26 +425,26 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
break; break;
case WRITE_SAME_32: case WRITE_SAME_32:
if (!ops->execute_write_same) if (!ops->execute_write_same)
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
sectors = transport_get_sectors_32(cdb); sectors = transport_get_sectors_32(cdb);
if (!sectors) { if (!sectors) {
pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
" supported\n"); " supported\n");
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
size = sbc_get_size(cmd, 1); size = sbc_get_size(cmd, 1);
cmd->t_task_lba = get_unaligned_be64(&cdb[12]); cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
if (sbc_write_same_supported(dev, &cdb[10]) < 0) if (sbc_write_same_supported(dev, &cdb[10]) < 0)
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
cmd->execute_cmd = ops->execute_write_same; cmd->execute_cmd = ops->execute_write_same;
break; break;
default: default:
pr_err("VARIABLE_LENGTH_CMD service action" pr_err("VARIABLE_LENGTH_CMD service action"
" 0x%04x not supported\n", service_action); " 0x%04x not supported\n", service_action);
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
} }
break; break;
} }
...@@ -454,7 +460,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -454,7 +460,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
default: default:
pr_err("Unsupported SA: 0x%02x\n", pr_err("Unsupported SA: 0x%02x\n",
cmd->t_task_cdb[1] & 0x1f); cmd->t_task_cdb[1] & 0x1f);
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
size = (cdb[10] << 24) | (cdb[11] << 16) | size = (cdb[10] << 24) | (cdb[11] << 16) |
(cdb[12] << 8) | cdb[13]; (cdb[12] << 8) | cdb[13];
...@@ -462,7 +468,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -462,7 +468,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
case SYNCHRONIZE_CACHE: case SYNCHRONIZE_CACHE:
case SYNCHRONIZE_CACHE_16: case SYNCHRONIZE_CACHE_16:
if (!ops->execute_sync_cache) if (!ops->execute_sync_cache)
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
/* /*
* Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
...@@ -483,42 +489,42 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -483,42 +489,42 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
*/ */
if (cmd->t_task_lba || sectors) { if (cmd->t_task_lba || sectors) {
if (sbc_check_valid_sectors(cmd) < 0) if (sbc_check_valid_sectors(cmd) < 0)
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
cmd->execute_cmd = ops->execute_sync_cache; cmd->execute_cmd = ops->execute_sync_cache;
break; break;
case UNMAP: case UNMAP:
if (!ops->execute_unmap) if (!ops->execute_unmap)
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
size = get_unaligned_be16(&cdb[7]); size = get_unaligned_be16(&cdb[7]);
cmd->execute_cmd = ops->execute_unmap; cmd->execute_cmd = ops->execute_unmap;
break; break;
case WRITE_SAME_16: case WRITE_SAME_16:
if (!ops->execute_write_same) if (!ops->execute_write_same)
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
sectors = transport_get_sectors_16(cdb); sectors = transport_get_sectors_16(cdb);
if (!sectors) { if (!sectors) {
pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
size = sbc_get_size(cmd, 1); size = sbc_get_size(cmd, 1);
cmd->t_task_lba = get_unaligned_be64(&cdb[2]); cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
if (sbc_write_same_supported(dev, &cdb[1]) < 0) if (sbc_write_same_supported(dev, &cdb[1]) < 0)
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
cmd->execute_cmd = ops->execute_write_same; cmd->execute_cmd = ops->execute_write_same;
break; break;
case WRITE_SAME: case WRITE_SAME:
if (!ops->execute_write_same) if (!ops->execute_write_same)
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
sectors = transport_get_sectors_10(cdb); sectors = transport_get_sectors_10(cdb);
if (!sectors) { if (!sectors) {
pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
size = sbc_get_size(cmd, 1); size = sbc_get_size(cmd, 1);
...@@ -529,7 +535,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -529,7 +535,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
* of byte 1 bit 3 UNMAP instead of original reserved field * of byte 1 bit 3 UNMAP instead of original reserved field
*/ */
if (sbc_write_same_supported(dev, &cdb[1]) < 0) if (sbc_write_same_supported(dev, &cdb[1]) < 0)
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
cmd->execute_cmd = ops->execute_write_same; cmd->execute_cmd = ops->execute_write_same;
break; break;
case VERIFY: case VERIFY:
...@@ -556,7 +562,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -556,7 +562,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
/* reject any command that we don't have a handler for */ /* reject any command that we don't have a handler for */
if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd) if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd)
goto out_unsupported_cdb; return TCM_UNSUPPORTED_SCSI_OPCODE;
if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
unsigned long long end_lba; unsigned long long end_lba;
...@@ -566,14 +572,14 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -566,14 +572,14 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
" big sectors %u exceeds fabric_max_sectors:" " big sectors %u exceeds fabric_max_sectors:"
" %u\n", cdb[0], sectors, " %u\n", cdb[0], sectors,
dev->dev_attrib.fabric_max_sectors); dev->dev_attrib.fabric_max_sectors);
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
if (sectors > dev->dev_attrib.hw_max_sectors) { if (sectors > dev->dev_attrib.hw_max_sectors) {
printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
" big sectors %u exceeds backend hw_max_sectors:" " big sectors %u exceeds backend hw_max_sectors:"
" %u\n", cdb[0], sectors, " %u\n", cdb[0], sectors,
dev->dev_attrib.hw_max_sectors); dev->dev_attrib.hw_max_sectors);
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
end_lba = dev->transport->get_blocks(dev) + 1; end_lba = dev->transport->get_blocks(dev) + 1;
...@@ -581,26 +587,13 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -581,26 +587,13 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
pr_err("cmd exceeds last lba %llu " pr_err("cmd exceeds last lba %llu "
"(lba %llu, sectors %u)\n", "(lba %llu, sectors %u)\n",
end_lba, cmd->t_task_lba, sectors); end_lba, cmd->t_task_lba, sectors);
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
size = sbc_get_size(cmd, sectors); size = sbc_get_size(cmd, sectors);
} }
ret = target_cmd_size_check(cmd, size); return target_cmd_size_check(cmd, size);
if (ret < 0)
return ret;
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;
} }
EXPORT_SYMBOL(sbc_parse_cdb); EXPORT_SYMBOL(sbc_parse_cdb);
......
...@@ -69,7 +69,8 @@ static void spc_fill_alua_data(struct se_port *port, unsigned char *buf) ...@@ -69,7 +69,8 @@ static void spc_fill_alua_data(struct se_port *port, unsigned char *buf)
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
} }
static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) static sense_reason_t
spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
{ {
struct se_lun *lun = cmd->se_lun; struct se_lun *lun = cmd->se_lun;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
...@@ -108,7 +109,8 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) ...@@ -108,7 +109,8 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
} }
/* unit serial number */ /* unit serial number */
static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) static sense_reason_t
spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
u16 len = 0; u16 len = 0;
...@@ -161,7 +163,8 @@ static void spc_parse_naa_6h_vendor_specific(struct se_device *dev, ...@@ -161,7 +163,8 @@ static void spc_parse_naa_6h_vendor_specific(struct se_device *dev,
* Device identification VPD, for a complete list of * Device identification VPD, for a complete list of
* DESIGNATOR TYPEs see spc4r17 Table 459. * DESIGNATOR TYPEs see spc4r17 Table 459.
*/ */
static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) static sense_reason_t
spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_lun *lun = cmd->se_lun; struct se_lun *lun = cmd->se_lun;
...@@ -406,7 +409,8 @@ static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) ...@@ -406,7 +409,8 @@ static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
} }
/* Extended INQUIRY Data VPD Page */ /* Extended INQUIRY Data VPD Page */
static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) static sense_reason_t
spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
{ {
buf[3] = 0x3c; buf[3] = 0x3c;
/* Set HEADSUP, ORDSUP, SIMPSUP */ /* Set HEADSUP, ORDSUP, SIMPSUP */
...@@ -419,7 +423,8 @@ static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) ...@@ -419,7 +423,8 @@ static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
} }
/* Block Limits VPD page */ /* Block Limits VPD page */
static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) static sense_reason_t
spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
u32 max_sectors; u32 max_sectors;
...@@ -490,7 +495,8 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) ...@@ -490,7 +495,8 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
} }
/* Block Device Characteristics VPD page */ /* Block Device Characteristics VPD page */
static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) static sense_reason_t
spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
...@@ -502,7 +508,8 @@ static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) ...@@ -502,7 +508,8 @@ static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
} }
/* Thin Provisioning VPD */ /* Thin Provisioning VPD */
static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) static sense_reason_t
spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
...@@ -552,11 +559,12 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) ...@@ -552,11 +559,12 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
return 0; return 0;
} }
static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); static sense_reason_t
spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
static struct { static struct {
uint8_t page; uint8_t page;
int (*emulate)(struct se_cmd *, unsigned char *); sense_reason_t (*emulate)(struct se_cmd *, unsigned char *);
} evpd_handlers[] = { } evpd_handlers[] = {
{ .page = 0x00, .emulate = spc_emulate_evpd_00 }, { .page = 0x00, .emulate = spc_emulate_evpd_00 },
{ .page = 0x80, .emulate = spc_emulate_evpd_80 }, { .page = 0x80, .emulate = spc_emulate_evpd_80 },
...@@ -568,7 +576,8 @@ static struct { ...@@ -568,7 +576,8 @@ static struct {
}; };
/* supported vital product data pages */ /* supported vital product data pages */
static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) static sense_reason_t
spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
{ {
int p; int p;
...@@ -586,14 +595,16 @@ static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) ...@@ -586,14 +595,16 @@ static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
return 0; return 0;
} }
static int spc_emulate_inquiry(struct se_cmd *cmd) static sense_reason_t
spc_emulate_inquiry(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
unsigned char *rbuf; unsigned char *rbuf;
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
unsigned char buf[SE_INQUIRY_BUF]; unsigned char buf[SE_INQUIRY_BUF];
int p, ret; sense_reason_t ret;
int p;
memset(buf, 0, SE_INQUIRY_BUF); memset(buf, 0, SE_INQUIRY_BUF);
...@@ -606,8 +617,7 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) ...@@ -606,8 +617,7 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
if (cdb[2]) { if (cdb[2]) {
pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
cdb[2]); cdb[2]);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; ret = TCM_INVALID_CDB_FIELD;
ret = -EINVAL;
goto out; goto out;
} }
...@@ -624,15 +634,15 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) ...@@ -624,15 +634,15 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
} }
pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; ret = TCM_INVALID_CDB_FIELD;
ret = -EINVAL;
out: out:
rbuf = transport_kmap_data_sg(cmd); rbuf = transport_kmap_data_sg(cmd);
if (rbuf) { if (!rbuf)
memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
transport_kunmap_data_sg(cmd);
} memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
transport_kunmap_data_sg(cmd);
if (!ret) if (!ret)
target_complete_cmd(cmd, GOOD); target_complete_cmd(cmd, GOOD);
...@@ -834,7 +844,7 @@ static int spc_modesense_long_blockdesc(unsigned char *buf, u64 blocks, u32 bloc ...@@ -834,7 +844,7 @@ static int spc_modesense_long_blockdesc(unsigned char *buf, u64 blocks, u32 bloc
return 17; return 17;
} }
static int spc_emulate_modesense(struct se_cmd *cmd) static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
char *cdb = cmd->t_task_cdb; char *cdb = cmd->t_task_cdb;
...@@ -851,7 +861,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd) ...@@ -851,7 +861,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
int i; int i;
map_buf = transport_kmap_data_sg(cmd); map_buf = transport_kmap_data_sg(cmd);
if (!map_buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
/* /*
* If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
* know we actually allocated a full page. Otherwise, if the * know we actually allocated a full page. Otherwise, if the
...@@ -864,8 +875,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd) ...@@ -864,8 +875,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL); buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL);
if (!buf) { if (!buf) {
transport_kunmap_data_sg(cmd); transport_kunmap_data_sg(cmd);
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -ENOMEM;
} }
} else { } else {
buf = map_buf; buf = map_buf;
...@@ -920,9 +930,10 @@ static int spc_emulate_modesense(struct se_cmd *cmd) ...@@ -920,9 +930,10 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
if (page == 0x3f) { if (page == 0x3f) {
if (subpage != 0x00 && subpage != 0xff) { if (subpage != 0x00 && subpage != 0xff) {
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage);
length = -EINVAL; kfree(buf);
goto out; transport_kunmap_data_sg(cmd);
return TCM_INVALID_CDB_FIELD;
} }
for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) { for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) {
...@@ -958,8 +969,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd) ...@@ -958,8 +969,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
page, subpage); page, subpage);
cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; transport_kunmap_data_sg(cmd);
return -EINVAL; return TCM_UNKNOWN_MODE_PAGE;
set_length: set_length:
if (ten) if (ten)
...@@ -967,7 +978,6 @@ static int spc_emulate_modesense(struct se_cmd *cmd) ...@@ -967,7 +978,6 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
else else
buf[0] = length - 1; buf[0] = length - 1;
out:
if (buf != map_buf) { if (buf != map_buf) {
memcpy(map_buf, buf, cmd->data_length); memcpy(map_buf, buf, cmd->data_length);
kfree(buf); kfree(buf);
...@@ -978,7 +988,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd) ...@@ -978,7 +988,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
return 0; return 0;
} }
static int spc_emulate_modeselect(struct se_cmd *cmd) static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
char *cdb = cmd->t_task_cdb; char *cdb = cmd->t_task_cdb;
...@@ -993,10 +1003,11 @@ static int spc_emulate_modeselect(struct se_cmd *cmd) ...@@ -993,10 +1003,11 @@ static int spc_emulate_modeselect(struct se_cmd *cmd)
int i; int i;
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
if (!pf) { if (!pf) {
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; ret = TCM_INVALID_CDB_FIELD;
ret = -EINVAL;
goto out; goto out;
} }
...@@ -1011,15 +1022,12 @@ static int spc_emulate_modeselect(struct se_cmd *cmd) ...@@ -1011,15 +1022,12 @@ static int spc_emulate_modeselect(struct se_cmd *cmd)
goto check_contents; goto check_contents;
} }
cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; ret = TCM_UNKNOWN_MODE_PAGE;
ret = -EINVAL;
goto out; goto out;
check_contents: check_contents:
if (memcmp(buf + off, tbuf, length)) { if (memcmp(buf + off, tbuf, length))
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
}
out: out:
transport_kunmap_data_sg(cmd); transport_kunmap_data_sg(cmd);
...@@ -1029,7 +1037,7 @@ static int spc_emulate_modeselect(struct se_cmd *cmd) ...@@ -1029,7 +1037,7 @@ static int spc_emulate_modeselect(struct se_cmd *cmd)
return ret; return ret;
} }
static int spc_emulate_request_sense(struct se_cmd *cmd) static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd)
{ {
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
unsigned char *rbuf; unsigned char *rbuf;
...@@ -1041,19 +1049,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) ...@@ -1041,19 +1049,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
if (cdb[1] & 0x01) { if (cdb[1] & 0x01) {
pr_err("REQUEST_SENSE description emulation not" pr_err("REQUEST_SENSE description emulation not"
" supported\n"); " supported\n");
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
return -ENOSYS;
} }
rbuf = transport_kmap_data_sg(cmd); rbuf = transport_kmap_data_sg(cmd);
if (cmd->scsi_sense_reason != 0) { if (!rbuf)
/* return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
* Out of memory. We will fail with CHECK CONDITION, so
* we must not clear the unit attention condition. if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
*/
target_complete_cmd(cmd, CHECK_CONDITION);
return 0;
} else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
/* /*
* CURRENT ERROR, UNIT ATTENTION * CURRENT ERROR, UNIT ATTENTION
*/ */
...@@ -1080,16 +1083,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) ...@@ -1080,16 +1083,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
buf[7] = 0x0A; buf[7] = 0x0A;
} }
if (rbuf) { memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); transport_kunmap_data_sg(cmd);
transport_kunmap_data_sg(cmd);
}
target_complete_cmd(cmd, GOOD); target_complete_cmd(cmd, GOOD);
return 0; return 0;
} }
int spc_emulate_report_luns(struct se_cmd *cmd) sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
{ {
struct se_dev_entry *deve; struct se_dev_entry *deve;
struct se_session *sess = cmd->se_sess; struct se_session *sess = cmd->se_sess;
...@@ -1099,13 +1100,12 @@ int spc_emulate_report_luns(struct se_cmd *cmd) ...@@ -1099,13 +1100,12 @@ int spc_emulate_report_luns(struct se_cmd *cmd)
if (cmd->data_length < 16) { if (cmd->data_length < 16) {
pr_warn("REPORT LUNS allocation length %u too small\n", pr_warn("REPORT LUNS allocation length %u too small\n",
cmd->data_length); cmd->data_length);
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf) if (!buf)
return -ENOMEM; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
/* /*
* If no struct se_session pointer is present, this struct se_cmd is * If no struct se_session pointer is present, this struct se_cmd is
...@@ -1153,13 +1153,15 @@ int spc_emulate_report_luns(struct se_cmd *cmd) ...@@ -1153,13 +1153,15 @@ int spc_emulate_report_luns(struct se_cmd *cmd)
} }
EXPORT_SYMBOL(spc_emulate_report_luns); EXPORT_SYMBOL(spc_emulate_report_luns);
static int spc_emulate_testunitready(struct se_cmd *cmd) static sense_reason_t
spc_emulate_testunitready(struct se_cmd *cmd)
{ {
target_complete_cmd(cmd, GOOD); target_complete_cmd(cmd, GOOD);
return 0; return 0;
} }
int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) sense_reason_t
spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
...@@ -1300,9 +1302,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) ...@@ -1300,9 +1302,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode" pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
" 0x%02x, sending CHECK_CONDITION.\n", " 0x%02x, sending CHECK_CONDITION.\n",
cmd->se_tfo->get_fabric_name(), cdb[0]); cmd->se_tfo->get_fabric_name(), cdb[0]);
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return TCM_UNSUPPORTED_SCSI_OPCODE;
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
return -EINVAL;
} }
return 0; return 0;
......
...@@ -557,7 +557,8 @@ static void target_complete_failure_work(struct work_struct *work) ...@@ -557,7 +557,8 @@ static void target_complete_failure_work(struct work_struct *work)
{ {
struct se_cmd *cmd = container_of(work, struct se_cmd, work); struct se_cmd *cmd = container_of(work, struct se_cmd, work);
transport_generic_request_failure(cmd); transport_generic_request_failure(cmd,
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE);
} }
/* /*
...@@ -625,7 +626,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) ...@@ -625,7 +626,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
complete(&cmd->t_transport_stop_comp); complete(&cmd->t_transport_stop_comp);
return; return;
} else if (cmd->transport_state & CMD_T_FAILED) { } else if (cmd->transport_state & CMD_T_FAILED) {
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
INIT_WORK(&cmd->work, target_complete_failure_work); INIT_WORK(&cmd->work, target_complete_failure_work);
} else { } else {
INIT_WORK(&cmd->work, target_complete_ok_work); INIT_WORK(&cmd->work, target_complete_ok_work);
...@@ -976,7 +976,8 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83) ...@@ -976,7 +976,8 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83)
} }
EXPORT_SYMBOL(transport_set_vpd_ident); EXPORT_SYMBOL(transport_set_vpd_ident);
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)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
...@@ -991,7 +992,7 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) ...@@ -991,7 +992,7 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
if (cmd->data_direction == DMA_TO_DEVICE) { if (cmd->data_direction == DMA_TO_DEVICE) {
pr_err("Rejecting underflow/overflow" pr_err("Rejecting underflow/overflow"
" WRITE data\n"); " WRITE data\n");
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
/* /*
* Reject READ_* or WRITE_* with overflow/underflow for * Reject READ_* or WRITE_* with overflow/underflow for
...@@ -1002,7 +1003,7 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) ...@@ -1002,7 +1003,7 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
" CDB on non 512-byte sector setup subsystem" " CDB on non 512-byte sector setup subsystem"
" plugin: %s\n", dev->transport->name); " plugin: %s\n", dev->transport->name);
/* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
goto out_invalid_cdb_field; return TCM_INVALID_CDB_FIELD;
} }
/* /*
* For the overflow case keep the existing fabric provided * For the overflow case keep the existing fabric provided
...@@ -1022,10 +1023,6 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) ...@@ -1022,10 +1023,6 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
return 0; return 0;
out_invalid_cdb_field:
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
/* /*
...@@ -1065,7 +1062,8 @@ void transport_init_se_cmd( ...@@ -1065,7 +1062,8 @@ void transport_init_se_cmd(
} }
EXPORT_SYMBOL(transport_init_se_cmd); EXPORT_SYMBOL(transport_init_se_cmd);
static int transport_check_alloc_task_attr(struct se_cmd *cmd) static sense_reason_t
transport_check_alloc_task_attr(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
...@@ -1079,7 +1077,7 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) ...@@ -1079,7 +1077,7 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd)
if (cmd->sam_task_attr == MSG_ACA_TAG) { if (cmd->sam_task_attr == MSG_ACA_TAG) {
pr_debug("SAM Task Attribute ACA" pr_debug("SAM Task Attribute ACA"
" emulation is not supported\n"); " emulation is not supported\n");
return -EINVAL; return TCM_INVALID_CDB_FIELD;
} }
/* /*
* Used to determine when ORDERED commands should go from * Used to determine when ORDERED commands should go from
...@@ -1093,17 +1091,12 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) ...@@ -1093,17 +1091,12 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd)
return 0; return 0;
} }
/* target_setup_cmd_from_cdb(): sense_reason_t
* target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
* Called from fabric RX Thread.
*/
int target_setup_cmd_from_cdb(
struct se_cmd *cmd,
unsigned char *cdb)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned long flags; unsigned long flags;
int ret; sense_reason_t ret;
/* /*
* Ensure that the received CDB is less than the max (252 + 8) bytes * Ensure that the received CDB is less than the max (252 + 8) bytes
...@@ -1113,9 +1106,7 @@ int target_setup_cmd_from_cdb( ...@@ -1113,9 +1106,7 @@ int target_setup_cmd_from_cdb(
pr_err("Received SCSI CDB with command_size: %d that" pr_err("Received SCSI CDB with command_size: %d that"
" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE); scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE);
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return TCM_INVALID_CDB_FIELD;
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
return -EINVAL;
} }
/* /*
* If the received CDB is larger than TCM_MAX_COMMAND_SIZE, * If the received CDB is larger than TCM_MAX_COMMAND_SIZE,
...@@ -1130,10 +1121,7 @@ int target_setup_cmd_from_cdb( ...@@ -1130,10 +1121,7 @@ int target_setup_cmd_from_cdb(
" %u > sizeof(cmd->__t_task_cdb): %lu ops\n", " %u > sizeof(cmd->__t_task_cdb): %lu ops\n",
scsi_command_size(cdb), scsi_command_size(cdb),
(unsigned long)sizeof(cmd->__t_task_cdb)); (unsigned long)sizeof(cmd->__t_task_cdb));
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return TCM_OUT_OF_RESOURCES;
cmd->scsi_sense_reason =
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -ENOMEM;
} }
} else } else
cmd->t_task_cdb = &cmd->__t_task_cdb[0]; cmd->t_task_cdb = &cmd->__t_task_cdb[0];
...@@ -1145,50 +1133,30 @@ int target_setup_cmd_from_cdb( ...@@ -1145,50 +1133,30 @@ int target_setup_cmd_from_cdb(
/* /*
* Check for an existing UNIT ATTENTION condition * Check for an existing UNIT ATTENTION condition
*/ */
if (core_scsi3_ua_check(cmd, cdb) < 0) { ret = target_scsi3_ua_check(cmd);
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; if (ret)
cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION; return ret;
return -EINVAL;
}
ret = target_alua_state_check(cmd); ret = target_alua_state_check(cmd);
if (ret) { if (ret)
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return ret;
if (ret > 0)
cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY;
else
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
return -EINVAL;
}
/*
* Check status for SPC-3 Persistent Reservations
*/
ret = target_check_reservation(cmd); ret = target_check_reservation(cmd);
if (ret) { if (ret)
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 ret; return ret;
}
ret = dev->transport->parse_cdb(cmd); ret = dev->transport->parse_cdb(cmd);
if (ret < 0) if (ret)
return ret;
ret = transport_check_alloc_task_attr(cmd);
if (ret)
return ret; return ret;
spin_lock_irqsave(&cmd->t_state_lock, flags); spin_lock_irqsave(&cmd->t_state_lock, flags);
cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
/*
* Check for SAM Task Attribute Emulation
*/
if (transport_check_alloc_task_attr(cmd) < 0) {
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
return -EINVAL;
}
spin_lock(&cmd->se_lun->lun_sep_lock); spin_lock(&cmd->se_lun->lun_sep_lock);
if (cmd->se_lun->lun_sep) if (cmd->se_lun->lun_sep)
cmd->se_lun->lun_sep->sep_stats.cmd_pdus++; cmd->se_lun->lun_sep->sep_stats.cmd_pdus++;
...@@ -1204,7 +1172,7 @@ EXPORT_SYMBOL(target_setup_cmd_from_cdb); ...@@ -1204,7 +1172,7 @@ EXPORT_SYMBOL(target_setup_cmd_from_cdb);
int transport_handle_cdb_direct( int transport_handle_cdb_direct(
struct se_cmd *cmd) struct se_cmd *cmd)
{ {
int ret; sense_reason_t ret;
if (!cmd->se_lun) { if (!cmd->se_lun) {
dump_stack(); dump_stack();
...@@ -1234,13 +1202,41 @@ int transport_handle_cdb_direct( ...@@ -1234,13 +1202,41 @@ int transport_handle_cdb_direct(
* and call transport_generic_request_failure() if necessary.. * and call transport_generic_request_failure() if necessary..
*/ */
ret = transport_generic_new_cmd(cmd); ret = transport_generic_new_cmd(cmd);
if (ret < 0) if (ret)
transport_generic_request_failure(cmd); transport_generic_request_failure(cmd, ret);
return 0; return 0;
} }
EXPORT_SYMBOL(transport_handle_cdb_direct); EXPORT_SYMBOL(transport_handle_cdb_direct);
static sense_reason_t
transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
u32 sgl_count, struct scatterlist *sgl_bidi, u32 sgl_bidi_count)
{
if (!sgl || !sgl_count)
return 0;
/*
* Reject SCSI data overflow with map_mem_to_cmd() as incoming
* scatterlists already have been set to follow what the fabric
* passes for the original expected data transfer length.
*/
if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
pr_warn("Rejecting SCSI DATA overflow for fabric using"
" SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n");
return TCM_INVALID_CDB_FIELD;
}
cmd->t_data_sg = sgl;
cmd->t_data_nents = sgl_count;
if (sgl_bidi && sgl_bidi_count) {
cmd->t_bidi_data_sg = sgl_bidi;
cmd->t_bidi_data_nents = sgl_bidi_count;
}
cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
return 0;
}
/* /*
* target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized * target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized
* se_cmd + use pre-allocated SGL memory. * se_cmd + use pre-allocated SGL memory.
...@@ -1273,7 +1269,8 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess ...@@ -1273,7 +1269,8 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
struct scatterlist *sgl_bidi, u32 sgl_bidi_count) struct scatterlist *sgl_bidi, u32 sgl_bidi_count)
{ {
struct se_portal_group *se_tpg; struct se_portal_group *se_tpg;
int rc; sense_reason_t rc;
int ret;
se_tpg = se_sess->se_tpg; se_tpg = se_sess->se_tpg;
BUG_ON(!se_tpg); BUG_ON(!se_tpg);
...@@ -1294,9 +1291,9 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess ...@@ -1294,9 +1291,9 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
* for fabrics using TARGET_SCF_ACK_KREF that expect a second * for fabrics using TARGET_SCF_ACK_KREF that expect a second
* kref_put() to happen during fabric packet acknowledgement. * kref_put() to happen during fabric packet acknowledgement.
*/ */
rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
if (rc) if (ret)
return rc; return ret;
/* /*
* Signal bidirectional data payloads to target-core * Signal bidirectional data payloads to target-core
*/ */
...@@ -1305,16 +1302,16 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess ...@@ -1305,16 +1302,16 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
/* /*
* Locate se_lun pointer and attach it to struct se_cmd * Locate se_lun pointer and attach it to struct se_cmd
*/ */
if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) { rc = transport_lookup_cmd_lun(se_cmd, unpacked_lun);
transport_send_check_condition_and_sense(se_cmd, if (rc) {
se_cmd->scsi_sense_reason, 0); transport_send_check_condition_and_sense(se_cmd, rc, 0);
target_put_sess_cmd(se_sess, se_cmd); target_put_sess_cmd(se_sess, se_cmd);
return 0; return 0;
} }
rc = target_setup_cmd_from_cdb(se_cmd, cdb); rc = target_setup_cmd_from_cdb(se_cmd, cdb);
if (rc != 0) { if (rc != 0) {
transport_generic_request_failure(se_cmd); transport_generic_request_failure(se_cmd, rc);
return 0; return 0;
} }
/* /*
...@@ -1349,7 +1346,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess ...@@ -1349,7 +1346,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
rc = transport_generic_map_mem_to_cmd(se_cmd, sgl, sgl_count, rc = transport_generic_map_mem_to_cmd(se_cmd, sgl, sgl_count,
sgl_bidi, sgl_bidi_count); sgl_bidi, sgl_bidi_count);
if (rc != 0) { if (rc != 0) {
transport_generic_request_failure(se_cmd); transport_generic_request_failure(se_cmd, rc);
return 0; return 0;
} }
} }
...@@ -1495,16 +1492,17 @@ bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags) ...@@ -1495,16 +1492,17 @@ bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags)
/* /*
* Handle SAM-esque emulation for generic transport request failures. * Handle SAM-esque emulation for generic transport request failures.
*/ */
void transport_generic_request_failure(struct se_cmd *cmd) void transport_generic_request_failure(struct se_cmd *cmd,
sense_reason_t sense_reason)
{ {
int ret = 0; int ret = 0;
pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x" pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x"
" CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd), " CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd),
cmd->t_task_cdb[0]); cmd->t_task_cdb[0]);
pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n", pr_debug("-----[ i_state: %d t_state: %d sense_reason: %d\n",
cmd->se_tfo->get_cmd_state(cmd), cmd->se_tfo->get_cmd_state(cmd),
cmd->t_state, cmd->scsi_sense_reason); cmd->t_state, sense_reason);
pr_debug("-----[ CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n", pr_debug("-----[ CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n",
(cmd->transport_state & CMD_T_ACTIVE) != 0, (cmd->transport_state & CMD_T_ACTIVE) != 0,
(cmd->transport_state & CMD_T_STOP) != 0, (cmd->transport_state & CMD_T_STOP) != 0,
...@@ -1515,7 +1513,7 @@ void transport_generic_request_failure(struct se_cmd *cmd) ...@@ -1515,7 +1513,7 @@ void transport_generic_request_failure(struct se_cmd *cmd)
*/ */
transport_complete_task_attr(cmd); transport_complete_task_attr(cmd);
switch (cmd->scsi_sense_reason) { switch (sense_reason) {
case TCM_NON_EXISTENT_LUN: case TCM_NON_EXISTENT_LUN:
case TCM_UNSUPPORTED_SCSI_OPCODE: case TCM_UNSUPPORTED_SCSI_OPCODE:
case TCM_INVALID_CDB_FIELD: case TCM_INVALID_CDB_FIELD:
...@@ -1528,6 +1526,9 @@ void transport_generic_request_failure(struct se_cmd *cmd) ...@@ -1528,6 +1526,9 @@ void transport_generic_request_failure(struct se_cmd *cmd)
case TCM_CHECK_CONDITION_UNIT_ATTENTION: case TCM_CHECK_CONDITION_UNIT_ATTENTION:
case TCM_CHECK_CONDITION_NOT_READY: case TCM_CHECK_CONDITION_NOT_READY:
break; break;
case TCM_OUT_OF_RESOURCES:
sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
break;
case TCM_RESERVATION_CONFLICT: case TCM_RESERVATION_CONFLICT:
/* /*
* No SENSE Data payload for this case, set SCSI Status * No SENSE Data payload for this case, set SCSI Status
...@@ -1555,13 +1556,12 @@ void transport_generic_request_failure(struct se_cmd *cmd) ...@@ -1555,13 +1556,12 @@ void transport_generic_request_failure(struct se_cmd *cmd)
goto check_stop; goto check_stop;
default: default:
pr_err("Unknown transport error for CDB 0x%02x: %d\n", pr_err("Unknown transport error for CDB 0x%02x: %d\n",
cmd->t_task_cdb[0], cmd->scsi_sense_reason); cmd->t_task_cdb[0], sense_reason);
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
break; break;
} }
ret = transport_send_check_condition_and_sense(cmd, ret = transport_send_check_condition_and_sense(cmd, sense_reason, 0);
cmd->scsi_sense_reason, 0);
if (ret == -EAGAIN || ret == -ENOMEM) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
...@@ -1579,21 +1579,21 @@ EXPORT_SYMBOL(transport_generic_request_failure); ...@@ -1579,21 +1579,21 @@ EXPORT_SYMBOL(transport_generic_request_failure);
static void __target_execute_cmd(struct se_cmd *cmd) static void __target_execute_cmd(struct se_cmd *cmd)
{ {
int error = 0; sense_reason_t ret;
spin_lock_irq(&cmd->t_state_lock); spin_lock_irq(&cmd->t_state_lock);
cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT); cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT);
spin_unlock_irq(&cmd->t_state_lock); spin_unlock_irq(&cmd->t_state_lock);
if (cmd->execute_cmd) if (cmd->execute_cmd) {
error = cmd->execute_cmd(cmd); ret = cmd->execute_cmd(cmd);
if (ret) {
if (error) { spin_lock_irq(&cmd->t_state_lock);
spin_lock_irq(&cmd->t_state_lock); cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); spin_unlock_irq(&cmd->t_state_lock);
spin_unlock_irq(&cmd->t_state_lock);
transport_generic_request_failure(cmd); transport_generic_request_failure(cmd, ret);
}
} }
} }
...@@ -1987,53 +1987,6 @@ static void transport_put_cmd(struct se_cmd *cmd) ...@@ -1987,53 +1987,6 @@ static void transport_put_cmd(struct se_cmd *cmd)
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
} }
/*
* transport_generic_map_mem_to_cmd - Use fabric-alloced pages instead of
* allocating in the core.
* @cmd: Associated se_cmd descriptor
* @mem: SGL style memory for TCM WRITE / READ
* @sg_mem_num: Number of SGL elements
* @mem_bidi_in: SGL style memory for TCM BIDI READ
* @sg_mem_bidi_num: Number of BIDI READ SGL elements
*
* Return: nonzero return cmd was rejected for -ENOMEM or inproper usage
* of parameters.
*/
int transport_generic_map_mem_to_cmd(
struct se_cmd *cmd,
struct scatterlist *sgl,
u32 sgl_count,
struct scatterlist *sgl_bidi,
u32 sgl_bidi_count)
{
if (!sgl || !sgl_count)
return 0;
/*
* Reject SCSI data overflow with map_mem_to_cmd() as incoming
* scatterlists already have been set to follow what the fabric
* passes for the original expected data transfer length.
*/
if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
pr_warn("Rejecting SCSI DATA overflow for fabric using"
" SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n");
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
return -EINVAL;
}
cmd->t_data_sg = sgl;
cmd->t_data_nents = sgl_count;
if (sgl_bidi && sgl_bidi_count) {
cmd->t_bidi_data_sg = sgl_bidi;
cmd->t_bidi_data_nents = sgl_bidi_count;
}
cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
return 0;
}
EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
void *transport_kmap_data_sg(struct se_cmd *cmd) void *transport_kmap_data_sg(struct se_cmd *cmd)
{ {
struct scatterlist *sg = cmd->t_data_sg; struct scatterlist *sg = cmd->t_data_sg;
...@@ -2054,10 +2007,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) ...@@ -2054,10 +2007,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
/* >1 page. use vmap */ /* >1 page. use vmap */
pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
if (!pages) { if (!pages)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return NULL; return NULL;
}
/* convert sg[] to pages[] */ /* convert sg[] to pages[] */
for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
...@@ -2066,10 +2017,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) ...@@ -2066,10 +2017,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL);
kfree(pages); kfree(pages);
if (!cmd->t_data_vmap) { if (!cmd->t_data_vmap)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return NULL; return NULL;
}
return cmd->t_data_vmap + cmd->t_data_sg[0].offset; return cmd->t_data_vmap + cmd->t_data_sg[0].offset;
} }
...@@ -2135,7 +2084,8 @@ transport_generic_get_mem(struct se_cmd *cmd) ...@@ -2135,7 +2084,8 @@ transport_generic_get_mem(struct se_cmd *cmd)
* might not have the payload yet, so notify the fabric via a call to * might not have the payload yet, so notify the fabric via a call to
* ->write_pending instead. Otherwise place it on the execution queue. * ->write_pending instead. Otherwise place it on the execution queue.
*/ */
int transport_generic_new_cmd(struct se_cmd *cmd) sense_reason_t
transport_generic_new_cmd(struct se_cmd *cmd)
{ {
int ret = 0; int ret = 0;
...@@ -2148,7 +2098,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd) ...@@ -2148,7 +2098,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
cmd->data_length) { cmd->data_length) {
ret = transport_generic_get_mem(cmd); ret = transport_generic_get_mem(cmd);
if (ret < 0) if (ret < 0)
goto out_fail; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
atomic_inc(&cmd->t_fe_count); atomic_inc(&cmd->t_fe_count);
...@@ -2174,14 +2124,11 @@ int transport_generic_new_cmd(struct se_cmd *cmd) ...@@ -2174,14 +2124,11 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
if (ret == -EAGAIN || ret == -ENOMEM) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
if (ret < 0) /* fabric drivers should only return -EAGAIN or -ENOMEM as error */
return ret; WARN_ON(ret);
return 1;
return 0;
out_fail:
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
queue_full: queue_full:
pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
cmd->t_state = TRANSPORT_COMPLETE_QF_WP; cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
...@@ -2625,10 +2572,9 @@ static int transport_get_sense_codes( ...@@ -2625,10 +2572,9 @@ static int transport_get_sense_codes(
return 0; return 0;
} }
int transport_send_check_condition_and_sense( int
struct se_cmd *cmd, transport_send_check_condition_and_sense(struct se_cmd *cmd,
u8 reason, sense_reason_t reason, int from_transport)
int from_transport)
{ {
unsigned char *buffer = cmd->sense_buffer; unsigned char *buffer = cmd->sense_buffer;
unsigned long flags; unsigned long flags;
......
...@@ -38,9 +38,8 @@ ...@@ -38,9 +38,8 @@
#include "target_core_pr.h" #include "target_core_pr.h"
#include "target_core_ua.h" #include "target_core_ua.h"
int core_scsi3_ua_check( sense_reason_t
struct se_cmd *cmd, target_scsi3_ua_check(struct se_cmd *cmd)
unsigned char *cdb)
{ {
struct se_dev_entry *deve; struct se_dev_entry *deve;
struct se_session *sess = cmd->se_sess; struct se_session *sess = cmd->se_sess;
...@@ -71,16 +70,14 @@ int core_scsi3_ua_check( ...@@ -71,16 +70,14 @@ int core_scsi3_ua_check(
* was received, then the device server shall process the command * was received, then the device server shall process the command
* and either: * and either:
*/ */
switch (cdb[0]) { switch (cmd->t_task_cdb[0]) {
case INQUIRY: case INQUIRY:
case REPORT_LUNS: case REPORT_LUNS:
case REQUEST_SENSE: case REQUEST_SENSE:
return 0; return 0;
default: default:
return -EINVAL; return TCM_CHECK_CONDITION_UNIT_ATTENTION;
} }
return -EINVAL;
} }
int core_scsi3_ua_allocate( int core_scsi3_ua_allocate(
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
extern struct kmem_cache *se_ua_cache; extern struct kmem_cache *se_ua_cache;
extern int core_scsi3_ua_check(struct se_cmd *, unsigned char *); extern sense_reason_t target_scsi3_ua_check(struct se_cmd *);
extern int core_scsi3_ua_allocate(struct se_node_acl *, u32, u8, u8); extern int core_scsi3_ua_allocate(struct se_node_acl *, u32, u8, u8);
extern void core_scsi3_ua_release_all(struct se_dev_entry *); extern void core_scsi3_ua_release_all(struct se_dev_entry *);
extern void core_scsi3_ua_for_check_condition(struct se_cmd *, u8 *, u8 *); extern void core_scsi3_ua_for_check_condition(struct se_cmd *, u8 *, u8 *);
......
...@@ -541,10 +541,6 @@ static void tcm_vhost_submission_work(struct work_struct *work) ...@@ -541,10 +541,6 @@ static void tcm_vhost_submission_work(struct work_struct *work)
if (tv_cmd->tvc_sgl_count) { if (tv_cmd->tvc_sgl_count) {
sg_ptr = tv_cmd->tvc_sgl; sg_ptr = tv_cmd->tvc_sgl;
/*
* For BIDI commands, pass in the extra READ buffer
* to transport_generic_map_mem_to_cmd() below..
*/
/* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */ /* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */
#if 0 #if 0
if (se_cmd->se_cmd_flags & SCF_BIDI) { if (se_cmd->se_cmd_flags & SCF_BIDI) {
......
...@@ -31,17 +31,17 @@ struct se_subsystem_api { ...@@ -31,17 +31,17 @@ struct se_subsystem_api {
struct scatterlist *, struct scatterlist *,
unsigned char *); unsigned char *);
int (*parse_cdb)(struct se_cmd *cmd); sense_reason_t (*parse_cdb)(struct se_cmd *cmd);
u32 (*get_device_type)(struct se_device *); u32 (*get_device_type)(struct se_device *);
sector_t (*get_blocks)(struct se_device *); sector_t (*get_blocks)(struct se_device *);
unsigned char *(*get_sense_buffer)(struct se_cmd *); unsigned char *(*get_sense_buffer)(struct se_cmd *);
}; };
struct sbc_ops { struct sbc_ops {
int (*execute_rw)(struct se_cmd *cmd); sense_reason_t (*execute_rw)(struct se_cmd *cmd);
int (*execute_sync_cache)(struct se_cmd *cmd); sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd);
int (*execute_write_same)(struct se_cmd *cmd); sense_reason_t (*execute_write_same)(struct se_cmd *cmd);
int (*execute_unmap)(struct se_cmd *cmd); sense_reason_t (*execute_unmap)(struct se_cmd *cmd);
}; };
int transport_subsystem_register(struct se_subsystem_api *); int transport_subsystem_register(struct se_subsystem_api *);
...@@ -49,11 +49,11 @@ void transport_subsystem_release(struct se_subsystem_api *); ...@@ -49,11 +49,11 @@ void transport_subsystem_release(struct se_subsystem_api *);
void target_complete_cmd(struct se_cmd *, u8); void target_complete_cmd(struct se_cmd *, u8);
int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size);
int spc_emulate_report_luns(struct se_cmd *cmd); sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd);
int spc_get_write_same_sectors(struct se_cmd *cmd); int spc_get_write_same_sectors(struct se_cmd *cmd);
int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops);
u32 sbc_get_device_rev(struct se_device *dev); u32 sbc_get_device_rev(struct se_device *dev);
u32 sbc_get_device_type(struct se_device *dev); u32 sbc_get_device_type(struct se_device *dev);
......
...@@ -144,8 +144,6 @@ enum se_cmd_flags_table { ...@@ -144,8 +144,6 @@ enum se_cmd_flags_table {
SCF_EMULATED_TASK_SENSE = 0x00000004, SCF_EMULATED_TASK_SENSE = 0x00000004,
SCF_SCSI_DATA_CDB = 0x00000008, SCF_SCSI_DATA_CDB = 0x00000008,
SCF_SCSI_TMR_CDB = 0x00000010, SCF_SCSI_TMR_CDB = 0x00000010,
SCF_SCSI_CDB_EXCEPTION = 0x00000020,
SCF_SCSI_RESERVATION_CONFLICT = 0x00000040,
SCF_FUA = 0x00000080, SCF_FUA = 0x00000080,
SCF_SE_LUN_CMD = 0x00000100, SCF_SE_LUN_CMD = 0x00000100,
SCF_BIDI = 0x00000400, SCF_BIDI = 0x00000400,
...@@ -167,27 +165,32 @@ enum transport_lunflags_table { ...@@ -167,27 +165,32 @@ enum transport_lunflags_table {
}; };
/* /*
* Used by transport_send_check_condition_and_sense() and se_cmd->scsi_sense_reason * Used by transport_send_check_condition_and_sense()
* to signal which ASC/ASCQ sense payload should be built. * to signal which ASC/ASCQ sense payload should be built.
*/ */
typedef unsigned __bitwise__ sense_reason_t;
enum tcm_sense_reason_table { enum tcm_sense_reason_table {
TCM_NON_EXISTENT_LUN = 0x01, #define R(x) (__force sense_reason_t )(x)
TCM_UNSUPPORTED_SCSI_OPCODE = 0x02, TCM_NON_EXISTENT_LUN = R(0x01),
TCM_INCORRECT_AMOUNT_OF_DATA = 0x03, TCM_UNSUPPORTED_SCSI_OPCODE = R(0x02),
TCM_UNEXPECTED_UNSOLICITED_DATA = 0x04, TCM_INCORRECT_AMOUNT_OF_DATA = R(0x03),
TCM_SERVICE_CRC_ERROR = 0x05, TCM_UNEXPECTED_UNSOLICITED_DATA = R(0x04),
TCM_SNACK_REJECTED = 0x06, TCM_SERVICE_CRC_ERROR = R(0x05),
TCM_SECTOR_COUNT_TOO_MANY = 0x07, TCM_SNACK_REJECTED = R(0x06),
TCM_INVALID_CDB_FIELD = 0x08, TCM_SECTOR_COUNT_TOO_MANY = R(0x07),
TCM_INVALID_PARAMETER_LIST = 0x09, TCM_INVALID_CDB_FIELD = R(0x08),
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE = 0x0a, TCM_INVALID_PARAMETER_LIST = R(0x09),
TCM_UNKNOWN_MODE_PAGE = 0x0b, TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE = R(0x0a),
TCM_WRITE_PROTECTED = 0x0c, TCM_UNKNOWN_MODE_PAGE = R(0x0b),
TCM_CHECK_CONDITION_ABORT_CMD = 0x0d, TCM_WRITE_PROTECTED = R(0x0c),
TCM_CHECK_CONDITION_UNIT_ATTENTION = 0x0e, TCM_CHECK_CONDITION_ABORT_CMD = R(0x0d),
TCM_CHECK_CONDITION_NOT_READY = 0x0f, TCM_CHECK_CONDITION_UNIT_ATTENTION = R(0x0e),
TCM_RESERVATION_CONFLICT = 0x10, TCM_CHECK_CONDITION_NOT_READY = R(0x0f),
TCM_ADDRESS_OUT_OF_RANGE = 0x11, TCM_RESERVATION_CONFLICT = R(0x10),
TCM_ADDRESS_OUT_OF_RANGE = R(0x11),
TCM_OUT_OF_RESOURCES = R(0x12),
#undef R
}; };
enum target_sc_flags_table { enum target_sc_flags_table {
...@@ -407,7 +410,6 @@ struct se_cmd { ...@@ -407,7 +410,6 @@ struct se_cmd {
u8 scsi_status; u8 scsi_status;
u8 scsi_asc; u8 scsi_asc;
u8 scsi_ascq; u8 scsi_ascq;
u8 scsi_sense_reason;
u16 scsi_sense_length; u16 scsi_sense_length;
/* Delay for ALUA Active/NonOptimized state access in milliseconds */ /* Delay for ALUA Active/NonOptimized state access in milliseconds */
int alua_nonop_delay; int alua_nonop_delay;
...@@ -445,7 +447,7 @@ struct se_cmd { ...@@ -445,7 +447,7 @@ struct se_cmd {
struct completion cmd_wait_comp; struct completion cmd_wait_comp;
struct kref cmd_kref; struct kref cmd_kref;
struct target_core_fabric_ops *se_tfo; struct target_core_fabric_ops *se_tfo;
int (*execute_cmd)(struct se_cmd *); sense_reason_t (*execute_cmd)(struct se_cmd *);
void (*transport_complete_callback)(struct se_cmd *); void (*transport_complete_callback)(struct se_cmd *);
unsigned char *t_task_cdb; unsigned char *t_task_cdb;
......
...@@ -98,8 +98,8 @@ void transport_deregister_session(struct se_session *); ...@@ -98,8 +98,8 @@ void transport_deregister_session(struct se_session *);
void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *, void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
struct se_session *, u32, int, int, unsigned char *); struct se_session *, u32, int, int, unsigned char *);
int transport_lookup_cmd_lun(struct se_cmd *, u32); sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u32);
int target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *, int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *,
unsigned char *, unsigned char *, u32, u32, int, int, int, unsigned char *, unsigned char *, u32, u32, int, int, int,
struct scatterlist *, u32, struct scatterlist *, u32); struct scatterlist *, u32, struct scatterlist *, u32);
...@@ -110,9 +110,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, ...@@ -110,9 +110,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
void *fabric_tmr_ptr, unsigned char tm_type, void *fabric_tmr_ptr, unsigned char tm_type,
gfp_t, unsigned int, int); gfp_t, unsigned int, int);
int transport_handle_cdb_direct(struct se_cmd *); int transport_handle_cdb_direct(struct se_cmd *);
int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, sense_reason_t transport_generic_new_cmd(struct se_cmd *);
struct scatterlist *, u32, struct scatterlist *, u32);
int transport_generic_new_cmd(struct se_cmd *);
void target_execute_cmd(struct se_cmd *cmd); void target_execute_cmd(struct se_cmd *cmd);
...@@ -120,7 +118,8 @@ void transport_generic_free_cmd(struct se_cmd *, int); ...@@ -120,7 +118,8 @@ void transport_generic_free_cmd(struct se_cmd *, int);
bool transport_wait_for_tasks(struct se_cmd *); bool transport_wait_for_tasks(struct se_cmd *);
int transport_check_aborted_status(struct se_cmd *, int); int transport_check_aborted_status(struct se_cmd *, int);
int transport_send_check_condition_and_sense(struct se_cmd *, u8, int); int transport_send_check_condition_and_sense(struct se_cmd *,
sense_reason_t, int);
int target_put_sess_cmd(struct se_session *, struct se_cmd *); int target_put_sess_cmd(struct se_session *, struct se_cmd *);
void target_sess_cmd_list_set_waiting(struct se_session *); void target_sess_cmd_list_set_waiting(struct se_session *);
...@@ -131,7 +130,7 @@ int core_alua_check_nonop_delay(struct se_cmd *); ...@@ -131,7 +130,7 @@ int core_alua_check_nonop_delay(struct se_cmd *);
int core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t); int core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t);
void core_tmr_release_req(struct se_tmr_req *); void core_tmr_release_req(struct se_tmr_req *);
int transport_generic_handle_tmr(struct se_cmd *); int transport_generic_handle_tmr(struct se_cmd *);
void transport_generic_request_failure(struct se_cmd *); void transport_generic_request_failure(struct se_cmd *, sense_reason_t);
int transport_lookup_tmr_lun(struct se_cmd *, u32); int transport_lookup_tmr_lun(struct se_cmd *, u32);
struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *, struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment