aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-05-07 21:43:52 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-05-08 11:04:54 -0400
commit4cf1043593db6a337f10e006c23c69e5fc93e722 (patch)
treeea7489898d58d9e8185539a1d484be21d57632ac /drivers/scsi
parenta85591fd0baf4ed3f03ee1aaac6a985e400cf089 (diff)
[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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libiscsi.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 010c1b9b178c..98164f3c3517 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1453,19 +1453,20 @@ static void iscsi_check_transport_timeouts(unsigned long data)
1453{ 1453{
1454 struct iscsi_conn *conn = (struct iscsi_conn *)data; 1454 struct iscsi_conn *conn = (struct iscsi_conn *)data;
1455 struct iscsi_session *session = conn->session; 1455 struct iscsi_session *session = conn->session;
1456 unsigned long timeout, next_timeout = 0, last_recv; 1456 unsigned long recv_timeout, next_timeout = 0, last_recv;
1457 1457
1458 spin_lock(&session->lock); 1458 spin_lock(&session->lock);
1459 if (session->state != ISCSI_STATE_LOGGED_IN) 1459 if (session->state != ISCSI_STATE_LOGGED_IN)
1460 goto done; 1460 goto done;
1461 1461
1462 timeout = conn->recv_timeout; 1462 recv_timeout = conn->recv_timeout;
1463 if (!timeout) 1463 if (!recv_timeout)
1464 goto done; 1464 goto done;
1465 1465
1466 timeout *= HZ; 1466 recv_timeout *= HZ;
1467 last_recv = conn->last_recv; 1467 last_recv = conn->last_recv;
1468 if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ), 1468 if (conn->ping_mtask &&
1469 time_before_eq(conn->last_ping + (conn->ping_timeout * HZ),
1469 jiffies)) { 1470 jiffies)) {
1470 iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " 1471 iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
1471 "expired, last rx %lu, last ping %lu, " 1472 "expired, last rx %lu, last ping %lu, "
@@ -1476,15 +1477,15 @@ static void iscsi_check_transport_timeouts(unsigned long data)
1476 return; 1477 return;
1477 } 1478 }
1478 1479
1479 if (time_before_eq(last_recv + timeout, jiffies)) { 1480 if (time_before_eq(last_recv + recv_timeout, jiffies)) {
1480 if (time_before_eq(conn->last_ping, last_recv)) { 1481 if (time_before_eq(conn->last_ping, last_recv)) {
1481 /* send a ping to try to provoke some traffic */ 1482 /* send a ping to try to provoke some traffic */
1482 debug_scsi("Sending nopout as ping on conn %p\n", conn); 1483 debug_scsi("Sending nopout as ping on conn %p\n", conn);
1483 iscsi_send_nopout(conn, NULL); 1484 iscsi_send_nopout(conn, NULL);
1484 } 1485 }
1485 next_timeout = last_recv + timeout + (conn->ping_timeout * HZ); 1486 next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
1486 } else 1487 } else
1487 next_timeout = last_recv + timeout; 1488 next_timeout = last_recv + recv_timeout;
1488 1489
1489 debug_scsi("Setting next tmo %lu\n", next_timeout); 1490 debug_scsi("Setting next tmo %lu\n", next_timeout);
1490 mod_timer(&conn->transport_timer, next_timeout); 1491 mod_timer(&conn->transport_timer, next_timeout);