rpc: allow xprt_class->setup to return a preexisting xprt
authorJ. Bruce Fields <bfields@redhat.com>
Wed, 8 Dec 2010 18:48:19 +0000 (13:48 -0500)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 11 Jan 2011 20:04:10 +0000 (15:04 -0500)
This allows us to reuse the xprt associated with a server connection if
one has already been set up.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
include/linux/sunrpc/xprt.h
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c

index 89d10d2..bef0f53 100644 (file)
@@ -321,6 +321,7 @@ void                        xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie);
 #define XPRT_CLOSING           (6)
 #define XPRT_CONNECTION_ABORT  (7)
 #define XPRT_CONNECTION_CLOSE  (8)
+#define XPRT_INITIALIZED       (9)
 
 static inline void xprt_set_connected(struct rpc_xprt *xprt)
 {
index 749ad15..856274d 100644 (file)
@@ -1102,6 +1102,9 @@ found:
                                -PTR_ERR(xprt));
                return xprt;
        }
+       if (test_and_set_bit(XPRT_INITIALIZED, &xprt->state))
+               /* ->setup returned a pre-initialized xprt: */
+               return xprt;
 
        spin_lock_init(&xprt->transport_lock);
        spin_lock_init(&xprt->reserve_lock);
index 0ef4dd4..ee091c8 100644 (file)
@@ -2359,6 +2359,15 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
        struct svc_sock *bc_sock;
        struct rpc_xprt *ret;
 
+       if (args->bc_xprt->xpt_bc_xprt) {
+               /*
+                * This server connection already has a backchannel
+                * export; we can't create a new one, as we wouldn't be
+                * able to match replies based on xid any more.  So,
+                * reuse the already-existing one:
+                */
+                return args->bc_xprt->xpt_bc_xprt;
+       }
        xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
        if (IS_ERR(xprt))
                return xprt;
@@ -2396,15 +2405,6 @@ 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