void iscsit_handle_dataout_timeout()

in iscsi/iscsi_target_erl1.c [1094:1180]


void iscsit_handle_dataout_timeout(struct timer_list *t)
{
	u32 pdu_length = 0, pdu_offset = 0;
	u32 r2t_length = 0, r2t_offset = 0;
	struct iscsi_cmd *cmd = from_timer(cmd, t, dataout_timer);
	struct iscsi_conn *conn = cmd->conn;
	struct iscsi_session *sess = NULL;
	struct iscsi_node_attrib *na;

	iscsit_inc_conn_usage_count(conn);

	spin_lock_bh(&cmd->dataout_timeout_lock);
	if (cmd->dataout_timer_flags & ISCSI_TF_STOP) {
		spin_unlock_bh(&cmd->dataout_timeout_lock);
		iscsit_dec_conn_usage_count(conn);
		return;
	}
	cmd->dataout_timer_flags &= ~ISCSI_TF_RUNNING;
	sess = conn->sess;
	na = iscsit_tpg_get_node_attrib(sess);

	if (!sess->sess_ops->ErrorRecoveryLevel) {
		pr_err("Unable to recover from DataOut timeout while"
			" in ERL=0, closing iSCSI connection for I_T Nexus"
			" %s,i,0x%6phN,%s,t,0x%02x\n",
			sess->sess_ops->InitiatorName, sess->isid,
			sess->tpg->tpg_tiqn->tiqn, (u32)sess->tpg->tpgt);
		goto failure;
	}

	if (++cmd->dataout_timeout_retries == na->dataout_timeout_retries) {
		pr_err("Command ITT: 0x%08x exceeded max retries"
			" for DataOUT timeout %u, closing iSCSI connection for"
			" I_T Nexus %s,i,0x%6phN,%s,t,0x%02x\n",
			cmd->init_task_tag, na->dataout_timeout_retries,
			sess->sess_ops->InitiatorName, sess->isid,
			sess->tpg->tpg_tiqn->tiqn, (u32)sess->tpg->tpgt);
		goto failure;
	}

	cmd->cmd_flags |= ICF_WITHIN_COMMAND_RECOVERY;

	if (conn->sess->sess_ops->DataSequenceInOrder) {
		if (conn->sess->sess_ops->DataPDUInOrder) {
			pdu_offset = cmd->write_data_done;
			if ((pdu_offset + (conn->sess->sess_ops->MaxBurstLength -
			     cmd->next_burst_len)) > cmd->se_cmd.data_length)
				pdu_length = (cmd->se_cmd.data_length -
					cmd->write_data_done);
			else
				pdu_length = (conn->sess->sess_ops->MaxBurstLength -
						cmd->next_burst_len);
		} else {
			pdu_offset = cmd->seq_start_offset;
			pdu_length = (cmd->seq_end_offset -
				cmd->seq_start_offset);
		}
	} else {
		if (iscsit_set_dataout_timeout_values(cmd, &pdu_offset,
				&pdu_length) < 0)
			goto failure;
	}

	if (iscsit_recalculate_dataout_values(cmd, pdu_offset, pdu_length,
			&r2t_offset, &r2t_length) < 0)
		goto failure;

	pr_debug("Command ITT: 0x%08x timed out waiting for"
		" completion of %sDataOUT Sequence Offset: %u, Length: %u\n",
		cmd->init_task_tag, (cmd->unsolicited_data) ? "Unsolicited " :
		"", r2t_offset, r2t_length);

	if (iscsit_send_recovery_r2t(cmd, r2t_offset, r2t_length) < 0)
		goto failure;

	iscsit_start_dataout_timer(cmd, conn);
	spin_unlock_bh(&cmd->dataout_timeout_lock);
	iscsit_dec_conn_usage_count(conn);

	return;

failure:
	spin_unlock_bh(&cmd->dataout_timeout_lock);
	iscsit_fill_cxn_timeout_err_stats(sess);
	iscsit_cause_connection_reinstatement(conn, 0);
	iscsit_dec_conn_usage_count(conn);
}