SUNRPC: Refactor rpc_clone_client()

rpc_clone_client() does most of the same tasks as rpc_new_client(),
so there is an opportunity for code re-use.  Create a generic helper
that makes it easy to clone an RPC client while replacing any of the
clnt's parameters.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Chuck Lever 2012-09-14 17:23:52 -04:00 committed by Trond Myklebust
parent 632f0d0503
commit 1b63a75180

View File

@ -490,59 +490,62 @@ EXPORT_SYMBOL_GPL(rpc_create);
* same transport while varying parameters such as the authentication * same transport while varying parameters such as the authentication
* flavour. * flavour.
*/ */
struct rpc_clnt * static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
rpc_clone_client(struct rpc_clnt *clnt) struct rpc_clnt *clnt)
{ {
struct rpc_clnt *new;
struct rpc_xprt *xprt; struct rpc_xprt *xprt;
int err = -ENOMEM; struct rpc_clnt *new;
int err;
new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); err = -ENOMEM;
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;
}
rcu_read_lock(); rcu_read_lock();
xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); xprt = xprt_get(rcu_dereference(clnt->cl_xprt));
rcu_read_unlock(); rcu_read_unlock();
if (xprt == NULL) if (xprt == NULL)
goto out_no_transport; goto out_err;
rcu_assign_pointer(new->cl_xprt, xprt); args->servername = xprt->servername;
atomic_set(&new->cl_count, 1);
err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); new = rpc_new_client(args, xprt);
if (err != 0) if (IS_ERR(new)) {
goto out_no_path; err = PTR_ERR(new);
rpc_clnt_set_nodename(new, utsname()->nodename); goto out_put;
if (new->cl_auth) }
atomic_inc(&new->cl_auth->au_count);
atomic_inc(&clnt->cl_count); atomic_inc(&clnt->cl_count);
rpc_register_client(new); new->cl_parent = clnt;
rpciod_up();
/* 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; return new;
out_no_path:
out_put:
xprt_put(xprt); xprt_put(xprt);
out_no_transport: out_err:
kfree(new->cl_principal);
out_no_principal:
rpc_free_iostats(new->cl_metrics);
out_no_stats:
kfree(new);
out_no_clnt:
dprintk("RPC: %s: returned error %d\n", __func__, err); dprintk("RPC: %s: returned error %d\n", __func__, err);
return ERR_PTR(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); EXPORT_SYMBOL_GPL(rpc_clone_client);
/* /*