aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2009-03-11 14:10:21 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-03-11 14:10:21 -0400
commitfe315e76fc3a3f9f7e1581dc22fec7e7719f0896 (patch)
tree15ba17ab92691d55f3e3168df8fef2fb366339c0
parent01d37c428ae080563c0a3bb8bdfa88c65a6891d3 (diff)
SUNRPC: Avoid spurious wake-up during UDP connect processing
To clear out old state, the UDP connect workers unconditionally invoke xs_close() before proceeding with a new connect. Nowadays this causes a spurious wake-up of the task waiting for the connect to complete. This is a little racey, but usually harmless. The waiting task immediately retries the connect via a call_bind/call_connect sequence, which usually finds the transport already in the connected state because the connect worker has finished in the background. To avoid a spurious wake-up, factor the xs_close() logic that resets the underlying socket into a helper, and have the UDP connect workers call that helper instead of xs_close(). Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--net/sunrpc/xprtsock.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 29c71e645b27..1127eb934136 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -767,23 +767,13 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s
767 sk->sk_error_report = transport->old_error_report; 767 sk->sk_error_report = transport->old_error_report;
768} 768}
769 769
770/** 770static void xs_reset_transport(struct sock_xprt *transport)
771 * xs_close - close a socket
772 * @xprt: transport
773 *
774 * This is used when all requests are complete; ie, no DRC state remains
775 * on the server we want to save.
776 */
777static void xs_close(struct rpc_xprt *xprt)
778{ 771{
779 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
780 struct socket *sock = transport->sock; 772 struct socket *sock = transport->sock;
781 struct sock *sk = transport->inet; 773 struct sock *sk = transport->inet;
782 774
783 if (!sk) 775 if (sk == NULL)
784 goto clear_close_wait; 776 return;
785
786 dprintk("RPC: xs_close xprt %p\n", xprt);
787 777
788 write_lock_bh(&sk->sk_callback_lock); 778 write_lock_bh(&sk->sk_callback_lock);
789 transport->inet = NULL; 779 transport->inet = NULL;
@@ -797,7 +787,23 @@ static void xs_close(struct rpc_xprt *xprt)
797 sk->sk_no_check = 0; 787 sk->sk_no_check = 0;
798 788
799 sock_release(sock); 789 sock_release(sock);
800clear_close_wait: 790}
791
792/**
793 * xs_close - close a socket
794 * @xprt: transport
795 *
796 * This is used when all requests are complete; ie, no DRC state remains
797 * on the server we want to save.
798 */
799static void xs_close(struct rpc_xprt *xprt)
800{
801 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
802
803 dprintk("RPC: xs_close xprt %p\n", xprt);
804
805 xs_reset_transport(transport);
806
801 smp_mb__before_clear_bit(); 807 smp_mb__before_clear_bit();
802 clear_bit(XPRT_CLOSE_WAIT, &xprt->state); 808 clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
803 clear_bit(XPRT_CLOSING, &xprt->state); 809 clear_bit(XPRT_CLOSING, &xprt->state);
@@ -1537,9 +1543,10 @@ static void xs_udp_connect_worker4(struct work_struct *work)
1537 goto out; 1543 goto out;
1538 1544
1539 /* Start by resetting any existing state */ 1545 /* Start by resetting any existing state */
1540 xs_close(xprt); 1546 xs_reset_transport(transport);
1541 1547
1542 if ((err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) { 1548 err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
1549 if (err < 0) {
1543 dprintk("RPC: can't create UDP transport socket (%d).\n", -err); 1550 dprintk("RPC: can't create UDP transport socket (%d).\n", -err);
1544 goto out; 1551 goto out;
1545 } 1552 }
@@ -1578,9 +1585,10 @@ static void xs_udp_connect_worker6(struct work_struct *work)
1578 goto out; 1585 goto out;
1579 1586
1580 /* Start by resetting any existing state */ 1587 /* Start by resetting any existing state */
1581 xs_close(xprt); 1588 xs_reset_transport(transport);
1582 1589
1583 if ((err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) { 1590 err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock);
1591 if (err < 0) {
1584 dprintk("RPC: can't create UDP transport socket (%d).\n", -err); 1592 dprintk("RPC: can't create UDP transport socket (%d).\n", -err);
1585 goto out; 1593 goto out;
1586 } 1594 }