mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
[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>
This commit is contained in:
parent
a85591fd0b
commit
4cf1043593
@ -1453,19 +1453,20 @@ static void iscsi_check_transport_timeouts(unsigned long data)
|
|||||||
{
|
{
|
||||||
struct iscsi_conn *conn = (struct iscsi_conn *)data;
|
struct iscsi_conn *conn = (struct iscsi_conn *)data;
|
||||||
struct iscsi_session *session = conn->session;
|
struct iscsi_session *session = conn->session;
|
||||||
unsigned long timeout, next_timeout = 0, last_recv;
|
unsigned long recv_timeout, next_timeout = 0, last_recv;
|
||||||
|
|
||||||
spin_lock(&session->lock);
|
spin_lock(&session->lock);
|
||||||
if (session->state != ISCSI_STATE_LOGGED_IN)
|
if (session->state != ISCSI_STATE_LOGGED_IN)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
timeout = conn->recv_timeout;
|
recv_timeout = conn->recv_timeout;
|
||||||
if (!timeout)
|
if (!recv_timeout)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
timeout *= HZ;
|
recv_timeout *= HZ;
|
||||||
last_recv = conn->last_recv;
|
last_recv = conn->last_recv;
|
||||||
if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ),
|
if (conn->ping_mtask &&
|
||||||
|
time_before_eq(conn->last_ping + (conn->ping_timeout * HZ),
|
||||||
jiffies)) {
|
jiffies)) {
|
||||||
iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
|
iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
|
||||||
"expired, last rx %lu, last ping %lu, "
|
"expired, last rx %lu, last ping %lu, "
|
||||||
@ -1476,15 +1477,15 @@ static void iscsi_check_transport_timeouts(unsigned long data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (time_before_eq(last_recv + timeout, jiffies)) {
|
if (time_before_eq(last_recv + recv_timeout, jiffies)) {
|
||||||
if (time_before_eq(conn->last_ping, last_recv)) {
|
if (time_before_eq(conn->last_ping, last_recv)) {
|
||||||
/* send a ping to try to provoke some traffic */
|
/* send a ping to try to provoke some traffic */
|
||||||
debug_scsi("Sending nopout as ping on conn %p\n", conn);
|
debug_scsi("Sending nopout as ping on conn %p\n", conn);
|
||||||
iscsi_send_nopout(conn, NULL);
|
iscsi_send_nopout(conn, NULL);
|
||||||
}
|
}
|
||||||
next_timeout = last_recv + timeout + (conn->ping_timeout * HZ);
|
next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
|
||||||
} else
|
} else
|
||||||
next_timeout = last_recv + timeout;
|
next_timeout = last_recv + recv_timeout;
|
||||||
|
|
||||||
debug_scsi("Setting next tmo %lu\n", next_timeout);
|
debug_scsi("Setting next tmo %lu\n", next_timeout);
|
||||||
mod_timer(&conn->transport_timer, next_timeout);
|
mod_timer(&conn->transport_timer, next_timeout);
|
||||||
|
Loading…
Reference in New Issue
Block a user