]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.fixes/iscsi_tcp-Evaluate-socket-state-in-data_ready
Imported linux-2.6.27.39 suse/xen patches.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.fixes / iscsi_tcp-Evaluate-socket-state-in-data_ready
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
5 References: bnc#472432
6
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.
12
13 Signed-off-by: Hannes Reinecke <hare@suse.de>
14 Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
15 ---
16 drivers/scsi/iscsi_tcp.c | 27 ++++++++++++++++++++++++---
17 1 files changed, 24 insertions(+), 3 deletions(-)
18
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:
24 return 0;
25 }
26
27 +/**
28 + * iscsi_sw_sk_state_check - check socket state
29 + * @sk: socket
30 + *
31 + * If the socket is in CLOSE or CLOSE_WAIT we should
32 + * not close the connection if there is still some
33 + * data pending.
34 + */
35 +static inline int iscsi_tcp_state_check(struct sock *sk)
36 +{
37 + if ((sk->sk_state == TCP_CLOSE_WAIT ||
38 + sk->sk_state == TCP_CLOSE) &&
39 + !atomic_read(&sk->sk_rmem_alloc))
40 + return -ECONNRESET;
41 +
42 + return 0;
43 +}
44 +
45 static void
46 iscsi_tcp_data_ready(struct sock *sk, int flag)
47 {
48 @@ -1033,6 +1051,11 @@ iscsi_tcp_data_ready(struct sock *sk, int flag)
49 rd_desc.count = 1;
50 tcp_read_sock(sk, &rd_desc, iscsi_tcp_recv);
51
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);
55 + }
56 +
57 read_unlock(&sk->sk_callback_lock);
58
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;
63
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);
70 }
71 --
72 1.6.0.2
73