Skip to content

Commit 523eeac

Browse files
hreineckeJames Bottomley
authored andcommitted
[SCSI] iscsi_tcp: Evaluate socket state in data_ready()
The network core will call the state_change() callback prior to the data_ready() callback, which might cause us to lose a connection state change. So we have to evaluate the socket state at the end of the data_ready() callback, too. Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
1 parent ac280b6 commit 523eeac

File tree

1 file changed

+25
-3
lines changed

1 file changed

+25
-3
lines changed

drivers/scsi/iscsi_tcp.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,24 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
9999
return total_consumed;
100100
}
101101

102+
/**
103+
* iscsi_sw_sk_state_check - check socket state
104+
* @sk: socket
105+
*
106+
* If the socket is in CLOSE or CLOSE_WAIT we should
107+
* not close the connection if there is still some
108+
* data pending.
109+
*/
110+
static inline int iscsi_sw_sk_state_check(struct sock *sk)
111+
{
112+
if ((sk->sk_state == TCP_CLOSE_WAIT ||
113+
sk->sk_state == TCP_CLOSE) &&
114+
!atomic_read(&sk->sk_rmem_alloc))
115+
return -ECONNRESET;
116+
117+
return 0;
118+
}
119+
102120
static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
103121
{
104122
struct iscsi_conn *conn = sk->sk_user_data;
@@ -117,6 +135,12 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
117135
rd_desc.count = 1;
118136
tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv);
119137

138+
if (iscsi_sw_sk_state_check(sk) < 0) {
139+
ISCSI_SW_TCP_DBG(conn, "iscsi_tcp_data_ready: "
140+
"TCP_CLOSE|TCP_CLOSE_WAIT\n");
141+
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
142+
}
143+
120144
read_unlock(&sk->sk_callback_lock);
121145

122146
/* If we had to (atomically) map a highmem page,
@@ -137,9 +161,7 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
137161
conn = (struct iscsi_conn*)sk->sk_user_data;
138162
session = conn->session;
139163

140-
if ((sk->sk_state == TCP_CLOSE_WAIT ||
141-
sk->sk_state == TCP_CLOSE) &&
142-
!atomic_read(&sk->sk_rmem_alloc)) {
164+
if (iscsi_sw_sk_state_check(sk) < 0) {
143165
ISCSI_SW_TCP_DBG(conn, "iscsi_tcp_state_change: "
144166
"TCP_CLOSE|TCP_CLOSE_WAIT\n");
145167
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);

0 commit comments

Comments
 (0)