SUNRPC: Allow creation of RPC clients with multiple connections
authorTrond Myklebust <trond.myklebust@primarydata.com>
Thu, 27 Apr 2017 12:50:51 +0000 (08:50 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Sat, 6 Jul 2019 18:54:50 +0000 (14:54 -0400)
Add an argument to struct rpc_create_args that allows the specification
of how many transport connections you want to set up to the server.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
include/linux/sunrpc/clnt.h
net/sunrpc/clnt.c
net/sunrpc/xprtmultipath.c

index 6e80731..4619098 100644 (file)
@@ -124,6 +124,7 @@ struct rpc_create_args {
        u32                     prognumber;     /* overrides program->number */
        u32                     version;
        rpc_authflavor_t        authflavor;
+       u32                     nconnect;
        unsigned long           flags;
        char                    *client_name;
        struct svc_xprt         *bc_xprt;       /* NFSv4.1 backchannel */
index 976eab6..b6aca8c 100644 (file)
@@ -528,6 +528,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
                .bc_xprt = args->bc_xprt,
        };
        char servername[48];
+       struct rpc_clnt *clnt;
+       int i;
 
        if (args->bc_xprt) {
                WARN_ON_ONCE(!(args->protocol & XPRT_TRANSPORT_BC));
@@ -590,7 +592,15 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
        if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
                xprt->resvport = 0;
 
-       return rpc_create_xprt(args, xprt);
+       clnt = rpc_create_xprt(args, xprt);
+       if (IS_ERR(clnt) || args->nconnect <= 1)
+               return clnt;
+
+       for (i = 0; i < args->nconnect - 1; i++) {
+               if (rpc_clnt_add_xprt(clnt, &xprtargs, NULL, NULL) < 0)
+                       break;
+       }
+       return clnt;
 }
 EXPORT_SYMBOL_GPL(rpc_create);
 
@@ -2730,6 +2740,10 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
                return -ENOMEM;
        data->xps = xprt_switch_get(xps);
        data->xprt = xprt_get(xprt);
+       if (rpc_xprt_switch_has_addr(data->xps, (struct sockaddr *)&xprt->addr)) {
+               rpc_cb_add_xprt_release(data);
+               goto success;
+       }
 
        task = rpc_call_null_helper(clnt, xprt, NULL,
                        RPC_TASK_SOFT|RPC_TASK_SOFTCONN|RPC_TASK_ASYNC|RPC_TASK_NULLCREDS,
@@ -2737,6 +2751,7 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
        if (IS_ERR(task))
                return PTR_ERR(task);
        rpc_put_task(task);
+success:
        return 1;
 }
 EXPORT_SYMBOL_GPL(rpc_clnt_test_and_add_xprt);
index 394e427..9d66ce5 100644 (file)
@@ -52,8 +52,7 @@ void rpc_xprt_switch_add_xprt(struct rpc_xprt_switch *xps,
        if (xprt == NULL)
                return;
        spin_lock(&xps->xps_lock);
-       if ((xps->xps_net == xprt->xprt_net || xps->xps_net == NULL) &&
-           !rpc_xprt_switch_has_addr(xps, (struct sockaddr *)&xprt->addr))
+       if (xps->xps_net == xprt->xprt_net || xps->xps_net == NULL)
                xprt_switch_add_xprt_locked(xps, xprt);
        spin_unlock(&xps->xps_lock);
 }