public inbox for linux-nfs@vger.kernel.org
 help / color / mirror / Atom feed
* Suggested improvements for localio support.
@ 2024-06-21  4:59 NeilBrown
  2024-06-21  4:59 ` [PATCH 1/3] NFS: Simplify Client NFS_LOCALIO_PROGRAM support NeilBrown
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: NeilBrown @ 2024-06-21  4:59 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: linux-nfs, Jeff Layton, Chuck Lever, Trond Myklebust

These three patches are intend to be merged into the nfs localio patch series.

The first two should be squashed into existing patches as mentioned in
the commit description.  The first is a stand alone patch which cleans
up some ugliness that the current rpcsvc infrastructure requires.

As mentioned in the first patch, a small rearranged of patches is
required for each individual patch to compile.

I would like to suggest changes to the CONFIG options too - I haven't
provided a patch for that.

There should be just one config option: CONFIG_NFS_LOCALIO.  There is no
point enabling for client without server or server without client as in
either configuration nothing useful can be achieved.  There is also no
gain in enabling only for v3 or v4 and not both (unless I've missed
something...)

Despite Jeff's generally sensible suggestion, I'd like the CONFIG option
to be added earliy so that we can compile-test each individual commit.
If that would mean some intermediate commit might be problematic then I
would rather the localio_enabled module parameter were forced to 'false'
until it was safe to turn it on.

I note that the server uses uuid_t while the client doesn't.  I might
have made that worse...  We should probably be consisent.

I have only tested very lightly - treat as a base for further work more
than as a fully polished solution.

Thanks,
NeilBrown

 [PATCH 1/3] NFS: Simplify Client NFS_LOCALIO_PROGRAM support
 [PATCH 2/3] NFSD: Simplify server NFS_LOCALIO_PROGRAM support
 [PATCH 3/3] SUNRPC: replace program list with program array

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] NFS: Simplify Client NFS_LOCALIO_PROGRAM support
  2024-06-21  4:59 Suggested improvements for localio support NeilBrown
@ 2024-06-21  4:59 ` NeilBrown
  2024-06-21  4:59 ` [PATCH 2/3] NFSD: Simplify server " NeilBrown
  2024-06-21  4:59 ` [PATCH 3/3] SUNRPC: replace program list with program array NeilBrown
  2 siblings, 0 replies; 4+ messages in thread
From: NeilBrown @ 2024-06-21  4:59 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: linux-nfs, Jeff Layton, Chuck Lever, Trond Myklebust

From: NeilBrown <neil@brown.name>

This patch is intended to be squashed into
  nfs: implement v3 and v4 client support for NFS_LOCALIO_PROGRAM

It moves all the knowledge of the LOCALIO RPC protocol in
fs/nfs/localio.c and implements just a single version (1) which is used
independently of what NFS version is used.

The #defines for PROGRAM and PROC numbers are moved out of uapi as these
are not part of the UAPI - only Linux internals need to know then.
Other servers might see them but the numbers are chosen so other servers
will reject the any request they see.

For the resulting patch to compile,
 nfs/nfsd: consolidate {encode,decode}_opaque_fixed in nfs_xdr.h

needs to be applied earlier in the series.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/nfs/internal.h        |  5 --
 fs/nfs/localio.c         | 99 ++++++++++++++++++++++++++++------------
 fs/nfs/nfs3_fs.h         |  1 -
 fs/nfs/nfs3client.c      | 23 ----------
 fs/nfs/nfs3proc.c        |  3 --
 fs/nfs/nfs3xdr.c         | 67 ---------------------------
 fs/nfs/nfs4_fs.h         |  2 -
 fs/nfs/nfs4client.c      | 23 ----------
 fs/nfs/nfs4proc.c        |  3 --
 fs/nfs/nfs4xdr.c         | 52 ---------------------
 include/linux/nfs.h      |  7 +++
 include/linux/nfs_xdr.h  | 12 -----
 include/uapi/linux/nfs.h |  4 --
 13 files changed, 76 insertions(+), 225 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 15310618f4f0..9251a357d097 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -456,8 +456,6 @@ extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
 /* localio.c */
 extern void nfs_local_disable(struct nfs_client *);
 extern void nfs_local_probe(struct nfs_client *);
-extern void nfs_init_localioclient(struct nfs_client *clp,
-				   const struct rpc_program *program, u32 vers);
 extern struct file *nfs_local_open_fh(struct nfs_client *, const struct cred *,
 				      struct nfs_fh *, const fmode_t);
 extern struct file *nfs_local_file_open(struct nfs_client *clp,
@@ -474,9 +472,6 @@ extern bool nfs_server_is_local(const struct nfs_client *clp);
 #else
 static inline void nfs_local_disable(struct nfs_client *clp) {}
 static inline void nfs_local_probe(struct nfs_client *clp) {}
-static inline void nfs_init_localioclient(struct nfs_client *clp,
-					  const struct rpc_program *program,
-					  u32 vers) {}
 static inline struct file *nfs_local_open_fh(struct nfs_client *clp,
 					const struct cred *cred,
 					struct nfs_fh *fh,
diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c
index 1fa41228b278..85a370bf7b28 100644
--- a/fs/nfs/localio.c
+++ b/fs/nfs/localio.c
@@ -135,6 +135,58 @@ bool nfs_server_is_local(const struct nfs_client *clp)
 }
 EXPORT_SYMBOL_GPL(nfs_server_is_local);
 
+
+static void localio_xdr_enc_getuuidargs(struct rpc_rqst *req,
+					struct xdr_stream *xdr,
+					const void *data)
+{
+	/* void function */
+}
+
+static int localio_xdr_dec_getuuidres(struct rpc_rqst *req,
+				      struct xdr_stream *xdr,
+				      void *result)
+{
+	u8 *uuid = result;
+
+	return decode_opaque_fixed(xdr, uuid, UUID_SIZE);
+}
+
+static const struct rpc_procinfo nfs_localio_procedures[] = {
+	[LOCALIOPROC_GETUUID] = {
+		.p_proc = LOCALIOPROC_GETUUID,
+		.p_encode = localio_xdr_enc_getuuidargs,
+		.p_decode = localio_xdr_dec_getuuidres,
+		.p_arglen = 0,
+		.p_replen = XDR_QUADLEN(UUID_SIZE),
+		.p_statidx = LOCALIOPROC_GETUUID,
+		.p_name = "GETUUID",
+	},
+};
+
+static unsigned int nfs_localio_counts[ARRAY_SIZE(nfs_localio_procedures)];
+const struct rpc_version nfslocalio_version1 = {
+	.number			= 1,
+	.nrprocs		= ARRAY_SIZE(nfs_localio_procedures),
+	.procs			= nfs_localio_procedures,
+	.counts			= nfs_localio_counts,
+};
+
+static const struct rpc_version *nfslocalio_version[] = {
+       [1]			= &nfslocalio_version1,
+};
+
+extern const struct rpc_program nfslocalio_program;
+static struct rpc_stat		nfslocalio_rpcstat = { &nfslocalio_program };
+
+const struct rpc_program nfslocalio_program = {
+	.name			= "nfslocalio",
+	.number			= NFS_LOCALIO_PROGRAM,
+	.nrvers			= ARRAY_SIZE(nfslocalio_version),
+	.version		= nfslocalio_version,
+	.stats			= &nfslocalio_rpcstat,
+};
+
 /*
  * nfs_local_enable - attempt to enable local i/o for an nfs_client
  */
@@ -167,13 +219,12 @@ void nfs_local_disable(struct nfs_client *clp)
 /*
  * nfs_init_localioclient - Initialise an NFS localio client connection
  */
-void nfs_init_localioclient(struct nfs_client *clp,
-			    const struct rpc_program *program, u32 vers)
+static void nfs_init_localioclient(struct nfs_client *clp)
 {
 	if (unlikely(!IS_ERR(clp->cl_rpcclient_localio)))
 		goto out;
 	clp->cl_rpcclient_localio = rpc_bind_new_program(clp->cl_rpcclient,
-							 program, vers);
+							 &nfslocalio_program, 1);
 	if (IS_ERR(clp->cl_rpcclient_localio))
 		goto out;
 	/* No errors! Assume that localio is supported */
@@ -183,38 +234,33 @@ void nfs_init_localioclient(struct nfs_client *clp,
 		clp->cl_rpcclient_localio = ERR_PTR(-EINVAL);
 	}
 out:
-	dprintk_rcu("%s: server (%s) %s NFSv%u LOCALIO, nfsd_open_local_fh is %s.\n",
+	dprintk_rcu("%s: server (%s) %s NFS LOCALIO, nfsd_open_local_fh is %s.\n",
 		__func__, rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR),
 		(IS_ERR(clp->cl_rpcclient_localio) ? "does not support" : "supports"),
-		vers, (clp->nfsd_open_local_fh ? "set" : "not set"));
+		(clp->nfsd_open_local_fh ? "set" : "not set"));
 }
-EXPORT_SYMBOL(nfs_init_localioclient);
 
 static bool nfs_local_server_getuuid(struct nfs_client *clp, uuid_t *nfsd_uuid)
 {
 	u8 uuid[UUID_SIZE];
-	struct nfs_getuuidres res = {
-		uuid,
-	};
 	struct rpc_message msg = {
-		.rpc_resp = &res,
+		.rpc_resp = &uuid,
 	};
 	int status;
 
-	/* Indirect call to nfs_init_localioclient() */
-	clp->rpc_ops->init_localioclient(clp);
+	nfs_init_localioclient(clp);
 	if (IS_ERR(clp->cl_rpcclient_localio))
 		return false;
 
 	dprintk("%s: NFS issuing getuuid\n", __func__);
-	msg.rpc_proc = &clp->cl_rpcclient_localio->cl_procinfo[LOCALIOPROC_GETUUID];
+	msg.rpc_proc = &nfs_localio_procedures[LOCALIOPROC_GETUUID];
 	status = rpc_call_sync(clp->cl_rpcclient_localio, &msg, 0);
 	dprintk("%s: NFS reply getuuid: status=%d uuid=%pU\n",
-		__func__, status, res.uuid);
+		__func__, status, uuid);
 	if (status)
 		return false;
 
-	import_uuid(nfsd_uuid, res.uuid);
+	import_uuid(nfsd_uuid, uuid);
 
 	return true;
 }
@@ -237,22 +283,15 @@ void nfs_local_probe(struct nfs_client *clp)
 		nfs_local_disable(clp);
 	}
 
-	switch (clp->cl_rpcclient->cl_vers) {
-	case 3:
-	case 4:
-		/*
-		 * Retrieve server's uuid via LOCALIO protocol and verify the
-		 * server with that uuid is known to be local. This ensures
-		 * client and server 1: support localio 2: are local to each other
-		 * by verifying client's nfsd, with specified uuid, is local.
-		 */
-		if (!nfs_local_server_getuuid(clp, &uuid) ||
-		    !nfsd_uuid_is_local(&uuid, &net))
-			goto unsupported;
-		break;
-	default:
+	/*
+	 * Retrieve server's uuid via LOCALIO protocol and verify the
+	 * server with that uuid is known to be local. This ensures
+	 * client and server 1: support localio 2: are local to each other
+	 * by verifying client's nfsd, with specified uuid, is local.
+	 */
+	if (!nfs_local_server_getuuid(clp, &uuid) ||
+	    !nfsd_uuid_is_local(&uuid, &net))
 		goto unsupported;
-	}
 
 	dprintk("%s: detected local server.\n", __func__);
 	nfs_local_enable(clp, net);
diff --git a/fs/nfs/nfs3_fs.h b/fs/nfs/nfs3_fs.h
index efdf2b6519e9..b333ea119ef5 100644
--- a/fs/nfs/nfs3_fs.h
+++ b/fs/nfs/nfs3_fs.h
@@ -30,7 +30,6 @@ static inline int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
 struct nfs_server *nfs3_create_server(struct fs_context *);
 struct nfs_server *nfs3_clone_server(struct nfs_server *, struct nfs_fh *,
 				     struct nfs_fattr *, rpc_authflavor_t);
-void nfs3_init_localioclient(struct nfs_client *);
 
 /* nfs3super.c */
 extern struct nfs_subversion nfs_v3;
diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c
index 5d478034f5ea..b0c8a39c2bbd 100644
--- a/fs/nfs/nfs3client.c
+++ b/fs/nfs/nfs3client.c
@@ -130,26 +130,3 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
 	return clp;
 }
 EXPORT_SYMBOL_GPL(nfs3_set_ds_client);
-
-#if defined(CONFIG_NFS_V3_LOCALIO)
-static struct rpc_stat		nfslocalio_rpcstat = { &nfslocalio_program3 };
-static const struct rpc_version *nfslocalio_version[] = {
-	[3]			= &nfslocalio_version3,
-};
-
-const struct rpc_program nfslocalio_program3 = {
-	.name			= "nfslocalio",
-	.number			= NFS_LOCALIO_PROGRAM,
-	.nrvers			= ARRAY_SIZE(nfslocalio_version),
-	.version		= nfslocalio_version,
-	.stats			= &nfslocalio_rpcstat,
-};
-
-/*
- * Initialise an NFSv3 localio client connection
- */
-void nfs3_init_localioclient(struct nfs_client *clp)
-{
-	nfs_init_localioclient(clp, &nfslocalio_program3, 3);
-}
-#endif /* CONFIG_NFS_V3_LOCALIO */
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 40b6e4d1e7be..74bda639a7cf 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -1067,7 +1067,4 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
 	.free_client	= nfs_free_client,
 	.create_server	= nfs3_create_server,
 	.clone_server	= nfs3_clone_server,
-#if defined(CONFIG_NFS_V3_LOCALIO)
-	.init_localioclient = nfs3_init_localioclient,
-#endif
 };
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index d2a17ecd12b8..60f032be805a 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -2579,70 +2579,3 @@ const struct rpc_version nfsacl_version3 = {
 	.counts			= nfs3_acl_counts,
 };
 #endif  /* CONFIG_NFS_V3_ACL */
-
-#if defined(CONFIG_NFS_V3_LOCALIO)
-
-#define LOCALIO3_getuuidres_sz	(1+XDR_QUADLEN(UUID_SIZE))
-
-static void nfs3_xdr_enc_getuuidargs(struct rpc_rqst *req,
-				struct xdr_stream *xdr,
-				const void *data)
-{
-	/* void function */
-}
-
-// FIXME: factor out from fs/nfs/nfs4xdr.c
-static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len)
-{
-	ssize_t ret = xdr_stream_decode_opaque_fixed(xdr, buf, len);
-	if (unlikely(ret < 0))
-		return -EIO;
-	return 0;
-}
-
-static inline int nfs3_decode_getuuidresok(struct xdr_stream *xdr,
-					struct nfs_getuuidres *result)
-{
-	return decode_opaque_fixed(xdr, result->uuid, UUID_SIZE);
-}
-
-static int nfs3_xdr_dec_getuuidres(struct rpc_rqst *req,
-				struct xdr_stream *xdr,
-				void *result)
-{
-	enum nfs_stat status;
-	int error;
-
-	error = decode_nfsstat3(xdr, &status);
-	if (unlikely(error))
-		goto out;
-	if (status != NFS3_OK)
-		goto out_default;
-	error = nfs3_decode_getuuidresok(xdr, result);
-out:
-	return error;
-out_default:
-	return nfs3_stat_to_errno(status);
-}
-
-static const struct rpc_procinfo nfs3_localio_procedures[] = {
-	[LOCALIOPROC_GETUUID] = {
-		.p_proc = LOCALIOPROC_GETUUID,
-		.p_encode = nfs3_xdr_enc_getuuidargs,
-		.p_decode = nfs3_xdr_dec_getuuidres,
-		.p_arglen = 1,
-		.p_replen = LOCALIO3_getuuidres_sz,
-		.p_timer = 0,
-		.p_name = "GETUUID",
-	},
-};
-
-static unsigned int nfs3_localio_counts[ARRAY_SIZE(nfs3_localio_procedures)];
-const struct rpc_version nfslocalio_version3 = {
-	.number			= 3,
-	.nrprocs		= ARRAY_SIZE(nfs3_localio_procedures),
-	.procs			= nfs3_localio_procedures,
-	.counts			= nfs3_localio_counts,
-};
-
-#endif  /* CONFIG_NFS_V3_LOCALIO */
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index a0a41917dec2..7024230f0d1d 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -538,8 +538,6 @@ extern int nfs4_proc_commit(struct file *dst, __u64 offset, __u32 count, struct
 extern const nfs4_stateid zero_stateid;
 extern const nfs4_stateid invalid_stateid;
 
-extern void nfs4_init_localioclient(struct nfs_client *);
-
 /* nfs4super.c */
 struct nfs_mount_info;
 extern struct nfs_subversion nfs_v4;
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index d2f634aa1e1b..84573df5cf5a 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -1384,26 +1384,3 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
 
 	return nfs_probe_server(server, NFS_FH(d_inode(server->super->s_root)));
 }
-
-#if defined(CONFIG_NFS_V4_LOCALIO)
-static struct rpc_stat		nfslocalio_rpcstat = { &nfslocalio_program4 };
-static const struct rpc_version *nfslocalio_version[] = {
-	[4]			= &nfslocalio_version4,
-};
-
-const struct rpc_program nfslocalio_program4 = {
-	.name			= "nfslocalio",
-	.number			= NFS_LOCALIO_PROGRAM,
-	.nrvers			= ARRAY_SIZE(nfslocalio_version),
-	.version		= nfslocalio_version,
-	.stats			= &nfslocalio_rpcstat,
-};
-
-/*
- * Initialise an NFSv4 localio client connection
- */
-void nfs4_init_localioclient(struct nfs_client *clp)
-{
-	nfs_init_localioclient(clp, &nfslocalio_program4, 4);
-}
-#endif /* CONFIG_NFS_V4_LOCALIO */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 060bc8dbee61..c93c12063b3a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -10745,9 +10745,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
 	.discover_trunking = nfs4_discover_trunking,
 	.enable_swap	= nfs4_enable_swap,
 	.disable_swap	= nfs4_disable_swap,
-#if defined(CONFIG_NFS_V4_LOCALIO)
-	.init_localioclient = nfs4_init_localioclient,
-#endif
 };
 
 static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index d3b4fa3245f0..1416099dfcd1 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -7728,55 +7728,3 @@ const struct rpc_version nfs_version4 = {
 	.procs			= nfs4_procedures,
 	.counts			= nfs_version4_counts,
 };
-
-#if defined(CONFIG_NFS_V4_LOCALIO)
-
-#define LOCALIO4_getuuidres_sz	(op_decode_hdr_maxsz+XDR_QUADLEN(UUID_SIZE))
-
-static void nfs4_xdr_enc_getuuidargs(struct rpc_rqst *req,
-				struct xdr_stream *xdr,
-				const void *data)
-{
-	/* void function */
-}
-
-static inline int nfs4_decode_getuuidresok(struct xdr_stream *xdr,
-					struct nfs_getuuidres *result)
-{
-	return decode_opaque_fixed(xdr, result->uuid, UUID_SIZE);
-}
-
-static int nfs4_xdr_dec_getuuidres(struct rpc_rqst *req,
-				struct xdr_stream *xdr,
-				void *result)
-{
-	// FIXME: need proper handling that isn't abusing nfs_opnum4
-	int error = decode_op_hdr(xdr, LOCALIOPROC_GETUUID);
-	if (unlikely(error))
-		goto out;
-	error = nfs4_decode_getuuidresok(xdr, result);
-out:
-	return error;
-}
-
-static const struct rpc_procinfo nfs4_localio_procedures[] = {
-	[LOCALIOPROC_GETUUID] = {
-		.p_proc = LOCALIOPROC_GETUUID,
-		.p_encode = nfs4_xdr_enc_getuuidargs,
-		.p_decode = nfs4_xdr_dec_getuuidres,
-		.p_arglen = 1,
-		.p_replen = LOCALIO4_getuuidres_sz,
-		.p_statidx = LOCALIOPROC_GETUUID,
-		.p_name = "GETUUID",
-	},
-};
-
-static unsigned int nfs4_localio_counts[ARRAY_SIZE(nfs4_localio_procedures)];
-const struct rpc_version nfslocalio_version4 = {
-	.number			= 4,
-	.nrprocs		= ARRAY_SIZE(nfs4_localio_procedures),
-	.procs			= nfs4_localio_procedures,
-	.counts			= nfs4_localio_counts,
-};
-
-#endif  /* CONFIG_NFS_V4_LOCALIO */
diff --git a/include/linux/nfs.h b/include/linux/nfs.h
index 64ed672a0b34..a19422141563 100644
--- a/include/linux/nfs.h
+++ b/include/linux/nfs.h
@@ -15,6 +15,13 @@
 #include <linux/crc32.h>
 #include <uapi/linux/nfs.h>
 
+/* The localio program is entirely private to Linux and is
+ * NOT part of the uapi.
+ */
+#define NFS_LOCALIO_PROGRAM	0x20000002
+#define LOCALIOPROC_NULL	0
+#define LOCALIOPROC_GETUUID	1
+
 /*
  * This is the kernel NFS client file handle representation
  */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 56d23b84efbb..764513a61601 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1002,10 +1002,6 @@ struct nfs3_getaclres {
 	struct posix_acl *	acl_default;
 };
 
-struct nfs_getuuidres {
-	__u8 *			uuid;
-};
-
 #if IS_ENABLED(CONFIG_NFS_V4)
 
 typedef u64 clientid4;
@@ -1823,9 +1819,6 @@ struct nfs_rpc_ops {
 	int	(*discover_trunking)(struct nfs_server *, struct nfs_fh *);
 	void	(*enable_swap)(struct inode *inode);
 	void	(*disable_swap)(struct inode *inode);
-#if IS_ENABLED(CONFIG_NFS_LOCALIO)
-	void	(*init_localioclient)(struct nfs_client *);
-#endif
 };
 
 /*
@@ -1841,9 +1834,4 @@ extern const struct rpc_version nfs_version4;
 extern const struct rpc_version nfsacl_version3;
 extern const struct rpc_program nfsacl_program;
 
-extern const struct rpc_version nfslocalio_version3;
-extern const struct rpc_program nfslocalio_program3;
-extern const struct rpc_version nfslocalio_version4;
-extern const struct rpc_program nfslocalio_program4;
-
 #endif
diff --git a/include/uapi/linux/nfs.h b/include/uapi/linux/nfs.h
index 81eb865d99ef..f356f2ba3814 100644
--- a/include/uapi/linux/nfs.h
+++ b/include/uapi/linux/nfs.h
@@ -33,10 +33,6 @@
 #define NFS_MNT_VERSION		1
 #define NFS_MNT3_VERSION	3
 
-#define NFS_LOCALIO_PROGRAM	0x20000002
-#define LOCALIOPROC_NULL	0
-#define LOCALIOPROC_GETUUID	1
-
 #define NFS_PIPE_DIRNAME "nfs"
 
 /*
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] NFSD: Simplify server NFS_LOCALIO_PROGRAM support
  2024-06-21  4:59 Suggested improvements for localio support NeilBrown
  2024-06-21  4:59 ` [PATCH 1/3] NFS: Simplify Client NFS_LOCALIO_PROGRAM support NeilBrown
@ 2024-06-21  4:59 ` NeilBrown
  2024-06-21  4:59 ` [PATCH 3/3] SUNRPC: replace program list with program array NeilBrown
  2 siblings, 0 replies; 4+ messages in thread
From: NeilBrown @ 2024-06-21  4:59 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: linux-nfs, Jeff Layton, Chuck Lever, Trond Myklebust

From: NeilBrown <neil@brown.name>

This patch is intended to be squashed into
 nfsd: implement v3 and v4 server support for NFS_LOCALIO_PROGRAM

It moves all code for the LOCALIO RPC programs into localio.c with a
little bit in nfssvc.c, and implements just a single version.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/nfsd/localio.c | 106 +++++++++-------------------------------------
 fs/nfsd/nfsd.h    |  11 -----
 fs/nfsd/nfssvc.c  |  59 ++------------------------
 fs/nfsd/xdr.h     |   6 ---
 4 files changed, 23 insertions(+), 159 deletions(-)

diff --git a/fs/nfsd/localio.c b/fs/nfsd/localio.c
index 6707eec462e6..dee3872a4552 100644
--- a/fs/nfsd/localio.c
+++ b/fs/nfsd/localio.c
@@ -18,8 +18,6 @@
 #include "netns.h"
 #include "filecache.h"
 #include "cache.h"
-#include "xdr3.h"
-#include "xdr4.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_FH
 
@@ -262,48 +260,39 @@ static __be32 nfsd_proc_null(struct svc_rqst *rqstp)
 	return rpc_success;
 }
 
+struct nfsd_getuuidres {
+	uuid_t			uuid;
+};
+
 static __be32 nfsd_proc_getuuid(struct svc_rqst *rqstp)
 {
 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 	struct nfsd_getuuidres *resp = rqstp->rq_resp;
 
 	uuid_copy(&resp->uuid, &nn->nfsd_uuid.uuid);
-	resp->status = nfs_ok;
 
 	return rpc_success;
 }
 
-#define NFS_getuuid_sz XDR_QUADLEN(UUID_SIZE)
-
 static inline void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len)
 {
 	WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0);
 }
 
-static void encode_uuid(struct xdr_stream *xdr, uuid_t *src_uuid)
+static bool nfslocalio_encode_getuuidres(struct svc_rqst *rqstp,
+				      struct xdr_stream *xdr)
 {
+	struct nfsd_getuuidres *resp = rqstp->rq_resp;
 	u8 uuid[UUID_SIZE];
 
-	export_uuid(uuid, src_uuid);
+	export_uuid(uuid, &resp->uuid);
 	encode_opaque_fixed(xdr, uuid, UUID_SIZE);
 	dprintk("%s: uuid=%pU\n", __func__, uuid);
-}
-
-#if defined(CONFIG_NFSD_V3_LOCALIO)
-static bool nfs3svc_encode_getuuidres(struct svc_rqst *rqstp,
-				      struct xdr_stream *xdr)
-{
-	struct nfsd_getuuidres *resp = rqstp->rq_resp;
-
-	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
-		return false;
-	if (resp->status == nfs_ok)
-		encode_uuid(xdr, &resp->uuid);
 
 	return true;
 }
 
-static const struct svc_procedure nfsd_localio_procedures3[2] = {
+static const struct svc_procedure nfsd_localio_procedures[2] = {
 	[LOCALIOPROC_NULL] = {
 		.pc_func = nfsd_proc_null,
 		.pc_decode = nfssvc_decode_voidarg,
@@ -311,86 +300,29 @@ static const struct svc_procedure nfsd_localio_procedures3[2] = {
 		.pc_argsize = sizeof(struct nfsd_voidargs),
 		.pc_ressize = sizeof(struct nfsd_voidres),
 		.pc_cachetype = RC_NOCACHE,
-		.pc_xdrressize = 1,
+		.pc_xdrressize = 0,
 		.pc_name = "NULL",
 	},
 	[LOCALIOPROC_GETUUID] = {
 		.pc_func = nfsd_proc_getuuid,
 		.pc_decode = nfssvc_decode_voidarg,
-		.pc_encode = nfs3svc_encode_getuuidres,
+		.pc_encode = nfslocalio_encode_getuuidres,
 		.pc_argsize = sizeof(struct nfsd_voidargs),
 		.pc_ressize = sizeof(struct nfsd_getuuidres),
 		.pc_cachetype = RC_NOCACHE,
-		.pc_xdrressize = 1+NFS_getuuid_sz,
+		.pc_xdrressize = XDR_QUADLEN(UUID_SIZE),
 		.pc_name = "GETUUID",
 	},
 };
 
 static DEFINE_PER_CPU_ALIGNED(unsigned long,
-			      nfsd_localio_count3[ARRAY_SIZE(nfsd_localio_procedures3)]);
-const struct svc_version nfsd_localio_version3 = {
-	.vs_vers	= 3,
+			      nfsd_localio_count[ARRAY_SIZE(nfsd_localio_procedures)]);
+const struct svc_version nfsd_localio_version1 = {
+	.vs_vers	= 1,
 	.vs_nproc	= 2,
-	.vs_proc	= nfsd_localio_procedures3,
+	.vs_proc	= nfsd_localio_procedures,
 	.vs_dispatch	= nfsd_dispatch,
-	.vs_count	= nfsd_localio_count3,
-	.vs_xdrsize	= NFS3_SVC_XDRSIZE,
-};
-#endif /* CONFIG_NFSD_V3_LOCALIO */
-
-#if defined(CONFIG_NFSD_V4_LOCALIO)
-static bool nfs4svc_encode_getuuidres(struct svc_rqst *rqstp,
-				      struct xdr_stream *xdr)
-{
-	struct nfsd_getuuidres *resp = rqstp->rq_resp;
-	__be32 *p;
-
-	p = xdr_reserve_space(xdr, 8);
-	if (!p)
-		return 0;
-	*p++ = cpu_to_be32(LOCALIOPROC_GETUUID);
-	*p++ = resp->status;
-
-	if (resp->status == nfs_ok)
-		encode_uuid(xdr, &resp->uuid);
-
-	return 1;
-}
-
-static const struct svc_procedure nfsd_localio_procedures4[2] = {
-	[LOCALIOPROC_NULL] = {
-		.pc_func = nfsd_proc_null,
-		.pc_decode = nfssvc_decode_voidarg,
-		.pc_encode = nfssvc_encode_voidres,
-		.pc_argsize = sizeof(struct nfsd_voidargs),
-		.pc_ressize = sizeof(struct nfsd_voidres),
-		.pc_cachetype = RC_NOCACHE,
-		.pc_xdrressize = 1,
-		.pc_name = "NULL",
-	},
-	[LOCALIOPROC_GETUUID] = {
-		.pc_func = nfsd_proc_getuuid,
-		.pc_decode = nfssvc_decode_voidarg,
-		.pc_encode = nfs4svc_encode_getuuidres,
-		.pc_argsize = sizeof(struct nfsd_voidargs),
-		.pc_ressize = sizeof(struct nfsd_getuuidres),
-		.pc_cachetype = RC_NOCACHE,
-		.pc_xdrressize = 2+NFS_getuuid_sz,
-		.pc_name = "GETUUID",
-	},
-};
-
-static DEFINE_PER_CPU_ALIGNED(unsigned long,
-			      nfsd_localio_count4[ARRAY_SIZE(nfsd_localio_procedures4)]);
-const struct svc_version nfsd_localio_version4 = {
-	.vs_vers	        = 4,
-	.vs_nproc	        = 2,
-	.vs_proc	        = nfsd_localio_procedures4,
-	.vs_dispatch	        = nfsd_dispatch,
-	.vs_count	        = nfsd_localio_count4,
-	.vs_xdrsize	        = NFS4_SVC_XDRSIZE,
-	.vs_rpcb_optnl		= true,
-	.vs_need_cong_ctrl	= true,
-
+	.vs_count	= nfsd_localio_count,
+	.vs_xdrsize	= XDR_QUADLEN(UUID_SIZE),
+	.vs_hidden	= true,
 };
-#endif /* CONFIG_NFSD_V4_LOCALIO */
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 4f51f95df294..cec8697b1cd6 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -143,17 +143,6 @@ extern const struct svc_version nfsd_acl_version3;
 #endif
 #endif
 
-#if defined(CONFIG_NFSD_V3_LOCALIO)
-extern const struct svc_version nfsd_localio_version3;
-#else
-#define nfsd_localio_version3 NULL
-#endif
-#if defined(CONFIG_NFSD_V4_LOCALIO)
-extern const struct svc_version nfsd_localio_version4;
-#else
-#define nfsd_localio_version4 NULL
-#endif
-
 struct nfsd_net;
 
 enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 48bfd3c6d619..bc69a2c90077 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -38,16 +38,6 @@
 atomic_t			nfsd_th_cnt = ATOMIC_INIT(0);
 extern struct svc_program	nfsd_program;
 static int			nfsd(void *vrqstp);
-#if IS_ENABLED(CONFIG_NFSD_LOCALIO)
-static int			nfsd_localio_rpcbind_set(struct net *,
-						     const struct svc_program *,
-						     u32, int,
-						     unsigned short,
-						     unsigned short);
-static __be32			nfsd_localio_init_request(struct svc_rqst *,
-						const struct svc_program *,
-						struct svc_process_info *);
-#endif /* CONFIG_NFSD_LOCALIO */
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 static int			nfsd_acl_rpcbind_set(struct net *,
 						     const struct svc_program *,
@@ -92,16 +82,11 @@ unsigned long	nfsd_drc_max_mem;
 unsigned long	nfsd_drc_mem_used;
 
 #if IS_ENABLED(CONFIG_NFSD_LOCALIO)
+extern const struct svc_version nfsd_localio_version1;
 static const struct svc_version *nfsd_localio_version[] = {
-#if defined(CONFIG_NFSD_V3_LOCALIO)
-	[3] = &nfsd_localio_version3,
-#endif
-#if defined(CONFIG_NFSD_V4_LOCALIO)
-	[4] = &nfsd_localio_version4,
-#endif
+	[1] = &nfsd_localio_version1,
 };
 
-#define NFSD_LOCALIO_MINVERS            3
 #define NFSD_LOCALIO_NRVERS		ARRAY_SIZE(nfsd_localio_version)
 
 static struct svc_program	nfsd_localio_program = {
@@ -111,8 +96,8 @@ static struct svc_program	nfsd_localio_program = {
 	.pg_name		= "nfslocalio",
 	.pg_class		= "nfsd",
 	.pg_authenticate	= &svc_set_client,
-	.pg_init_request	= nfsd_localio_init_request,
-	.pg_rpcbind_set		= nfsd_localio_rpcbind_set,
+	.pg_init_request	= svc_generic_init_request,
+	.pg_rpcbind_set		= svc_generic_rpcbind_set,
 };
 #endif /* CONFIG_NFSD_LOCALIO */
 
@@ -875,42 +860,6 @@ nfsd_svc(int n, int *nthreads, struct net *net, const struct cred *cred, const c
 	return error;
 }
 
-#if IS_ENABLED(CONFIG_NFSD_LOCALIO)
-static bool
-nfsd_support_localio_version(int vers)
-{
-	if (vers >= NFSD_LOCALIO_MINVERS && vers < NFSD_LOCALIO_NRVERS)
-		return nfsd_localio_version[vers] != NULL;
-	return false;
-}
-
-static int
-nfsd_localio_rpcbind_set(struct net *net, const struct svc_program *progp,
-			u32 version, int family, unsigned short proto,
-			unsigned short port)
-{
-	if (!nfsd_support_localio_version(version) ||
-	    !nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST))
-		return 0;
-	return svc_generic_rpcbind_set(net, progp, version, family,
-			proto, port);
-}
-
-static __be32
-nfsd_localio_init_request(struct svc_rqst *rqstp,
-			const struct svc_program *progp,
-			struct svc_process_info *ret)
-{
-	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
-
-	if (likely(nfsd_support_localio_version(rqstp->rq_vers) &&
-	    nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST)))
-		return svc_generic_init_request(rqstp, progp, ret);
-
-	return rpc_prog_unavail;
-}
-#endif /* CONFIG_NFSD_LOCALIO */
-
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 static bool
 nfsd_support_acl_version(int vers)
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index 5714469af597..852f71580bd0 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -5,7 +5,6 @@
 #define LINUX_NFSD_H
 
 #include <linux/vfs.h>
-#include <linux/uuid.h>
 #include "nfsd.h"
 #include "nfsfh.h"
 
@@ -124,11 +123,6 @@ struct nfsd_statfsres {
 	struct kstatfs		stats;
 };
 
-struct nfsd_getuuidres {
-	__be32			status;
-	uuid_t			uuid;
-};
-
 /*
  * Storage requirements for XDR arguments and results.
  */
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] SUNRPC: replace program list with program array
  2024-06-21  4:59 Suggested improvements for localio support NeilBrown
  2024-06-21  4:59 ` [PATCH 1/3] NFS: Simplify Client NFS_LOCALIO_PROGRAM support NeilBrown
  2024-06-21  4:59 ` [PATCH 2/3] NFSD: Simplify server " NeilBrown
@ 2024-06-21  4:59 ` NeilBrown
  2 siblings, 0 replies; 4+ messages in thread
From: NeilBrown @ 2024-06-21  4:59 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: linux-nfs, Jeff Layton, Chuck Lever, Trond Myklebust

From: NeilBrown <neil@brown.name>

A service created with svc_create_pooled() can be given a linked list of
programs and all of these will be served.

Using a linked list makes is cumbersome when there a several programs
that can be optionally selection with CONFIG settings.

So change to use an array with explicit size.  svc_create() is always
passed a single program.  svc_create_pooled() now must be used for
multiple programs.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/nfsd/nfsctl.c           |  2 +-
 fs/nfsd/nfsd.h             |  2 +-
 fs/nfsd/nfssvc.c           | 69 ++++++++++++++++++--------------------
 include/linux/sunrpc/svc.h |  7 ++--
 net/sunrpc/svc.c           | 68 +++++++++++++++++++++----------------
 net/sunrpc/svc_xprt.c      |  2 +-
 net/sunrpc/svcauth_unix.c  |  3 +-
 7 files changed, 80 insertions(+), 73 deletions(-)

diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index e5d2cc74ef77..6fb92bb61c6d 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -2265,7 +2265,7 @@ static __net_init int nfsd_net_init(struct net *net)
 	if (retval)
 		goto out_repcache_error;
 	memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats));
-	nn->nfsd_svcstats.program = &nfsd_program;
+	nn->nfsd_svcstats.program = &nfsd_programs[0];
 	nn->nfsd_versions = NULL;
 	nn->nfsd4_minorversions = NULL;
 	nfsd4_init_leases_net(nn);
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index cec8697b1cd6..c3f7c5957950 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -80,7 +80,7 @@ struct nfsd_genl_rqstp {
 	u32			rq_opnum[NFSD_MAX_OPS_PER_COMPOUND];
 };
 
-extern struct svc_program	nfsd_program;
+extern struct svc_program	nfsd_programs[];
 extern const struct svc_version	nfsd_version2, nfsd_version3, nfsd_version4;
 extern struct mutex		nfsd_mutex;
 extern spinlock_t		nfsd_drc_lock;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index bc69a2c90077..1df9e18c510b 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -36,7 +36,6 @@
 #define NFSDDBG_FACILITY	NFSDDBG_SVC
 
 atomic_t			nfsd_th_cnt = ATOMIC_INIT(0);
-extern struct svc_program	nfsd_program;
 static int			nfsd(void *vrqstp);
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 static int			nfsd_acl_rpcbind_set(struct net *,
@@ -89,16 +88,6 @@ static const struct svc_version *nfsd_localio_version[] = {
 
 #define NFSD_LOCALIO_NRVERS		ARRAY_SIZE(nfsd_localio_version)
 
-static struct svc_program	nfsd_localio_program = {
-	.pg_prog		= NFS_LOCALIO_PROGRAM,
-	.pg_nvers		= NFSD_LOCALIO_NRVERS,
-	.pg_vers		= nfsd_localio_version,
-	.pg_name		= "nfslocalio",
-	.pg_class		= "nfsd",
-	.pg_authenticate	= &svc_set_client,
-	.pg_init_request	= svc_generic_init_request,
-	.pg_rpcbind_set		= svc_generic_rpcbind_set,
-};
 #endif /* CONFIG_NFSD_LOCALIO */
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
@@ -111,23 +100,9 @@ static const struct svc_version *nfsd_acl_version[] = {
 # endif
 };
 
-#define NFSD_ACL_MINVERS            2
+#define NFSD_ACL_MINVERS	2
 #define NFSD_ACL_NRVERS		ARRAY_SIZE(nfsd_acl_version)
 
-static struct svc_program	nfsd_acl_program = {
-#if IS_ENABLED(CONFIG_NFSD_LOCALIO)
-	.pg_next		= &nfsd_localio_program,
-#endif /* CONFIG_NFSD_LOCALIO */
-	.pg_prog		= NFS_ACL_PROGRAM,
-	.pg_nvers		= NFSD_ACL_NRVERS,
-	.pg_vers		= nfsd_acl_version,
-	.pg_name		= "nfsacl",
-	.pg_class		= "nfsd",
-	.pg_authenticate	= &svc_set_client,
-	.pg_init_request	= nfsd_acl_init_request,
-	.pg_rpcbind_set		= nfsd_acl_rpcbind_set,
-};
-
 #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
 
 static const struct svc_version *nfsd_version[] = {
@@ -140,25 +115,44 @@ static const struct svc_version *nfsd_version[] = {
 #endif
 };
 
-#define NFSD_MINVERS    	2
+#define NFSD_MINVERS		2
 #define NFSD_NRVERS		ARRAY_SIZE(nfsd_version)
 
-struct svc_program		nfsd_program = {
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
-	.pg_next		= &nfsd_acl_program,
-#else
-#if IS_ENABLED(CONFIG_NFSD_LOCALIO)
-	.pg_next		= &nfsd_localio_program,
-#endif /* CONFIG_NFSD_LOCALIO */
-#endif
+struct svc_program		nfsd_programs[] = {
+	{
 	.pg_prog		= NFS_PROGRAM,		/* program number */
 	.pg_nvers		= NFSD_NRVERS,		/* nr of entries in nfsd_version */
 	.pg_vers		= nfsd_version,		/* version table */
 	.pg_name		= "nfsd",		/* program name */
 	.pg_class		= "nfsd",		/* authentication class */
-	.pg_authenticate	= &svc_set_client,	/* export authentication */
+	.pg_authenticate	= svc_set_client,	/* export authentication */
 	.pg_init_request	= nfsd_init_request,
 	.pg_rpcbind_set		= nfsd_rpcbind_set,
+	},
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+	{
+	.pg_prog		= NFS_ACL_PROGRAM,
+	.pg_nvers		= NFSD_ACL_NRVERS,
+	.pg_vers		= nfsd_acl_version,
+	.pg_name		= "nfsacl",
+	.pg_class		= "nfsd",
+	.pg_authenticate	= svc_set_client,
+	.pg_init_request	= nfsd_acl_init_request,
+	.pg_rpcbind_set		= nfsd_acl_rpcbind_set,
+	},
+#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
+#if IS_ENABLED(CONFIG_NFSD_LOCALIO)
+	{
+	.pg_prog		= NFS_LOCALIO_PROGRAM,
+	.pg_nvers		= NFSD_LOCALIO_NRVERS,
+	.pg_vers		= nfsd_localio_version,
+	.pg_name		= "nfslocalio",
+	.pg_class		= "nfsd",
+	.pg_authenticate	= svc_set_client,
+	.pg_init_request	= svc_generic_init_request,
+	.pg_rpcbind_set		= svc_generic_rpcbind_set,
+	}
+#endif /* IS_ENABLED(CONFIG_NFSD_LOCALIO) */
 };
 
 bool nfsd_support_version(int vers)
@@ -696,7 +690,8 @@ int nfsd_create_serv(struct net *net)
 	if (nfsd_max_blksize == 0)
 		nfsd_max_blksize = nfsd_get_default_max_blksize();
 	nfsd_reset_versions(nn);
-	serv = svc_create_pooled(&nfsd_program, &nn->nfsd_svcstats,
+	serv = svc_create_pooled(nfsd_programs, ARRAY_SIZE(nfsd_programs),
+				 &nn->nfsd_svcstats,
 				 nfsd_max_blksize, nfsd);
 	if (serv == NULL)
 		return -ENOMEM;
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index a7d0406b9ef5..7c86b1696398 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -66,9 +66,10 @@ enum {
  * We currently do not support more than one RPC program per daemon.
  */
 struct svc_serv {
-	struct svc_program *	sv_program;	/* RPC program */
+	struct svc_program *	sv_programs;	/* RPC programs */
 	struct svc_stat *	sv_stats;	/* RPC statistics */
 	spinlock_t		sv_lock;
+	unsigned int		sv_nprogs;	/* Number of sv_programs */
 	unsigned int		sv_nrthreads;	/* # of server threads */
 	unsigned int		sv_maxconn;	/* max connections allowed or
 						 * '0' causing max to be based
@@ -329,10 +330,9 @@ struct svc_process_info {
 };
 
 /*
- * List of RPC programs on the same transport endpoint
+ * RPC program - an array of these can use the same transport endpoint
  */
 struct svc_program {
-	struct svc_program *	pg_next;	/* other programs (same xprt) */
 	u32			pg_prog;	/* program number */
 	unsigned int		pg_lovers;	/* lowest version */
 	unsigned int		pg_hivers;	/* highest version */
@@ -414,6 +414,7 @@ void		   svc_rqst_release_pages(struct svc_rqst *rqstp);
 void		   svc_rqst_free(struct svc_rqst *);
 void		   svc_exit_thread(struct svc_rqst *);
 struct svc_serv *  svc_create_pooled(struct svc_program *prog,
+				     unsigned int nprog,
 				     struct svc_stat *stats,
 				     unsigned int bufsize,
 				     int (*threadfn)(void *data));
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 965a27806bfd..d9f348aa0672 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -440,10 +440,11 @@ EXPORT_SYMBOL_GPL(svc_rpcb_cleanup);
 
 static int svc_uses_rpcbind(struct svc_serv *serv)
 {
-	struct svc_program	*progp;
-	unsigned int		i;
+	unsigned int		p, i;
+
+	for (p = 0; p < serv->sv_nprogs; p++) {
+		struct svc_program *progp = &serv->sv_programs[p];
 
-	for (progp = serv->sv_program; progp; progp = progp->pg_next) {
 		for (i = 0; i < progp->pg_nvers; i++) {
 			if (progp->pg_vers[i] == NULL)
 				continue;
@@ -480,7 +481,7 @@ __svc_init_bc(struct svc_serv *serv)
  * Create an RPC service
  */
 static struct svc_serv *
-__svc_create(struct svc_program *prog, struct svc_stat *stats,
+__svc_create(struct svc_program *prog, int nprogs, struct svc_stat *stats,
 	     unsigned int bufsize, int npools, int (*threadfn)(void *data))
 {
 	struct svc_serv	*serv;
@@ -491,7 +492,8 @@ __svc_create(struct svc_program *prog, struct svc_stat *stats,
 	if (!(serv = kzalloc(sizeof(*serv), GFP_KERNEL)))
 		return NULL;
 	serv->sv_name      = prog->pg_name;
-	serv->sv_program   = prog;
+	serv->sv_programs  = prog;
+	serv->sv_nprogs    = nprogs;
 	serv->sv_stats     = stats;
 	if (bufsize > RPCSVC_MAXPAYLOAD)
 		bufsize = RPCSVC_MAXPAYLOAD;
@@ -499,17 +501,18 @@ __svc_create(struct svc_program *prog, struct svc_stat *stats,
 	serv->sv_max_mesg  = roundup(serv->sv_max_payload + PAGE_SIZE, PAGE_SIZE);
 	serv->sv_threadfn = threadfn;
 	xdrsize = 0;
-	while (prog) {
-		prog->pg_lovers = prog->pg_nvers-1;
-		for (vers=0; vers<prog->pg_nvers ; vers++)
-			if (prog->pg_vers[vers]) {
-				prog->pg_hivers = vers;
-				if (prog->pg_lovers > vers)
-					prog->pg_lovers = vers;
-				if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
-					xdrsize = prog->pg_vers[vers]->vs_xdrsize;
+	for (i = 0; i < nprogs; i++) {
+		struct svc_program *progp = &prog[i];
+
+		progp->pg_lovers = progp->pg_nvers-1;
+		for (vers = 0; vers < progp->pg_nvers ; vers++)
+			if (progp->pg_vers[vers]) {
+				progp->pg_hivers = vers;
+				if (progp->pg_lovers > vers)
+					progp->pg_lovers = vers;
+				if (progp->pg_vers[vers]->vs_xdrsize > xdrsize)
+					xdrsize = progp->pg_vers[vers]->vs_xdrsize;
 			}
-		prog = prog->pg_next;
 	}
 	serv->sv_xdrsize   = xdrsize;
 	INIT_LIST_HEAD(&serv->sv_tempsocks);
@@ -558,13 +561,14 @@ __svc_create(struct svc_program *prog, struct svc_stat *stats,
 struct svc_serv *svc_create(struct svc_program *prog, unsigned int bufsize,
 			    int (*threadfn)(void *data))
 {
-	return __svc_create(prog, NULL, bufsize, 1, threadfn);
+	return __svc_create(prog, 1, NULL, bufsize, 1, threadfn);
 }
 EXPORT_SYMBOL_GPL(svc_create);
 
 /**
  * svc_create_pooled - Create an RPC service with pooled threads
- * @prog: the RPC program the new service will handle
+ * @prog:  Array of RPC programs the new service will handle
+ * @nprogs: Number of programs in the array
  * @stats: the stats struct if desired
  * @bufsize: maximum message size for @prog
  * @threadfn: a function to service RPC requests for @prog
@@ -572,6 +576,7 @@ EXPORT_SYMBOL_GPL(svc_create);
  * Returns an instantiated struct svc_serv object or NULL.
  */
 struct svc_serv *svc_create_pooled(struct svc_program *prog,
+				   unsigned int nprogs,
 				   struct svc_stat *stats,
 				   unsigned int bufsize,
 				   int (*threadfn)(void *data))
@@ -579,7 +584,7 @@ struct svc_serv *svc_create_pooled(struct svc_program *prog,
 	struct svc_serv *serv;
 	unsigned int npools = svc_pool_map_get();
 
-	serv = __svc_create(prog, stats, bufsize, npools, threadfn);
+	serv = __svc_create(prog, nprogs, stats, bufsize, npools, threadfn);
 	if (!serv)
 		goto out_err;
 	serv->sv_is_pooled = true;
@@ -602,16 +607,16 @@ svc_destroy(struct svc_serv **servp)
 
 	*servp = NULL;
 
-	dprintk("svc: svc_destroy(%s)\n", serv->sv_program->pg_name);
+	dprintk("svc: svc_destroy(%s)\n", serv->sv_programs->pg_name);
 	timer_shutdown_sync(&serv->sv_temptimer);
 
 	/*
 	 * Remaining transports at this point are not expected.
 	 */
 	WARN_ONCE(!list_empty(&serv->sv_permsocks),
-		  "SVC: permsocks remain for %s\n", serv->sv_program->pg_name);
+		  "SVC: permsocks remain for %s\n", serv->sv_programs->pg_name);
 	WARN_ONCE(!list_empty(&serv->sv_tempsocks),
-		  "SVC: tempsocks remain for %s\n", serv->sv_program->pg_name);
+		  "SVC: tempsocks remain for %s\n", serv->sv_programs->pg_name);
 
 	cache_clean_deferred(serv);
 
@@ -1156,15 +1161,16 @@ int svc_register(const struct svc_serv *serv, struct net *net,
 		 const int family, const unsigned short proto,
 		 const unsigned short port)
 {
-	struct svc_program	*progp;
-	unsigned int		i;
+	unsigned int		p, i;
 	int			error = 0;
 
 	WARN_ON_ONCE(proto == 0 && port == 0);
 	if (proto == 0 && port == 0)
 		return -EINVAL;
 
-	for (progp = serv->sv_program; progp; progp = progp->pg_next) {
+	for (p = 0; p < serv->sv_nprogs; p++) {
+		struct svc_program *progp = &serv->sv_programs[p];
+
 		for (i = 0; i < progp->pg_nvers; i++) {
 
 			error = progp->pg_rpcbind_set(net, progp, i,
@@ -1216,13 +1222,14 @@ static void __svc_unregister(struct net *net, const u32 program, const u32 versi
 static void svc_unregister(const struct svc_serv *serv, struct net *net)
 {
 	struct sighand_struct *sighand;
-	struct svc_program *progp;
 	unsigned long flags;
-	unsigned int i;
+	unsigned int p, i;
 
 	clear_thread_flag(TIF_SIGPENDING);
 
-	for (progp = serv->sv_program; progp; progp = progp->pg_next) {
+	for (p = 0; p < serv->sv_nprogs; p++) {
+		struct svc_program *progp = &serv->sv_programs[p];
+
 		for (i = 0; i < progp->pg_nvers; i++) {
 			if (progp->pg_vers[i] == NULL)
 				continue;
@@ -1328,7 +1335,7 @@ svc_process_common(struct svc_rqst *rqstp)
 	struct svc_process_info process;
 	enum svc_auth_status	auth_res;
 	unsigned int		aoffset;
-	int			rc;
+	int			pr, rc;
 	__be32			*p;
 
 	/* Will be turned off only when NFSv4 Sessions are used */
@@ -1352,9 +1359,12 @@ svc_process_common(struct svc_rqst *rqstp)
 	rqstp->rq_vers = be32_to_cpup(p++);
 	rqstp->rq_proc = be32_to_cpup(p);
 
-	for (progp = serv->sv_program; progp; progp = progp->pg_next)
+	for (pr = 0; pr < serv->sv_nprogs; pr++) {
+		progp = &serv->sv_programs[pr];
+
 		if (rqstp->rq_prog == progp->pg_prog)
 			break;
+	}
 
 	/*
 	 * Decode auth data, and add verifier to reply buffer.
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index d3735ab3e6d1..16634afdf253 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -268,7 +268,7 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
 		spin_unlock(&svc_xprt_class_lock);
 		newxprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
 		if (IS_ERR(newxprt)) {
-			trace_svc_xprt_create_err(serv->sv_program->pg_name,
+			trace_svc_xprt_create_err(serv->sv_programs->pg_name,
 						  xcl->xcl_name, sap, len,
 						  newxprt);
 			module_put(xcl->xcl_owner);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 04b45588ae6f..8ca98b146ec8 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -697,7 +697,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
 	rqstp->rq_auth_stat = rpc_autherr_badcred;
 	ipm = ip_map_cached_get(xprt);
 	if (ipm == NULL)
-		ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
+		ipm = __ip_map_lookup(sn->ip_map_cache,
+				      rqstp->rq_server->sv_programs->pg_class,
 				    &sin6->sin6_addr);
 
 	if (ipm == NULL)
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-06-21  5:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-21  4:59 Suggested improvements for localio support NeilBrown
2024-06-21  4:59 ` [PATCH 1/3] NFS: Simplify Client NFS_LOCALIO_PROGRAM support NeilBrown
2024-06-21  4:59 ` [PATCH 2/3] NFSD: Simplify server " NeilBrown
2024-06-21  4:59 ` [PATCH 3/3] SUNRPC: replace program list with program array NeilBrown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox