diff options
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 518dbd91df85..2b1b834a098b 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -99,6 +99,27 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, | |||
99 | return total_consumed; | 99 | return total_consumed; |
100 | } | 100 | } |
101 | 101 | ||
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 | struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data; | ||
113 | |||
114 | if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) && | ||
115 | !atomic_read(&sk->sk_rmem_alloc)) { | ||
116 | ISCSI_SW_TCP_DBG(conn, "TCP_CLOSE|TCP_CLOSE_WAIT\n"); | ||
117 | iscsi_conn_failure(conn, ISCSI_ERR_TCP_CONN_CLOSE); | ||
118 | return -ECONNRESET; | ||
119 | } | ||
120 | return 0; | ||
121 | } | ||
122 | |||
102 | static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag) | 123 | static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag) |
103 | { | 124 | { |
104 | struct iscsi_conn *conn = sk->sk_user_data; | 125 | struct iscsi_conn *conn = sk->sk_user_data; |
@@ -117,6 +138,8 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag) | |||
117 | rd_desc.count = 1; | 138 | rd_desc.count = 1; |
118 | tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv); | 139 | tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv); |
119 | 140 | ||
141 | iscsi_sw_sk_state_check(sk); | ||
142 | |||
120 | read_unlock(&sk->sk_callback_lock); | 143 | read_unlock(&sk->sk_callback_lock); |
121 | 144 | ||
122 | /* If we had to (atomically) map a highmem page, | 145 | /* If we had to (atomically) map a highmem page, |
@@ -137,13 +160,7 @@ static void iscsi_sw_tcp_state_change(struct sock *sk) | |||
137 | conn = (struct iscsi_conn*)sk->sk_user_data; | 160 | conn = (struct iscsi_conn*)sk->sk_user_data; |
138 | session = conn->session; | 161 | session = conn->session; |
139 | 162 | ||
140 | if ((sk->sk_state == TCP_CLOSE_WAIT || | 163 | iscsi_sw_sk_state_check(sk); |
141 | sk->sk_state == TCP_CLOSE) && | ||
142 | !atomic_read(&sk->sk_rmem_alloc)) { | ||
143 | ISCSI_SW_TCP_DBG(conn, "iscsi_tcp_state_change: " | ||
144 | "TCP_CLOSE|TCP_CLOSE_WAIT\n"); | ||
145 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
146 | } | ||
147 | 164 | ||
148 | tcp_conn = conn->dd_data; | 165 | tcp_conn = conn->dd_data; |
149 | tcp_sw_conn = tcp_conn->dd_data; | 166 | tcp_sw_conn = tcp_conn->dd_data; |