- Fixing case when during SRRs ping-pong between initiator and target HW pending timeout gets triggered and the corresponding command deleted => oops on the next ping-pong turn

- Minor cleanups and fixes



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1662 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2010-04-28 16:54:22 +00:00
parent 5a87f2af9e
commit a6270011ec
4 changed files with 54 additions and 13 deletions

View File

@@ -2604,6 +2604,9 @@ static int q2t_prepare_srr_ctio(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
goto out;
}
if (cmd->scst_cmd != NULL)
scst_update_hw_pending_start(cmd->scst_cmd);
sc = kzalloc(sizeof(*sc), GFP_ATOMIC);
if (sc != NULL) {
sc->cmd = cmd;
@@ -3604,6 +3607,8 @@ static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
TRACE_ENTRY();
TRACE_MGMT_DBG("SRR cmd %p, srr_ui %x", cmd, ntfy->srr_ui);
switch (ntfy->srr_ui) {
case SRR_IU_STATUS:
spin_lock_irq(&ha->hardware_lock);
@@ -3702,6 +3707,8 @@ static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
TRACE_ENTRY();
TRACE_MGMT_DBG("SRR cmd %p, srr_ui %x", cmd, ntfy->srr_ui);
switch (ntfy->srr_ui) {
case SRR_IU_STATUS:
spin_lock_irq(&ha->hardware_lock);

View File

@@ -2451,6 +2451,8 @@ static inline void scst_tgt_set_tgt_priv(struct scst_tgt *tgt, void *val)
tgt->tgt_priv = val;
}
void scst_update_hw_pending_start(struct scst_cmd *cmd);
/*
* Get/Set functions for session's target private data
*/

View File

@@ -1891,7 +1891,35 @@ out_unlock_tgt:
return res;
}
/* Returns 0 to continue, >0 to restart, <0 to break */
/**
* scst_update_hw_pending_start() - update commands pending start
*
* Updates the command's hw_pending_start as if it's just started hw pending.
* Target drivers should call it if they received reply from this pending
* command, but SCST core won't see it.
*/
void scst_update_hw_pending_start(struct scst_cmd *cmd)
{
unsigned long flags;
TRACE_ENTRY();
/* To sync with scst_check_hw_pending_cmd() */
spin_lock_irqsave(&cmd->sess->sess_list_lock, flags);
cmd->hw_pending_start = jiffies;
TRACE_MGMT_DBG("Updated hw_pending_start to %ld (cmd %p)",
cmd->hw_pending_start, cmd);
spin_unlock_irqrestore(&cmd->sess->sess_list_lock, flags);
TRACE_EXIT();
return;
}
EXPORT_SYMBOL(scst_update_hw_pending_start);
/*
* Supposed to be called under sess_list_lock, but can release/reaquire it.
* Returns 0 to continue, >0 to restart, <0 to break.
*/
static int scst_check_hw_pending_cmd(struct scst_cmd *cmd,
unsigned long cur_time, unsigned long max_time,
struct scst_session *sess, unsigned long *flags,
@@ -1904,7 +1932,7 @@ static int scst_check_hw_pending_cmd(struct scst_cmd *cmd,
(long)(cur_time - cmd->start_time) / HZ,
(long)(cur_time - cmd->hw_pending_start) / HZ);
if (time_before_eq(cur_time, cmd->start_time + max_time)) {
if (time_before(cur_time, cmd->start_time + max_time)) {
/* Cmds are ordered, so no need to check more */
goto out;
}
@@ -1915,7 +1943,7 @@ static int scst_check_hw_pending_cmd(struct scst_cmd *cmd,
}
if (time_before(cur_time, cmd->hw_pending_start + max_time)) {
/* Cmds are ordered, so no need to check more */
res = 0; /* continue */
goto out;
}
@@ -5412,9 +5440,8 @@ int scst_obtain_device_parameters(struct scst_device *dev)
if (scsi_status_is_good(rc)) {
int q;
PRINT_BUFF_FLAG(TRACE_SCSI,
"Returned control mode page data",
buffer, sizeof(buffer));
PRINT_BUFF_FLAG(TRACE_SCSI, "Returned control mode "
"page data", buffer, sizeof(buffer));
dev->tst = buffer[4+2] >> 5;
q = buffer[4+3] >> 4;
@@ -5455,9 +5482,9 @@ int scst_obtain_device_parameters(struct scst_device *dev)
*/
if (SCST_SENSE_VALID(sense_buffer)) {
#endif
PRINT_BUFF_FLAG(TRACE_SCSI,
"Returned sense data",
sense_buffer, sizeof(sense_buffer));
PRINT_BUFF_FLAG(TRACE_SCSI, "Returned sense "
"data", sense_buffer,
sizeof(sense_buffer));
if (scst_analyze_sense(sense_buffer,
sizeof(sense_buffer),
SCST_SENSE_KEY_VALID,

View File

@@ -1395,10 +1395,10 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result,
scst_alloc_set_sense(cmd, 1, rq_sense, rq_sense_len);
}
TRACE(TRACE_SCSI, "cmd %p, result=%x, cmd->status=%x, resid=%d, "
"cmd->msg_status=%x, cmd->host_status=%x, "
"cmd->driver_status=%x (cmd %p)", cmd, result, cmd->status, resid,
cmd->msg_status, cmd->host_status, cmd->driver_status, cmd);
TRACE(TRACE_SCSI, "cmd %p, result %x, cmd->status %x, resid %d, "
"cmd->msg_status %x, cmd->host_status %x, "
"cmd->driver_status %x", cmd, result, cmd->status, resid,
cmd->msg_status, cmd->host_status, cmd->driver_status);
cmd->completed = 1;
@@ -1506,6 +1506,11 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state,
scst_set_exec_time(cmd);
TRACE(TRACE_SCSI, "cmd %p, status %x, msg_status %x, host_status %x, "
"driver_status %x, resp_data_len %d", cmd, cmd->status,
cmd->msg_status, cmd->host_status, cmd->driver_status,
cmd->resp_data_len);
if (next_state == SCST_CMD_STATE_DEFAULT)
next_state = SCST_CMD_STATE_PRE_DEV_DONE;