Commit 007e251f2b2760f738c92adc8c80cbae0bed3ce5
Committed by
Trond Myklebust
1 parent
cdf477068e
Exists in
master
and in
39 other branches
[PATCH] RPC: Allow multiple RPC client programs to share the same transport
Signed-off-by: Andreas Gruenbacher <agruen@suse.de> Acked-by: Olaf Kirch <okir@suse.de> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Showing 4 changed files with 46 additions and 0 deletions Side-by-side Diff
include/linux/sunrpc/clnt.h
... | ... | @@ -114,6 +114,8 @@ |
114 | 114 | struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname, |
115 | 115 | struct rpc_program *info, |
116 | 116 | u32 version, rpc_authflavor_t authflavor); |
117 | +struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, | |
118 | + struct rpc_program *, int); | |
117 | 119 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); |
118 | 120 | int rpc_shutdown_client(struct rpc_clnt *); |
119 | 121 | int rpc_destroy_client(struct rpc_clnt *); |
net/sunrpc/clnt.c
... | ... | @@ -241,6 +241,8 @@ |
241 | 241 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); |
242 | 242 | if (new->cl_auth) |
243 | 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 | 246 | return new; |
245 | 247 | out_no_clnt: |
246 | 248 | printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); |
... | ... | @@ -327,6 +329,44 @@ |
327 | 329 | wake_up(&destroy_wait); |
328 | 330 | if (clnt->cl_oneshot || clnt->cl_dead) |
329 | 331 | rpc_destroy_client(clnt); |
332 | +} | |
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; | |
330 | 370 | } |
331 | 371 | |
332 | 372 | /* |
net/sunrpc/pmap_clnt.c
... | ... | @@ -53,6 +53,9 @@ |
53 | 53 | task->tk_pid, clnt->cl_server, |
54 | 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 | 59 | spin_lock(&pmap_lock); |
57 | 60 | if (map->pm_binding) { |
58 | 61 | rpc_sleep_on(&map->pm_bindwait, task, NULL, NULL); |
net/sunrpc/sunrpc_syms.c
... | ... | @@ -42,6 +42,7 @@ |
42 | 42 | /* RPC client functions */ |
43 | 43 | EXPORT_SYMBOL(rpc_create_client); |
44 | 44 | EXPORT_SYMBOL(rpc_clone_client); |
45 | +EXPORT_SYMBOL(rpc_bind_new_program); | |
45 | 46 | EXPORT_SYMBOL(rpc_destroy_client); |
46 | 47 | EXPORT_SYMBOL(rpc_shutdown_client); |
47 | 48 | EXPORT_SYMBOL(rpc_release_client); |