in iscsi/iscsi_target_erl1.c [887:995]
int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
{
struct se_cmd *se_cmd = &cmd->se_cmd;
struct iscsi_conn *conn = cmd->conn;
int lr = 0;
spin_lock_bh(&cmd->istate_lock);
if (ooo)
cmd->cmd_flags &= ~ICF_OOO_CMDSN;
switch (cmd->iscsi_opcode) {
case ISCSI_OP_SCSI_CMD:
/*
* Go ahead and send the CHECK_CONDITION status for
* any SCSI CDB exceptions that may have occurred.
*/
if (cmd->sense_reason) {
if (cmd->sense_reason == TCM_RESERVATION_CONFLICT) {
cmd->i_state = ISTATE_SEND_STATUS;
spin_unlock_bh(&cmd->istate_lock);
iscsit_add_cmd_to_response_queue(cmd, cmd->conn,
cmd->i_state);
return 0;
}
spin_unlock_bh(&cmd->istate_lock);
if (cmd->se_cmd.transport_state & CMD_T_ABORTED)
return 0;
return transport_send_check_condition_and_sense(se_cmd,
cmd->sense_reason, 0);
}
/*
* Special case for delayed CmdSN with Immediate
* Data and/or Unsolicited Data Out attached.
*/
if (cmd->immediate_data) {
if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
spin_unlock_bh(&cmd->istate_lock);
target_execute_cmd(&cmd->se_cmd);
return 0;
}
spin_unlock_bh(&cmd->istate_lock);
if (!(cmd->cmd_flags &
ICF_NON_IMMEDIATE_UNSOLICITED_DATA)) {
if (cmd->se_cmd.transport_state & CMD_T_ABORTED)
return 0;
iscsit_set_dataout_sequence_values(cmd);
conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
}
return 0;
}
/*
* The default handler.
*/
spin_unlock_bh(&cmd->istate_lock);
if ((cmd->data_direction == DMA_TO_DEVICE) &&
!(cmd->cmd_flags & ICF_NON_IMMEDIATE_UNSOLICITED_DATA)) {
if (cmd->se_cmd.transport_state & CMD_T_ABORTED)
return 0;
iscsit_set_unsolicited_dataout(cmd);
}
return transport_handle_cdb_direct(&cmd->se_cmd);
case ISCSI_OP_NOOP_OUT:
case ISCSI_OP_TEXT:
spin_unlock_bh(&cmd->istate_lock);
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
break;
case ISCSI_OP_SCSI_TMFUNC:
if (cmd->se_cmd.se_tmr_req->response) {
spin_unlock_bh(&cmd->istate_lock);
iscsit_add_cmd_to_response_queue(cmd, cmd->conn,
cmd->i_state);
return 0;
}
spin_unlock_bh(&cmd->istate_lock);
return transport_generic_handle_tmr(&cmd->se_cmd);
case ISCSI_OP_LOGOUT:
spin_unlock_bh(&cmd->istate_lock);
switch (cmd->logout_reason) {
case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
lr = iscsit_logout_closesession(cmd, cmd->conn);
break;
case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
lr = iscsit_logout_closeconnection(cmd, cmd->conn);
break;
case ISCSI_LOGOUT_REASON_RECOVERY:
lr = iscsit_logout_removeconnforrecovery(cmd, cmd->conn);
break;
default:
pr_err("Unknown iSCSI Logout Request Code:"
" 0x%02x\n", cmd->logout_reason);
return -1;
}
return lr;
default:
spin_unlock_bh(&cmd->istate_lock);
pr_err("Cannot perform out of order execution for"
" unknown iSCSI Opcode: 0x%02x\n", cmd->iscsi_opcode);
return -1;
}
return 0;
}