|
@@ -490,59 +490,62 @@ EXPORT_SYMBOL_GPL(rpc_create);
|
|
|
* same transport while varying parameters such as the authentication
|
|
|
* flavour.
|
|
|
*/
|
|
|
-struct rpc_clnt *
|
|
|
-rpc_clone_client(struct rpc_clnt *clnt)
|
|
|
+static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
|
|
|
+ struct rpc_clnt *clnt)
|
|
|
{
|
|
|
- struct rpc_clnt *new;
|
|
|
struct rpc_xprt *xprt;
|
|
|
- int err = -ENOMEM;
|
|
|
+ struct rpc_clnt *new;
|
|
|
+ int err;
|
|
|
|
|
|
- new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
|
|
|
- if (!new)
|
|
|
- goto out_no_clnt;
|
|
|
- new->cl_parent = clnt;
|
|
|
- /* Turn off autobind on clones */
|
|
|
- new->cl_autobind = 0;
|
|
|
- INIT_LIST_HEAD(&new->cl_tasks);
|
|
|
- spin_lock_init(&new->cl_lock);
|
|
|
- rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval);
|
|
|
- new->cl_metrics = rpc_alloc_iostats(clnt);
|
|
|
- if (new->cl_metrics == NULL)
|
|
|
- goto out_no_stats;
|
|
|
- if (clnt->cl_principal) {
|
|
|
- new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL);
|
|
|
- if (new->cl_principal == NULL)
|
|
|
- goto out_no_principal;
|
|
|
- }
|
|
|
+ err = -ENOMEM;
|
|
|
rcu_read_lock();
|
|
|
xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
|
|
|
rcu_read_unlock();
|
|
|
if (xprt == NULL)
|
|
|
- goto out_no_transport;
|
|
|
- rcu_assign_pointer(new->cl_xprt, xprt);
|
|
|
- atomic_set(&new->cl_count, 1);
|
|
|
- err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
|
|
|
- if (err != 0)
|
|
|
- goto out_no_path;
|
|
|
- rpc_clnt_set_nodename(new, utsname()->nodename);
|
|
|
- if (new->cl_auth)
|
|
|
- atomic_inc(&new->cl_auth->au_count);
|
|
|
+ goto out_err;
|
|
|
+ args->servername = xprt->servername;
|
|
|
+
|
|
|
+ new = rpc_new_client(args, xprt);
|
|
|
+ if (IS_ERR(new)) {
|
|
|
+ err = PTR_ERR(new);
|
|
|
+ goto out_put;
|
|
|
+ }
|
|
|
+
|
|
|
atomic_inc(&clnt->cl_count);
|
|
|
- rpc_register_client(new);
|
|
|
- rpciod_up();
|
|
|
+ new->cl_parent = clnt;
|
|
|
+
|
|
|
+ /* Turn off autobind on clones */
|
|
|
+ new->cl_autobind = 0;
|
|
|
+ new->cl_softrtry = clnt->cl_softrtry;
|
|
|
+ new->cl_discrtry = clnt->cl_discrtry;
|
|
|
+ new->cl_chatty = clnt->cl_chatty;
|
|
|
return new;
|
|
|
-out_no_path:
|
|
|
+
|
|
|
+out_put:
|
|
|
xprt_put(xprt);
|
|
|
-out_no_transport:
|
|
|
- kfree(new->cl_principal);
|
|
|
-out_no_principal:
|
|
|
- rpc_free_iostats(new->cl_metrics);
|
|
|
-out_no_stats:
|
|
|
- kfree(new);
|
|
|
-out_no_clnt:
|
|
|
+out_err:
|
|
|
dprintk("RPC: %s: returned error %d\n", __func__, err);
|
|
|
return ERR_PTR(err);
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * rpc_clone_client - Clone an RPC client structure
|
|
|
+ *
|
|
|
+ * @clnt: RPC client whose parameters are copied
|
|
|
+ *
|
|
|
+ * Returns a fresh RPC client or an ERR_PTR.
|
|
|
+ */
|
|
|
+struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt)
|
|
|
+{
|
|
|
+ struct rpc_create_args args = {
|
|
|
+ .program = clnt->cl_program,
|
|
|
+ .prognumber = clnt->cl_prog,
|
|
|
+ .version = clnt->cl_vers,
|
|
|
+ .authflavor = clnt->cl_auth->au_flavor,
|
|
|
+ .client_name = clnt->cl_principal,
|
|
|
+ };
|
|
|
+ return __rpc_clone_client(&args, clnt);
|
|
|
+}
|
|
|
EXPORT_SYMBOL_GPL(rpc_clone_client);
|
|
|
|
|
|
/*
|