diff options
author | J. Bruce Fields <bfields@redhat.com> | 2010-12-08 12:45:44 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-01-11 15:04:10 -0500 |
commit | 99de8ea962bbc11a51ad4c52e3dc93bee5f6ba70 (patch) | |
tree | 1cda6aaeabe8fc4e3502104005c06a3888bb0bf4 /net/sunrpc | |
parent | d75faea330dbd1873c9094e9926ae306590c0998 (diff) |
rpc: keep backchannel xprt as long as server connection
Multiple backchannels can share the same tcp connection; from rfc 5661 section
2.10.3.1:
A connection's association with a session is not exclusive. A
connection associated with the channel(s) of one session may be
simultaneously associated with the channel(s) of other sessions
including sessions associated with other client IDs.
However, multiple backchannels share a connection, they must all share
the same xid stream (hence the same rpc_xprt); the only way we have to
match replies with calls at the rpc layer is using the xid.
So, keep the rpc_xprt around as long as the connection lasts, in case
we're asked to use the connection as a backchannel again.
Requests to create new backchannel clients over a given server
connection should results in creating new clients that reuse the
existing rpc_xprt.
But to start, just reject attempts to associate multiple rpc_xprt's with
the same underlying bc_xprt.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 4 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 34 |
3 files changed, 29 insertions, 11 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 173f3b975d49..ab86b7927f84 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/sunrpc/stats.h> | 13 | #include <linux/sunrpc/stats.h> |
14 | #include <linux/sunrpc/svc_xprt.h> | 14 | #include <linux/sunrpc/svc_xprt.h> |
15 | #include <linux/sunrpc/svcsock.h> | 15 | #include <linux/sunrpc/svcsock.h> |
16 | #include <linux/sunrpc/xprt.h> | ||
16 | 17 | ||
17 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 18 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
18 | 19 | ||
@@ -128,6 +129,9 @@ static void svc_xprt_free(struct kref *kref) | |||
128 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) | 129 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) |
129 | svcauth_unix_info_release(xprt); | 130 | svcauth_unix_info_release(xprt); |
130 | put_net(xprt->xpt_net); | 131 | put_net(xprt->xpt_net); |
132 | /* See comment on corresponding get in xs_setup_bc_tcp(): */ | ||
133 | if (xprt->xpt_bc_xprt) | ||
134 | xprt_put(xprt->xpt_bc_xprt); | ||
131 | xprt->xpt_ops->xpo_free(xprt); | 135 | xprt->xpt_ops->xpo_free(xprt); |
132 | module_put(owner); | 136 | module_put(owner); |
133 | } | 137 | } |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 4c8f18aff7c3..749ad15ae305 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -965,6 +965,7 @@ struct rpc_xprt *xprt_alloc(struct net *net, int size, int max_req) | |||
965 | xprt = kzalloc(size, GFP_KERNEL); | 965 | xprt = kzalloc(size, GFP_KERNEL); |
966 | if (xprt == NULL) | 966 | if (xprt == NULL) |
967 | goto out; | 967 | goto out; |
968 | kref_init(&xprt->kref); | ||
968 | 969 | ||
969 | xprt->max_reqs = max_req; | 970 | xprt->max_reqs = max_req; |
970 | xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL); | 971 | xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL); |
@@ -1102,7 +1103,6 @@ found: | |||
1102 | return xprt; | 1103 | return xprt; |
1103 | } | 1104 | } |
1104 | 1105 | ||
1105 | kref_init(&xprt->kref); | ||
1106 | spin_lock_init(&xprt->transport_lock); | 1106 | spin_lock_init(&xprt->transport_lock); |
1107 | spin_lock_init(&xprt->reserve_lock); | 1107 | spin_lock_init(&xprt->reserve_lock); |
1108 | 1108 | ||
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 18dc42eb5597..0ef4dd4414ec 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -2375,16 +2375,6 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
2375 | xprt->reestablish_timeout = 0; | 2375 | xprt->reestablish_timeout = 0; |
2376 | xprt->idle_timeout = 0; | 2376 | xprt->idle_timeout = 0; |
2377 | 2377 | ||
2378 | /* | ||
2379 | * The backchannel uses the same socket connection as the | ||
2380 | * forechannel | ||
2381 | */ | ||
2382 | args->bc_xprt->xpt_bc_xprt = xprt; | ||
2383 | xprt->bc_xprt = args->bc_xprt; | ||
2384 | bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt); | ||
2385 | transport->sock = bc_sock->sk_sock; | ||
2386 | transport->inet = bc_sock->sk_sk; | ||
2387 | |||
2388 | xprt->ops = &bc_tcp_ops; | 2378 | xprt->ops = &bc_tcp_ops; |
2389 | 2379 | ||
2390 | switch (addr->sa_family) { | 2380 | switch (addr->sa_family) { |
@@ -2407,6 +2397,29 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
2407 | xprt->address_strings[RPC_DISPLAY_PROTO]); | 2397 | xprt->address_strings[RPC_DISPLAY_PROTO]); |
2408 | 2398 | ||
2409 | /* | 2399 | /* |
2400 | * The backchannel uses the same socket connection as the | ||
2401 | * forechannel | ||
2402 | */ | ||
2403 | if (args->bc_xprt->xpt_bc_xprt) { | ||
2404 | /* XXX: actually, want to catch this case... */ | ||
2405 | ret = ERR_PTR(-EINVAL); | ||
2406 | goto out_err; | ||
2407 | } | ||
2408 | /* | ||
2409 | * Once we've associated a backchannel xprt with a connection, | ||
2410 | * we want to keep it around as long as long as the connection | ||
2411 | * lasts, in case we need to start using it for a backchannel | ||
2412 | * again; this reference won't be dropped until bc_xprt is | ||
2413 | * destroyed. | ||
2414 | */ | ||
2415 | xprt_get(xprt); | ||
2416 | args->bc_xprt->xpt_bc_xprt = xprt; | ||
2417 | xprt->bc_xprt = args->bc_xprt; | ||
2418 | bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt); | ||
2419 | transport->sock = bc_sock->sk_sock; | ||
2420 | transport->inet = bc_sock->sk_sk; | ||
2421 | |||
2422 | /* | ||
2410 | * Since we don't want connections for the backchannel, we set | 2423 | * Since we don't want connections for the backchannel, we set |
2411 | * the xprt status to connected | 2424 | * the xprt status to connected |
2412 | */ | 2425 | */ |
@@ -2415,6 +2428,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
2415 | 2428 | ||
2416 | if (try_module_get(THIS_MODULE)) | 2429 | if (try_module_get(THIS_MODULE)) |
2417 | return xprt; | 2430 | return xprt; |
2431 | xprt_put(xprt); | ||
2418 | ret = ERR_PTR(-EINVAL); | 2432 | ret = ERR_PTR(-EINVAL); |
2419 | out_err: | 2433 | out_err: |
2420 | xprt_free(xprt); | 2434 | xprt_free(xprt); |