Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39a9beab authored by J. Bruce Fields's avatar J. Bruce Fields
Browse files

rpc: share one xps between all backchannels



The spec allows backchannels for multiple clients to share the same tcp
connection.  When that happens, we need to use the same xprt for all of
them.  Similarly, we need the same xps.

This fixes list corruption introduced by the multipath code.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
Acked-by: default avatarTrond Myklebust <trondmy@primarydata.com>
parent d50039ea
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ struct svc_xprt {

	struct net		*xpt_net;
	struct rpc_xprt		*xpt_bc_xprt;	/* NFSv4.1 backchannel */
	struct rpc_xprt_switch	*xpt_bc_xps;	/* NFSv4.1 backchannel */
};

static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
+1 −0
Original line number Diff line number Diff line
@@ -297,6 +297,7 @@ struct xprt_create {
	size_t			addrlen;
	const char		*servername;
	struct svc_xprt		*bc_xprt;	/* NFSv4.1 backchannel */
	struct rpc_xprt_switch	*bc_xps;
	unsigned int		flags;
};

+14 −4
Original line number Diff line number Diff line
@@ -452,11 +452,21 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
	struct rpc_clnt *clnt = NULL;
	struct rpc_xprt_switch *xps;

	if (args->bc_xprt && args->bc_xprt->xpt_bc_xps) {
		WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP);
		xps = args->bc_xprt->xpt_bc_xps;
		xprt_switch_get(xps);
	} else {
		xps = xprt_switch_alloc(xprt, GFP_KERNEL);
		if (xps == NULL) {
			xprt_put(xprt);
			return ERR_PTR(-ENOMEM);
		}
		if (xprt->bc_xprt) {
			xprt_switch_get(xps);
			xprt->bc_xprt->xpt_bc_xps = xps;
		}
	}
	clnt = rpc_new_client(args, xps, xprt, NULL);
	if (IS_ERR(clnt))
		return clnt;
+2 −0
Original line number Diff line number Diff line
@@ -136,6 +136,8 @@ static void svc_xprt_free(struct kref *kref)
	/* See comment on corresponding get in xs_setup_bc_tcp(): */
	if (xprt->xpt_bc_xprt)
		xprt_put(xprt->xpt_bc_xprt);
	if (xprt->xpt_bc_xps)
		xprt_switch_put(xprt->xpt_bc_xps);
	xprt->xpt_ops->xpo_free(xprt);
	module_put(owner);
}
+1 −0
Original line number Diff line number Diff line
@@ -3057,6 +3057,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
		return xprt;

	args->bc_xprt->xpt_bc_xprt = NULL;
	args->bc_xprt->xpt_bc_xps = NULL;
	xprt_put(xprt);
	ret = ERR_PTR(-EINVAL);
out_err: