diff options
-rw-r--r-- | include/linux/sunrpc/xprt.h | 1 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 33 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 12 |
3 files changed, 27 insertions, 19 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index dd860128ceda..6ef99b14ff09 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
@@ -254,6 +254,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to); | |||
254 | #define XPRT_LOCKED (0) | 254 | #define XPRT_LOCKED (0) |
255 | #define XPRT_CONNECTED (1) | 255 | #define XPRT_CONNECTED (1) |
256 | #define XPRT_CONNECTING (2) | 256 | #define XPRT_CONNECTING (2) |
257 | #define XPRT_CLOSE_WAIT (3) | ||
257 | 258 | ||
258 | static inline void xprt_set_connected(struct rpc_xprt *xprt) | 259 | static inline void xprt_set_connected(struct rpc_xprt *xprt) |
259 | { | 260 | { |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 069a6cbd49ea..8bc0d5acf0da 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -119,6 +119,17 @@ out_sleep: | |||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | static void xprt_clear_locked(struct rpc_xprt *xprt) | ||
123 | { | ||
124 | xprt->snd_task = NULL; | ||
125 | if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state) || xprt->shutdown) { | ||
126 | smp_mb__before_clear_bit(); | ||
127 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
128 | smp_mb__after_clear_bit(); | ||
129 | } else | ||
130 | schedule_work(&xprt->task_cleanup); | ||
131 | } | ||
132 | |||
122 | /* | 133 | /* |
123 | * xprt_reserve_xprt_cong - serialize write access to transports | 134 | * xprt_reserve_xprt_cong - serialize write access to transports |
124 | * @task: task that is requesting access to the transport | 135 | * @task: task that is requesting access to the transport |
@@ -145,9 +156,7 @@ int xprt_reserve_xprt_cong(struct rpc_task *task) | |||
145 | } | 156 | } |
146 | return 1; | 157 | return 1; |
147 | } | 158 | } |
148 | smp_mb__before_clear_bit(); | 159 | xprt_clear_locked(xprt); |
149 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
150 | smp_mb__after_clear_bit(); | ||
151 | out_sleep: | 160 | out_sleep: |
152 | dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt); | 161 | dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt); |
153 | task->tk_timeout = 0; | 162 | task->tk_timeout = 0; |
@@ -193,9 +202,7 @@ static void __xprt_lock_write_next(struct rpc_xprt *xprt) | |||
193 | return; | 202 | return; |
194 | 203 | ||
195 | out_unlock: | 204 | out_unlock: |
196 | smp_mb__before_clear_bit(); | 205 | xprt_clear_locked(xprt); |
197 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
198 | smp_mb__after_clear_bit(); | ||
199 | } | 206 | } |
200 | 207 | ||
201 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | 208 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) |
@@ -222,9 +229,7 @@ static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | |||
222 | return; | 229 | return; |
223 | } | 230 | } |
224 | out_unlock: | 231 | out_unlock: |
225 | smp_mb__before_clear_bit(); | 232 | xprt_clear_locked(xprt); |
226 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
227 | smp_mb__after_clear_bit(); | ||
228 | } | 233 | } |
229 | 234 | ||
230 | /** | 235 | /** |
@@ -237,10 +242,7 @@ out_unlock: | |||
237 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | 242 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) |
238 | { | 243 | { |
239 | if (xprt->snd_task == task) { | 244 | if (xprt->snd_task == task) { |
240 | xprt->snd_task = NULL; | 245 | xprt_clear_locked(xprt); |
241 | smp_mb__before_clear_bit(); | ||
242 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
243 | smp_mb__after_clear_bit(); | ||
244 | __xprt_lock_write_next(xprt); | 246 | __xprt_lock_write_next(xprt); |
245 | } | 247 | } |
246 | } | 248 | } |
@@ -256,10 +258,7 @@ void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | |||
256 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) | 258 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) |
257 | { | 259 | { |
258 | if (xprt->snd_task == task) { | 260 | if (xprt->snd_task == task) { |
259 | xprt->snd_task = NULL; | 261 | xprt_clear_locked(xprt); |
260 | smp_mb__before_clear_bit(); | ||
261 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
262 | smp_mb__after_clear_bit(); | ||
263 | __xprt_lock_write_next_cong(xprt); | 262 | __xprt_lock_write_next_cong(xprt); |
264 | } | 263 | } |
265 | } | 264 | } |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 3e8893001479..c458f8d1d6d1 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -425,7 +425,7 @@ static void xs_close(struct rpc_xprt *xprt) | |||
425 | struct sock *sk = xprt->inet; | 425 | struct sock *sk = xprt->inet; |
426 | 426 | ||
427 | if (!sk) | 427 | if (!sk) |
428 | return; | 428 | goto clear_close_wait; |
429 | 429 | ||
430 | dprintk("RPC: xs_close xprt %p\n", xprt); | 430 | dprintk("RPC: xs_close xprt %p\n", xprt); |
431 | 431 | ||
@@ -442,6 +442,10 @@ static void xs_close(struct rpc_xprt *xprt) | |||
442 | sk->sk_no_check = 0; | 442 | sk->sk_no_check = 0; |
443 | 443 | ||
444 | sock_release(sock); | 444 | sock_release(sock); |
445 | clear_close_wait: | ||
446 | smp_mb__before_clear_bit(); | ||
447 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
448 | smp_mb__after_clear_bit(); | ||
445 | } | 449 | } |
446 | 450 | ||
447 | /** | 451 | /** |
@@ -801,9 +805,13 @@ static void xs_tcp_state_change(struct sock *sk) | |||
801 | case TCP_SYN_SENT: | 805 | case TCP_SYN_SENT: |
802 | case TCP_SYN_RECV: | 806 | case TCP_SYN_RECV: |
803 | break; | 807 | break; |
808 | case TCP_CLOSE_WAIT: | ||
809 | /* Try to schedule an autoclose RPC calls */ | ||
810 | set_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
811 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) | ||
812 | schedule_work(&xprt->task_cleanup); | ||
804 | default: | 813 | default: |
805 | xprt_disconnect(xprt); | 814 | xprt_disconnect(xprt); |
806 | break; | ||
807 | } | 815 | } |
808 | out: | 816 | out: |
809 | read_unlock(&sk->sk_callback_lock); | 817 | read_unlock(&sk->sk_callback_lock); |