summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libiscsi.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 212fe2027a8c..c648bd328a21 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -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;
@@ -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;
@@ -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;