]>
Commit | Line | Data |
---|---|---|
82094b55 AF |
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 |