Commit e6237b6f authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4.1: Don't rebind to the same source port when reconnecting to the server



NFSv2, v3 and NFSv4 servers often have duplicate replay caches that look
at the source port when deciding whether or not an RPC call is a replay
of a previous call. This requires clients to perform strange TCP gymnastics
in order to ensure that when they reconnect to the server, they bind
to the same source port.

NFSv4.1 and NFSv4.2 have sessions that provide proper replay semantics,
that do not look at the source port of the connection. This patch therefore
ensures they can ignore the rebind requirement.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 52f98f1a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -464,7 +464,8 @@ nlm_bind_host(struct nlm_host *host)
			.version	= host->h_version,
			.authflavor	= RPC_AUTH_UNIX,
			.flags		= (RPC_CLNT_CREATE_NOPING |
					   RPC_CLNT_CREATE_AUTOBIND),
					   RPC_CLNT_CREATE_AUTOBIND |
					   RPC_CLNT_CREATE_REUSEPORT),
			.cred		= host->h_cred,
		};

+3 −0
Original line number Diff line number Diff line
@@ -523,6 +523,8 @@ int nfs_create_rpc_client(struct nfs_client *clp,
		args.flags |= RPC_CLNT_CREATE_INFINITE_SLOTS;
	if (test_bit(NFS_CS_NOPING, &clp->cl_flags))
		args.flags |= RPC_CLNT_CREATE_NOPING;
	if (test_bit(NFS_CS_REUSEPORT, &clp->cl_flags))
		args.flags |= RPC_CLNT_CREATE_REUSEPORT;

	if (!IS_ERR(clp->cl_rpcclient))
		return 0;
@@ -670,6 +672,7 @@ static int nfs_init_server(struct nfs_server *server,
		.timeparms = &timeparms,
		.cred = server->cred,
		.nconnect = data->nfs_server.nconnect,
		.init_flags = (1UL << NFS_CS_REUSEPORT),
	};
	struct nfs_client *clp;
	int error;
+4 −1
Original line number Diff line number Diff line
@@ -879,8 +879,11 @@ static int nfs4_set_client(struct nfs_server *server,
	};
	struct nfs_client *clp;

	if (minorversion > 0 && proto == XPRT_TRANSPORT_TCP)
	if (minorversion == 0)
		__set_bit(NFS_CS_REUSEPORT, &cl_init.init_flags);
	else if (proto == XPRT_TRANSPORT_TCP)
		cl_init.nconnect = nconnect;

	if (server->flags & NFS_MOUNT_NORESVPORT)
		__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
	if (server->options & NFS_OPTION_MIGRATION)
+1 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ struct nfs_client {
#define NFS_CS_TSM_POSSIBLE	5		/* - Maybe state migration */
#define NFS_CS_NOPING		6		/* - don't ping on connect */
#define NFS_CS_DS		7		/* - Server is a DS */
#define NFS_CS_REUSEPORT	8		/* - reuse src port on reconnect */
	struct sockaddr_storage	cl_addr;	/* server identifier */
	size_t			cl_addrlen;
	char *			cl_hostname;	/* hostname of server */
+1 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ struct rpc_add_xprt_test {
#define RPC_CLNT_CREATE_NO_IDLE_TIMEOUT	(1UL << 8)
#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT	(1UL << 9)
#define RPC_CLNT_CREATE_SOFTERR		(1UL << 10)
#define RPC_CLNT_CREATE_REUSEPORT	(1UL << 11)

struct rpc_clnt *rpc_create(struct rpc_create_args *args);
struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
Loading