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