diff options
-rw-r--r-- | include/linux/sunrpc/clnt.h | 2 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 40 | ||||
-rw-r--r-- | net/sunrpc/pmap_clnt.c | 3 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 1 |
4 files changed, 46 insertions, 0 deletions
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index d25e80f77ff5..ab151bbb66df 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
@@ -114,6 +114,8 @@ struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname, | |||
114 | struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname, | 114 | struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname, |
115 | struct rpc_program *info, | 115 | struct rpc_program *info, |
116 | u32 version, rpc_authflavor_t authflavor); | 116 | u32 version, rpc_authflavor_t authflavor); |
117 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, | ||
118 | struct rpc_program *, int); | ||
117 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); | 119 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); |
118 | int rpc_shutdown_client(struct rpc_clnt *); | 120 | int rpc_shutdown_client(struct rpc_clnt *); |
119 | int rpc_destroy_client(struct rpc_clnt *); | 121 | int rpc_destroy_client(struct rpc_clnt *); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 33f12b84e265..c979fcf88798 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -241,6 +241,8 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
241 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | 241 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); |
242 | if (new->cl_auth) | 242 | if (new->cl_auth) |
243 | atomic_inc(&new->cl_auth->au_count); | 243 | atomic_inc(&new->cl_auth->au_count); |
244 | new->cl_pmap = &new->cl_pmap_default; | ||
245 | rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait"); | ||
244 | return new; | 246 | return new; |
245 | out_no_clnt: | 247 | out_no_clnt: |
246 | printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); | 248 | printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); |
@@ -329,6 +331,44 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
329 | rpc_destroy_client(clnt); | 331 | rpc_destroy_client(clnt); |
330 | } | 332 | } |
331 | 333 | ||
334 | /** | ||
335 | * rpc_bind_new_program - bind a new RPC program to an existing client | ||
336 | * @old - old rpc_client | ||
337 | * @program - rpc program to set | ||
338 | * @vers - rpc program version | ||
339 | * | ||
340 | * Clones the rpc client and sets up a new RPC program. This is mainly | ||
341 | * of use for enabling different RPC programs to share the same transport. | ||
342 | * The Sun NFSv2/v3 ACL protocol can do this. | ||
343 | */ | ||
344 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | ||
345 | struct rpc_program *program, | ||
346 | int vers) | ||
347 | { | ||
348 | struct rpc_clnt *clnt; | ||
349 | struct rpc_version *version; | ||
350 | int err; | ||
351 | |||
352 | BUG_ON(vers >= program->nrvers || !program->version[vers]); | ||
353 | version = program->version[vers]; | ||
354 | clnt = rpc_clone_client(old); | ||
355 | if (IS_ERR(clnt)) | ||
356 | goto out; | ||
357 | clnt->cl_procinfo = version->procs; | ||
358 | clnt->cl_maxproc = version->nrprocs; | ||
359 | clnt->cl_protname = program->name; | ||
360 | clnt->cl_prog = program->number; | ||
361 | clnt->cl_vers = version->number; | ||
362 | clnt->cl_stats = program->stats; | ||
363 | err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); | ||
364 | if (err != 0) { | ||
365 | rpc_shutdown_client(clnt); | ||
366 | clnt = ERR_PTR(err); | ||
367 | } | ||
368 | out: | ||
369 | return clnt; | ||
370 | } | ||
371 | |||
332 | /* | 372 | /* |
333 | * Default callback for async RPC calls | 373 | * Default callback for async RPC calls |
334 | */ | 374 | */ |
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c index df4d84c9020d..4e81f2766923 100644 --- a/net/sunrpc/pmap_clnt.c +++ b/net/sunrpc/pmap_clnt.c | |||
@@ -53,6 +53,9 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt) | |||
53 | task->tk_pid, clnt->cl_server, | 53 | task->tk_pid, clnt->cl_server, |
54 | map->pm_prog, map->pm_vers, map->pm_prot); | 54 | map->pm_prog, map->pm_vers, map->pm_prot); |
55 | 55 | ||
56 | /* Autobind on cloned rpc clients is discouraged */ | ||
57 | BUG_ON(clnt->cl_parent != clnt); | ||
58 | |||
56 | spin_lock(&pmap_lock); | 59 | spin_lock(&pmap_lock); |
57 | if (map->pm_binding) { | 60 | if (map->pm_binding) { |
58 | rpc_sleep_on(&map->pm_bindwait, task, NULL, NULL); | 61 | rpc_sleep_on(&map->pm_bindwait, task, NULL, NULL); |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 1b0ff7e0e869..d8673f66acc3 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -42,6 +42,7 @@ EXPORT_SYMBOL(rpc_release_task); | |||
42 | /* RPC client functions */ | 42 | /* RPC client functions */ |
43 | EXPORT_SYMBOL(rpc_create_client); | 43 | EXPORT_SYMBOL(rpc_create_client); |
44 | EXPORT_SYMBOL(rpc_clone_client); | 44 | EXPORT_SYMBOL(rpc_clone_client); |
45 | EXPORT_SYMBOL(rpc_bind_new_program); | ||
45 | EXPORT_SYMBOL(rpc_destroy_client); | 46 | EXPORT_SYMBOL(rpc_destroy_client); |
46 | EXPORT_SYMBOL(rpc_shutdown_client); | 47 | EXPORT_SYMBOL(rpc_shutdown_client); |
47 | EXPORT_SYMBOL(rpc_release_client); | 48 | EXPORT_SYMBOL(rpc_release_client); |