mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
libiscsi: Fix iscsi_check_transport_timeouts possible infinite loop
Connection last_ping is not being updated when iscsi_send_nopout fails. Not updating the last_ping will cause firing a timer to a past time (last_ping + ping_tmo < current_time) which triggers an infinite loop of iscsi_check_transport_timeouts() and hogs the cpu. Fix this issue by checking the return value of iscsi_send_nopout. If it fails set the next_timeout to one second later. Signed-off-by: Ariel Nahum <arieln@mellanox.com> Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Odin.com>
This commit is contained in:
parent
6ff33f3902
commit
52f5664a87
@ -976,13 +976,13 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
|
||||
wake_up(&conn->ehwait);
|
||||
}
|
||||
|
||||
static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
|
||||
static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
|
||||
{
|
||||
struct iscsi_nopout hdr;
|
||||
struct iscsi_task *task;
|
||||
|
||||
if (!rhdr && conn->ping_task)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
memset(&hdr, 0, sizeof(struct iscsi_nopout));
|
||||
hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
|
||||
@ -996,13 +996,16 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
|
||||
hdr.ttt = RESERVED_ITT;
|
||||
|
||||
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
|
||||
if (!task)
|
||||
if (!task) {
|
||||
iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
|
||||
else if (!rhdr) {
|
||||
return -EIO;
|
||||
} else if (!rhdr) {
|
||||
/* only track our nops */
|
||||
conn->ping_task = task;
|
||||
conn->last_ping = jiffies;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iscsi_nop_out_rsp(struct iscsi_task *task,
|
||||
@ -2092,8 +2095,10 @@ static void iscsi_check_transport_timeouts(unsigned long data)
|
||||
if (time_before_eq(last_recv + recv_timeout, jiffies)) {
|
||||
/* send a ping to try to provoke some traffic */
|
||||
ISCSI_DBG_CONN(conn, "Sending nopout as ping\n");
|
||||
iscsi_send_nopout(conn, NULL);
|
||||
next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
|
||||
if (iscsi_send_nopout(conn, NULL))
|
||||
next_timeout = jiffies + (1 * HZ);
|
||||
else
|
||||
next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
|
||||
} else
|
||||
next_timeout = last_recv + recv_timeout;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user