int iscsit_execute_cmd()

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;
}