diff options
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r-- | net/sunrpc/xprtsock.c | 12 |
1 files changed, 10 insertions, 2 deletions
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); |