<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
From: Andreas Gruenbacher &lt;agruen@suse.de&gt;

Allow a clone of an RPC client (created with rpc_clone_client()) to change to
another program.  This allows the NFS and NFSACL programs to share the same
transport.

Signed-off-by: Andreas Gruenbacher &lt;agruen@suse.de&gt;
Acked-by: Olaf Kirch &lt;okir@suse.de&gt;
Signed-off-by: Andrew Morton &lt;akpm@osdl.org&gt;
---

 25-akpm/include/linux/sunrpc/clnt.h |    3 +++
 25-akpm/net/sunrpc/clnt.c           |   23 +++++++++++++++++++++++
 25-akpm/net/sunrpc/pmap_clnt.c      |    4 ++--
 25-akpm/net/sunrpc/sunrpc_syms.c    |    1 +
 4 files changed, 29 insertions(+), 2 deletions(-)

diff -puN include/linux/sunrpc/clnt.h~nfsacl-allow-multiple-programs-to-share-the-same-transport include/linux/sunrpc/clnt.h
--- 25/include/linux/sunrpc/clnt.h~nfsacl-allow-multiple-programs-to-share-the-same-transport	2005-01-23 01:27:52.312353640 -0800
+++ 25-akpm/include/linux/sunrpc/clnt.h	2005-01-23 01:27:52.320352424 -0800
@@ -22,6 +22,7 @@
  * This defines an RPC port mapping
  */
 struct rpc_portmap {
+	struct rpc_portmap	*pm_parent;
 	__u32			pm_prog;
 	__u32			pm_vers;
 	__u32			pm_prot;
@@ -116,6 +117,8 @@ struct rpc_clnt *rpc_clone_client(struct
 int		rpc_shutdown_client(struct rpc_clnt *);
 int		rpc_destroy_client(struct rpc_clnt *);
 void		rpc_release_client(struct rpc_clnt *);
+void		rpc_change_program(struct rpc_clnt *, struct rpc_program *,
+				   int);
 void		rpc_getport(struct rpc_task *, struct rpc_clnt *);
 int		rpc_register(u32, u32, int, unsigned short, int *);
 
diff -puN net/sunrpc/clnt.c~nfsacl-allow-multiple-programs-to-share-the-same-transport net/sunrpc/clnt.c
--- 25/net/sunrpc/clnt.c~nfsacl-allow-multiple-programs-to-share-the-same-transport	2005-01-23 01:27:52.314353336 -0800
+++ 25-akpm/net/sunrpc/clnt.c	2005-01-23 01:27:52.321352272 -0800
@@ -139,6 +139,7 @@ rpc_create_client(struct rpc_xprt *xprt,
 	clnt-&gt;cl_maxproc  = version-&gt;nrprocs;
 	clnt-&gt;cl_protname = program-&gt;name;
 	clnt-&gt;cl_pmap	  = &amp;clnt-&gt;cl_pmap_default;
+	clnt-&gt;cl_pmap-&gt;pm_parent = clnt-&gt;cl_pmap;
 	clnt-&gt;cl_port     = xprt-&gt;addr.sin_port;
 	clnt-&gt;cl_prog     = program-&gt;number;
 	clnt-&gt;cl_vers     = version-&gt;number;
@@ -207,6 +208,9 @@ rpc_clone_client(struct rpc_clnt *clnt)
 	rpc_init_rtt(&amp;new-&gt;cl_rtt_default, clnt-&gt;cl_xprt-&gt;timeout.to_initval);
 	if (new-&gt;cl_auth)
 		atomic_inc(&amp;new-&gt;cl_auth-&gt;au_count);
+	new-&gt;cl_pmap		= &amp;new-&gt;cl_pmap_default;
+	new-&gt;cl_pmap-&gt;pm_parent = clnt-&gt;cl_pmap-&gt;pm_parent;
+	rpc_init_wait_queue(&amp;new-&gt;cl_pmap_default.pm_bindwait, "bindwait");
 	return new;
 out_no_clnt:
 	printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
@@ -296,6 +300,25 @@ rpc_release_client(struct rpc_clnt *clnt
 }
 
 /*
+ * Change the program of a (usually cloned) client
+ */
+void
+rpc_change_program(struct rpc_clnt *clnt, struct rpc_program *program,
+		   int vers)
+{
+	struct rpc_version *version;
+
+	BUG_ON(vers &gt;= program-&gt;nrvers || !program-&gt;version[vers]);
+	version = program-&gt;version[vers];
+	clnt-&gt;cl_procinfo = version-&gt;procs;
+	clnt-&gt;cl_maxproc  = version-&gt;nrprocs;
+	clnt-&gt;cl_protname = program-&gt;name;
+	clnt-&gt;cl_prog     = program-&gt;number;
+	clnt-&gt;cl_vers     = version-&gt;number;
+	clnt-&gt;cl_stats    = program-&gt;stats;
+}
+
+/*
  * Default callback for async RPC calls
  */
 static void
diff -puN net/sunrpc/pmap_clnt.c~nfsacl-allow-multiple-programs-to-share-the-same-transport net/sunrpc/pmap_clnt.c
--- 25/net/sunrpc/pmap_clnt.c~nfsacl-allow-multiple-programs-to-share-the-same-transport	2005-01-23 01:27:52.315353184 -0800
+++ 25-akpm/net/sunrpc/pmap_clnt.c	2005-01-23 01:27:52.322352120 -0800
@@ -41,7 +41,7 @@ static DEFINE_SPINLOCK(pmap_lock);
 void
 rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
 {
-	struct rpc_portmap *map = clnt-&gt;cl_pmap;
+	struct rpc_portmap *map = clnt-&gt;cl_pmap-&gt;pm_parent;
 	struct sockaddr_in *sap = &amp;clnt-&gt;cl_xprt-&gt;addr;
 	struct rpc_message msg = {
 		.rpc_proc	= &amp;pmap_procedures[PMAP_GETPORT],
@@ -132,7 +132,7 @@ static void
 pmap_getport_done(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task-&gt;tk_client;
-	struct rpc_portmap *map = clnt-&gt;cl_pmap;
+	struct rpc_portmap *map = clnt-&gt;cl_pmap-&gt;pm_parent;
 
 	dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n",
 			task-&gt;tk_pid, task-&gt;tk_status, clnt-&gt;cl_port);
diff -puN net/sunrpc/sunrpc_syms.c~nfsacl-allow-multiple-programs-to-share-the-same-transport net/sunrpc/sunrpc_syms.c
--- 25/net/sunrpc/sunrpc_syms.c~nfsacl-allow-multiple-programs-to-share-the-same-transport	2005-01-23 01:27:52.317352880 -0800
+++ 25-akpm/net/sunrpc/sunrpc_syms.c	2005-01-23 01:27:52.322352120 -0800
@@ -42,6 +42,7 @@ EXPORT_SYMBOL(rpc_release_task);
 /* RPC client functions */
 EXPORT_SYMBOL(rpc_create_client);
 EXPORT_SYMBOL(rpc_clone_client);
+EXPORT_SYMBOL(rpc_change_program);
 EXPORT_SYMBOL(rpc_destroy_client);
 EXPORT_SYMBOL(rpc_shutdown_client);
 EXPORT_SYMBOL(rpc_release_client);
_
</pre></body></html>