[SCSI] libiscsi regression in 2.6.25: fix nop timer handling

The following patch fixes a bug in the iscsi nop processing.
The target sends iscsi nops to ping the initiator and the
initiator has to send nops to reply and can send nops to
ping the target.

In 2.6.25 we moved the nop processing to the kernel to handle
problems when the userspace daemon is not up, but the target
is pinging us, and to handle when scsi commands timeout, but
the transport may be the cause (we can send a nop to check
the transport). When we added this code we added a bug where
if the transport timer wakes at the exact same time we are supposed to check
for a nop timeout we drop the session instead of checking the transport.

This patch checks if a iscsi ping is outstanding and if the ping has
timed out, to determine if we need to signal a connection problem.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Cc: Stable Tree <stable@kernel.org>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

authored by Mike Christie and committed by James Bottomley 4cf10435 a85591fd

+9 -8
+9 -8
drivers/scsi/libiscsi.c
··· 1453 { 1454 struct iscsi_conn *conn = (struct iscsi_conn *)data; 1455 struct iscsi_session *session = conn->session; 1456 - unsigned long timeout, next_timeout = 0, last_recv; 1457 1458 spin_lock(&session->lock); 1459 if (session->state != ISCSI_STATE_LOGGED_IN) 1460 goto done; 1461 1462 - timeout = conn->recv_timeout; 1463 - if (!timeout) 1464 goto done; 1465 1466 - timeout *= HZ; 1467 last_recv = conn->last_recv; 1468 - if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ), 1469 jiffies)) { 1470 iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " 1471 "expired, last rx %lu, last ping %lu, " ··· 1477 return; 1478 } 1479 1480 - if (time_before_eq(last_recv + timeout, jiffies)) { 1481 if (time_before_eq(conn->last_ping, last_recv)) { 1482 /* send a ping to try to provoke some traffic */ 1483 debug_scsi("Sending nopout as ping on conn %p\n", conn); 1484 iscsi_send_nopout(conn, NULL); 1485 } 1486 - next_timeout = last_recv + timeout + (conn->ping_timeout * HZ); 1487 } else 1488 - next_timeout = last_recv + timeout; 1489 1490 debug_scsi("Setting next tmo %lu\n", next_timeout); 1491 mod_timer(&conn->transport_timer, next_timeout);
··· 1453 { 1454 struct iscsi_conn *conn = (struct iscsi_conn *)data; 1455 struct iscsi_session *session = conn->session; 1456 + unsigned long recv_timeout, next_timeout = 0, last_recv; 1457 1458 spin_lock(&session->lock); 1459 if (session->state != ISCSI_STATE_LOGGED_IN) 1460 goto done; 1461 1462 + recv_timeout = conn->recv_timeout; 1463 + if (!recv_timeout) 1464 goto done; 1465 1466 + recv_timeout *= HZ; 1467 last_recv = conn->last_recv; 1468 + if (conn->ping_mtask && 1469 + time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), 1470 jiffies)) { 1471 iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " 1472 "expired, last rx %lu, last ping %lu, " ··· 1476 return; 1477 } 1478 1479 + if (time_before_eq(last_recv + recv_timeout, jiffies)) { 1480 if (time_before_eq(conn->last_ping, last_recv)) { 1481 /* send a ping to try to provoke some traffic */ 1482 debug_scsi("Sending nopout as ping on conn %p\n", conn); 1483 iscsi_send_nopout(conn, NULL); 1484 } 1485 + next_timeout = conn->last_ping + (conn->ping_timeout * HZ); 1486 } else 1487 + next_timeout = last_recv + recv_timeout; 1488 1489 debug_scsi("Setting next tmo %lu\n", next_timeout); 1490 mod_timer(&conn->transport_timer, next_timeout);