]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/sunrpc/xprtsock.c
rpc: keep backchannel xprt as long as server connection
[mv-sheeva.git] / net / sunrpc / xprtsock.c
index 18dc42eb5597a4fd92d6da906fc7a598f65030f0..0ef4dd4414ec9886f3bcb1bb05b809e50f2dae90 100644 (file)
@@ -2375,16 +2375,6 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
        xprt->reestablish_timeout = 0;
        xprt->idle_timeout = 0;
 
-       /*
-        * The backchannel uses the same socket connection as the
-        * forechannel
-        */
-       args->bc_xprt->xpt_bc_xprt = xprt;
-       xprt->bc_xprt = args->bc_xprt;
-       bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt);
-       transport->sock = bc_sock->sk_sock;
-       transport->inet = bc_sock->sk_sk;
-
        xprt->ops = &bc_tcp_ops;
 
        switch (addr->sa_family) {
@@ -2406,6 +2396,29 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
                        xprt->address_strings[RPC_DISPLAY_PORT],
                        xprt->address_strings[RPC_DISPLAY_PROTO]);
 
+       /*
+        * The backchannel uses the same socket connection as the
+        * forechannel
+        */
+       if (args->bc_xprt->xpt_bc_xprt) {
+               /* XXX: actually, want to catch this case... */
+               ret = ERR_PTR(-EINVAL);
+               goto out_err;
+       }
+       /*
+        * Once we've associated a backchannel xprt with a connection,
+        * we want to keep it around as long as long as the connection
+        * lasts, in case we need to start using it for a backchannel
+        * again; this reference won't be dropped until bc_xprt is
+        * destroyed.
+        */
+       xprt_get(xprt);
+       args->bc_xprt->xpt_bc_xprt = xprt;
+       xprt->bc_xprt = args->bc_xprt;
+       bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt);
+       transport->sock = bc_sock->sk_sock;
+       transport->inet = bc_sock->sk_sk;
+
        /*
         * Since we don't want connections for the backchannel, we set
         * the xprt status to connected
@@ -2415,6 +2428,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
 
        if (try_module_get(THIS_MODULE))
                return xprt;
+       xprt_put(xprt);
        ret = ERR_PTR(-EINVAL);
 out_err:
        xprt_free(xprt);