提交 52f5664a 编写于 作者: A Ariel Nahum 提交者: James Bottomley

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: NAriel Nahum <arieln@mellanox.com>
Signed-off-by: NSagi Grimberg <sagig@mellanox.com>
Reviewed-by: NMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: NJames Bottomley <JBottomley@Odin.com>
上级 6ff33f39
...@@ -976,13 +976,13 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) ...@@ -976,13 +976,13 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
wake_up(&conn->ehwait); 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_nopout hdr;
struct iscsi_task *task; struct iscsi_task *task;
if (!rhdr && conn->ping_task) if (!rhdr && conn->ping_task)
return; return -EINVAL;
memset(&hdr, 0, sizeof(struct iscsi_nopout)); memset(&hdr, 0, sizeof(struct iscsi_nopout));
hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; 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) ...@@ -996,13 +996,16 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
hdr.ttt = RESERVED_ITT; hdr.ttt = RESERVED_ITT;
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); 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"); iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
else if (!rhdr) { return -EIO;
} else if (!rhdr) {
/* only track our nops */ /* only track our nops */
conn->ping_task = task; conn->ping_task = task;
conn->last_ping = jiffies; conn->last_ping = jiffies;
} }
return 0;
} }
static int iscsi_nop_out_rsp(struct iscsi_task *task, static int iscsi_nop_out_rsp(struct iscsi_task *task,
...@@ -2092,8 +2095,10 @@ static void iscsi_check_transport_timeouts(unsigned long data) ...@@ -2092,8 +2095,10 @@ static void iscsi_check_transport_timeouts(unsigned long data)
if (time_before_eq(last_recv + recv_timeout, jiffies)) { if (time_before_eq(last_recv + recv_timeout, jiffies)) {
/* send a ping to try to provoke some traffic */ /* send a ping to try to provoke some traffic */
ISCSI_DBG_CONN(conn, "Sending nopout as ping\n"); ISCSI_DBG_CONN(conn, "Sending nopout as ping\n");
iscsi_send_nopout(conn, NULL); if (iscsi_send_nopout(conn, NULL))
next_timeout = conn->last_ping + (conn->ping_timeout * HZ); next_timeout = jiffies + (1 * HZ);
else
next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
} else } else
next_timeout = last_recv + recv_timeout; next_timeout = last_recv + recv_timeout;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册