1 From: Hannes Reinecke <hare@suse.de>
2 Date: Thu, 13 Aug 2009 10:35:43 +0200
3 Subject: iscsi_tcp: Evaluate socket state in data_ready()
4 X-Git: 523eeac6703a995d58918aaf321f128f75c13108
7 The network core will call the state_change() callback
8 prior to the data_ready() callback, which might cause
9 us to lose a connection state change.
10 So we have to evaluate the socket state at the end
11 of the data_ready() callback, too.
13 Signed-off-by: Hannes Reinecke <hare@suse.de>
14 Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
16 drivers/scsi/iscsi_tcp.c | 27 ++++++++++++++++++++++++---
17 1 files changed, 24 insertions(+), 3 deletions(-)
19 diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
20 index cfcb8ec..b870bfc 100644
21 --- a/drivers/scsi/iscsi_tcp.c
22 +++ b/drivers/scsi/iscsi_tcp.c
23 @@ -1014,6 +1014,24 @@ error:
28 + * iscsi_sw_sk_state_check - check socket state
31 + * If the socket is in CLOSE or CLOSE_WAIT we should
32 + * not close the connection if there is still some
35 +static inline int iscsi_tcp_state_check(struct sock *sk)
37 + if ((sk->sk_state == TCP_CLOSE_WAIT ||
38 + sk->sk_state == TCP_CLOSE) &&
39 + !atomic_read(&sk->sk_rmem_alloc))
46 iscsi_tcp_data_ready(struct sock *sk, int flag)
48 @@ -1033,6 +1051,11 @@ iscsi_tcp_data_ready(struct sock *sk, int flag)
50 tcp_read_sock(sk, &rd_desc, iscsi_tcp_recv);
52 + if (iscsi_tcp_state_check(sk) < 0) {
53 + debug_tcp("iscsi_tcp_data_ready: TCP_CLOSE|TCP_CLOSE_WAIT\n");
54 + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
57 read_unlock(&sk->sk_callback_lock);
59 /* If we had to (atomically) map a highmem page,
60 @@ -1053,9 +1076,7 @@ iscsi_tcp_state_change(struct sock *sk)
61 conn = (struct iscsi_conn*)sk->sk_user_data;
62 session = conn->session;
64 - if ((sk->sk_state == TCP_CLOSE_WAIT ||
65 - sk->sk_state == TCP_CLOSE) &&
66 - !atomic_read(&sk->sk_rmem_alloc)) {
67 + if (iscsi_tcp_state_check(sk) < 0) {
68 debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n");
69 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);