aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <cel@netapp.com>2005-08-25 19:25:55 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-09-23 12:38:52 -0400
commit3167e12c0c424f3c323944701615343022d86418 (patch)
tree952961988fe19c19fc63f9cffb5edb4566f3527f
parent529b33c6db0120126b1381faa51406dc463acdc9 (diff)
[PATCH] RPC: make sure to get the same local port number when reconnecting
Implement a best practice: if the remote end drops our connection, try to reconnect using the same port number. This is important because the NFS server's Duplicate Reply Cache often hashes on the source port number. If the client reuses the port number when it reconnects, the server's DRC will be more effective. Based on suggestions by Mike Eisler, Olaf Kirch, and Alexey Kuznetsky. Test-plan: Destructive testing. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--net/sunrpc/xprtsock.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 62c2e7caa345..88ac71fcd335 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -362,6 +362,8 @@ static int xs_tcp_send_request(struct rpc_task *task)
362 * xs_close - close a socket 362 * xs_close - close a socket
363 * @xprt: transport 363 * @xprt: transport
364 * 364 *
365 * This is used when all requests are complete; ie, no DRC state remains
366 * on the server we want to save.
365 */ 367 */
366static void xs_close(struct rpc_xprt *xprt) 368static void xs_close(struct rpc_xprt *xprt)
367{ 369{
@@ -949,6 +951,30 @@ out:
949 xprt_clear_connecting(xprt); 951 xprt_clear_connecting(xprt);
950} 952}
951 953
954/*
955 * We need to preserve the port number so the reply cache on the server can
956 * find our cached RPC replies when we get around to reconnecting.
957 */
958static void xs_tcp_reuse_connection(struct rpc_xprt *xprt)
959{
960 int result;
961 struct socket *sock = xprt->sock;
962 struct sockaddr any;
963
964 dprintk("RPC: disconnecting xprt %p to reuse port\n", xprt);
965
966 /*
967 * Disconnect the transport socket by doing a connect operation
968 * with AF_UNSPEC. This should return immediately...
969 */
970 memset(&any, 0, sizeof(any));
971 any.sa_family = AF_UNSPEC;
972 result = sock->ops->connect(sock, &any, sizeof(any), 0);
973 if (result)
974 dprintk("RPC: AF_UNSPEC connect return code %d\n",
975 result);
976}
977
952/** 978/**
953 * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint 979 * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint
954 * @args: RPC transport to connect 980 * @args: RPC transport to connect
@@ -966,18 +992,20 @@ static void xs_tcp_connect_worker(void *args)
966 992
967 dprintk("RPC: xs_tcp_connect_worker for xprt %p\n", xprt); 993 dprintk("RPC: xs_tcp_connect_worker for xprt %p\n", xprt);
968 994
969 /* Start by resetting any existing socket state */ 995 if (!xprt->sock) {
970 xs_close(xprt); 996 /* start from scratch */
971 997 if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
972 if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { 998 dprintk("RPC: can't create TCP transport socket (%d).\n", -err);
973 dprintk("RPC: can't create TCP transport socket (%d).\n", -err); 999 goto out;
974 goto out; 1000 }
975 }
976 1001
977 if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) { 1002 if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
978 sock_release(sock); 1003 sock_release(sock);
979 goto out; 1004 goto out;
980 } 1005 }
1006 } else
1007 /* "close" the socket, preserving the local port */
1008 xs_tcp_reuse_connection(xprt);
981 1009
982 if (!xprt->inet) { 1010 if (!xprt->inet) {
983 struct sock *sk = sock->sk; 1011 struct sock *sk = sock->sk;
@@ -991,7 +1019,12 @@ static void xs_tcp_connect_worker(void *args)
991 sk->sk_data_ready = xs_tcp_data_ready; 1019 sk->sk_data_ready = xs_tcp_data_ready;
992 sk->sk_state_change = xs_tcp_state_change; 1020 sk->sk_state_change = xs_tcp_state_change;
993 sk->sk_write_space = xs_tcp_write_space; 1021 sk->sk_write_space = xs_tcp_write_space;
994 tcp_sk(sk)->nonagle = 1; 1022
1023 /* socket options */
1024 sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
1025 sock_reset_flag(sk, SOCK_LINGER);
1026 tcp_sk(sk)->linger2 = 0;
1027 tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
995 1028
996 xprt_clear_connected(xprt); 1029 xprt_clear_connected(xprt);
997 1030
@@ -1012,6 +1045,14 @@ static void xs_tcp_connect_worker(void *args)
1012 case -EINPROGRESS: 1045 case -EINPROGRESS:
1013 case -EALREADY: 1046 case -EALREADY:
1014 goto out_clear; 1047 goto out_clear;
1048 case -ECONNREFUSED:
1049 case -ECONNRESET:
1050 /* retry with existing socket, after a delay */
1051 break;
1052 default:
1053 /* get rid of existing socket, and retry */
1054 xs_close(xprt);
1055 break;
1015 } 1056 }
1016 } 1057 }
1017out: 1058out: