Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Ariel Nahum and committed by
James Bottomley
52f5664a 6ff33f39

+11 -6
+11 -6
drivers/scsi/libiscsi.c
··· 976 976 wake_up(&conn->ehwait); 977 977 } 978 978 979 - static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) 979 + static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) 980 980 { 981 981 struct iscsi_nopout hdr; 982 982 struct iscsi_task *task; 983 983 984 984 if (!rhdr && conn->ping_task) 985 - return; 985 + return -EINVAL; 986 986 987 987 memset(&hdr, 0, sizeof(struct iscsi_nopout)); 988 988 hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; ··· 996 996 hdr.ttt = RESERVED_ITT; 997 997 998 998 task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); 999 - if (!task) 999 + if (!task) { 1000 1000 iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); 1001 - else if (!rhdr) { 1001 + return -EIO; 1002 + } else if (!rhdr) { 1002 1003 /* only track our nops */ 1003 1004 conn->ping_task = task; 1004 1005 conn->last_ping = jiffies; 1005 1006 } 1007 + 1008 + return 0; 1006 1009 } 1007 1010 1008 1011 static int iscsi_nop_out_rsp(struct iscsi_task *task, ··· 2095 2092 if (time_before_eq(last_recv + recv_timeout, jiffies)) { 2096 2093 /* send a ping to try to provoke some traffic */ 2097 2094 ISCSI_DBG_CONN(conn, "Sending nopout as ping\n"); 2098 - iscsi_send_nopout(conn, NULL); 2099 - next_timeout = conn->last_ping + (conn->ping_timeout * HZ); 2095 + if (iscsi_send_nopout(conn, NULL)) 2096 + next_timeout = jiffies + (1 * HZ); 2097 + else 2098 + next_timeout = conn->last_ping + (conn->ping_timeout * HZ); 2100 2099 } else 2101 2100 next_timeout = last_recv + recv_timeout; 2102 2101