Skip to content

Commit 39a9bea

Browse files
author
J. Bruce Fields
committed
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: J. Bruce Fields <bfields@redhat.com> Acked-by: Trond Myklebust <trondmy@primarydata.com>
1 parent d50039e commit 39a9bea

File tree

5 files changed

+19
-4
lines changed

5 files changed

+19
-4
lines changed

include/linux/sunrpc/svc_xprt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct svc_xprt {
8484

8585
struct net *xpt_net;
8686
struct rpc_xprt *xpt_bc_xprt; /* NFSv4.1 backchannel */
87+
struct rpc_xprt_switch *xpt_bc_xps; /* NFSv4.1 backchannel */
8788
};
8889

8990
static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)

include/linux/sunrpc/xprt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ struct xprt_create {
297297
size_t addrlen;
298298
const char *servername;
299299
struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */
300+
struct rpc_xprt_switch *bc_xps;
300301
unsigned int flags;
301302
};
302303

net/sunrpc/clnt.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,20 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
452452
struct rpc_clnt *clnt = NULL;
453453
struct rpc_xprt_switch *xps;
454454

455-
xps = xprt_switch_alloc(xprt, GFP_KERNEL);
456-
if (xps == NULL) {
457-
xprt_put(xprt);
458-
return ERR_PTR(-ENOMEM);
455+
if (args->bc_xprt && args->bc_xprt->xpt_bc_xps) {
456+
WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP);
457+
xps = args->bc_xprt->xpt_bc_xps;
458+
xprt_switch_get(xps);
459+
} else {
460+
xps = xprt_switch_alloc(xprt, GFP_KERNEL);
461+
if (xps == NULL) {
462+
xprt_put(xprt);
463+
return ERR_PTR(-ENOMEM);
464+
}
465+
if (xprt->bc_xprt) {
466+
xprt_switch_get(xps);
467+
xprt->bc_xprt->xpt_bc_xps = xps;
468+
}
459469
}
460470
clnt = rpc_new_client(args, xps, xprt, NULL);
461471
if (IS_ERR(clnt))

net/sunrpc/svc_xprt.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ static void svc_xprt_free(struct kref *kref)
136136
/* See comment on corresponding get in xs_setup_bc_tcp(): */
137137
if (xprt->xpt_bc_xprt)
138138
xprt_put(xprt->xpt_bc_xprt);
139+
if (xprt->xpt_bc_xps)
140+
xprt_switch_put(xprt->xpt_bc_xps);
139141
xprt->xpt_ops->xpo_free(xprt);
140142
module_put(owner);
141143
}

net/sunrpc/xprtsock.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3057,6 +3057,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
30573057
return xprt;
30583058

30593059
args->bc_xprt->xpt_bc_xprt = NULL;
3060+
args->bc_xprt->xpt_bc_xps = NULL;
30603061
xprt_put(xprt);
30613062
ret = ERR_PTR(-EINVAL);
30623063
out_err:

0 commit comments

Comments
 (0)