Skip to content

Commit

Permalink
[SCSI] libiscsi: fix iscsi transport checks to account for slower links
Browse files Browse the repository at this point in the history
If we have not got any pdus for recv_timeout seconds, then we will
send a iscsi ping/nop to make sure the target is still around. The
problem is if this is a slow link, and the ping got queued after
the data for a data_out (read), then the transport code could think
the ping has failed when it is just slowly making its way through
the network. This patch has us check if we are making progress while
the nop is outstanding. If we are still reading in data, then we
do not fail the session at that time.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
  • Loading branch information
Mike Christie authored and James Bottomley committed May 23, 2009
1 parent d1acfae commit 4c48a82
Showing 1 changed file with 29 additions and 9 deletions.
38 changes: 29 additions & 9 deletions drivers/scsi/libiscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1677,6 +1677,22 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
iscsi_conn_queue_work(conn);
}

/*
* We want to make sure a ping is in flight. It has timed out.
* And we are not busy processing a pdu that is making
* progress but got started before the ping and is taking a while
* to complete so the ping is just stuck behind it in a queue.
*/
static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
{
if (conn->ping_task &&
time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
(conn->ping_timeout * HZ), jiffies))
return 1;
else
return 0;
}

static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
{
struct iscsi_cls_session *cls_session;
Expand Down Expand Up @@ -1712,16 +1728,20 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
* if the ping timedout then we are in the middle of cleaning up
* and can let the iscsi eh handle it
*/
if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
(conn->ping_timeout * HZ), jiffies))
if (iscsi_has_ping_timed_out(conn)) {
rc = BLK_EH_RESET_TIMER;
goto done;
}
/*
* if we are about to check the transport then give the command
* more time
*/
if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
jiffies))
jiffies)) {
rc = BLK_EH_RESET_TIMER;
goto done;
}

/* if in the middle of checking the transport then give us more time */
if (conn->ping_task)
rc = BLK_EH_RESET_TIMER;
Expand All @@ -1748,13 +1768,13 @@ static void iscsi_check_transport_timeouts(unsigned long data)

recv_timeout *= HZ;
last_recv = conn->last_recv;
if (conn->ping_task &&
time_before_eq(conn->last_ping + (conn->ping_timeout * HZ),
jiffies)) {

if (iscsi_has_ping_timed_out(conn)) {
iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
"expired, last rx %lu, last ping %lu, "
"now %lu\n", conn->ping_timeout, last_recv,
conn->last_ping, jiffies);
"expired, recv timeout %d, last rx %lu, "
"last ping %lu, now %lu\n",
conn->ping_timeout, conn->recv_timeout,
last_recv, conn->last_ping, jiffies);
spin_unlock(&session->lock);
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
return;
Expand Down

0 comments on commit 4c48a82

Please sign in to comment.