From: Mike Snitzer <snitzer@kernel.org>
To: linux-nfs@vger.kernel.org
Cc: Jeff Layton <jlayton@kernel.org>,
Chuck Lever <chuck.lever@oracle.com>,
Trond Myklebust <trondmy@hammerspace.com>,
NeilBrown <neilb@suse.de>,
snitzer@hammerspace.com
Subject: [PATCH v6 12/18] nfsd: implement v3 and v4 server support for NFS_LOCALIO_PROGRAM
Date: Wed, 19 Jun 2024 16:40:26 -0400 [thread overview]
Message-ID: <20240619204032.93740-13-snitzer@kernel.org> (raw)
In-Reply-To: <20240619204032.93740-1-snitzer@kernel.org>
LOCALIOPROC_GETUUID encodes the server's uuid_t in terms of the fixed
UUID_SIZE (16). The fixed size opaque encode and decode XDR methods
are used instead of the less efficient variable sized methods.
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
---
fs/nfsd/localio.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++
fs/nfsd/nfsd.h | 11 ++++
fs/nfsd/nfssvc.c | 80 ++++++++++++++++++++++++-
fs/nfsd/xdr.h | 6 ++
4 files changed, 244 insertions(+), 1 deletion(-)
diff --git a/fs/nfsd/localio.c b/fs/nfsd/localio.c
index f6df66b1d523..46b66e43b81b 100644
--- a/fs/nfsd/localio.c
+++ b/fs/nfsd/localio.c
@@ -17,6 +17,9 @@
#include "vfs.h"
#include "netns.h"
#include "filecache.h"
+#include "cache.h"
+#include "xdr3.h"
+#include "xdr4.h"
#define NFSDDBG_FACILITY NFSDDBG_FH
@@ -249,3 +252,148 @@ EXPORT_SYMBOL_GPL(nfsd_open_local_fh);
/* Compile time type checking, not used by anything */
static nfs_to_nfsd_open_t __maybe_unused nfsd_open_local_fh_typecheck = nfsd_open_local_fh;
+
+/*
+ * GETUUID XDR encode functions
+ */
+
+static __be32 nfsd_proc_null(struct svc_rqst *rqstp)
+{
+ return rpc_success;
+}
+
+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)
+{
+ u8 uuid[UUID_SIZE];
+
+ export_uuid(uuid, src_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;
+}
+
+#define ST 1 /* status */
+#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
+
+static const struct svc_procedure nfsd_localio_procedures3[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 = nfs3svc_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_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,
+ .vs_nproc = 2,
+ .vs_proc = nfsd_localio_procedures3,
+ .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,
+
+};
+#endif /* CONFIG_NFSD_V4_LOCALIO */
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index cec8697b1cd6..4f51f95df294 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -143,6 +143,17 @@ 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 a477d2c5088a..48bfd3c6d619 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -38,6 +38,16 @@
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 *,
@@ -81,6 +91,31 @@ DEFINE_SPINLOCK(nfsd_drc_lock);
unsigned long nfsd_drc_max_mem;
unsigned long nfsd_drc_mem_used;
+#if IS_ENABLED(CONFIG_NFSD_LOCALIO)
+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
+};
+
+#define NFSD_LOCALIO_MINVERS 3
+#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 = nfsd_localio_init_request,
+ .pg_rpcbind_set = nfsd_localio_rpcbind_set,
+};
+#endif /* CONFIG_NFSD_LOCALIO */
+
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
static const struct svc_version *nfsd_acl_version[] = {
# if defined(CONFIG_NFSD_V2_ACL)
@@ -95,6 +130,9 @@ static const struct svc_version *nfsd_acl_version[] = {
#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,
@@ -123,6 +161,10 @@ static const struct svc_version *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
.pg_prog = NFS_PROGRAM, /* program number */
.pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
@@ -833,6 +875,42 @@ 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)
@@ -975,7 +1053,7 @@ nfsd(void *vrqstp)
}
/**
- * nfsd_dispatch - Process an NFS or NFSACL Request
+ * nfsd_dispatch - Process an NFS or NFSACL or NFSLOCALIO Request
* @rqstp: incoming request
*
* This RPC dispatcher integrates the NFS server's duplicate reply cache.
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index 852f71580bd0..5714469af597 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -5,6 +5,7 @@
#define LINUX_NFSD_H
#include <linux/vfs.h>
+#include <linux/uuid.h>
#include "nfsd.h"
#include "nfsfh.h"
@@ -123,6 +124,11 @@ struct nfsd_statfsres {
struct kstatfs stats;
};
+struct nfsd_getuuidres {
+ __be32 status;
+ uuid_t uuid;
+};
+
/*
* Storage requirements for XDR arguments and results.
*/
--
2.44.0
next prev parent reply other threads:[~2024-06-19 20:40 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-19 20:40 [PATCH v6 00/18] nfs/nfsd: add support for localio Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 01/18] nfs: pass nfs_client to nfs_initiate_pgio Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 02/18] nfs: pass descriptor thru nfs_initiate_pgio path Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 03/18] nfs: pass struct file to nfs_init_pgio and nfs_init_commit Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 04/18] sunrpc: add rpcauth_map_to_svc_cred_local Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 05/18] nfs_common: add NFS LOCALIO auxiliary protocol enablement Mike Snitzer
2024-06-21 4:43 ` Jeff Johnson
2024-06-19 20:40 ` [PATCH v6 06/18] nfs/nfsd: add "localio" support Mike Snitzer
2024-06-21 6:08 ` NeilBrown
2024-06-21 23:28 ` Mike Snitzer
2024-06-23 22:27 ` NeilBrown
2024-06-25 4:59 ` Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 07/18] nfsd/localio: manage netns reference in nfsd_open_local_fh Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 08/18] NFS: Enable localio for non-pNFS I/O Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 09/18] pnfs/flexfiles: Enable localio for flexfiles I/O Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 10/18] nfs/localio: use dedicated workqueues for filesystem read and write Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 11/18] nfs: implement v3 and v4 client support for NFS_LOCALIO_PROGRAM Mike Snitzer
2024-06-19 20:40 ` Mike Snitzer [this message]
2024-06-19 20:40 ` [PATCH v6 13/18] nfs/nfsd: consolidate {encode,decode}_opaque_fixed in nfs_xdr.h Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 14/18] nfsd: prepare to use SRCU to dereference nn->nfsd_serv Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 15/18] nfsd: " Mike Snitzer
2024-06-21 6:35 ` NeilBrown
2024-06-21 23:58 ` Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 16/18] nfsd/localio: use SRCU to dereference nn->nfsd_serv in nfsd_open_local_fh Mike Snitzer
2024-06-19 20:40 ` [PATCH v6 17/18] nfs: add Documentation/filesystems/nfs/localio.rst Mike Snitzer
2024-06-20 13:52 ` Chuck Lever
2024-06-20 14:33 ` Mike Snitzer
2024-06-20 14:45 ` Chuck Lever
2024-06-20 22:12 ` NeilBrown
2024-06-20 22:35 ` Mike Snitzer
2024-06-20 23:28 ` Chuck Lever
2024-06-20 23:42 ` NeilBrown
2024-06-21 0:30 ` Mike Snitzer
2024-06-21 0:38 ` Mike Snitzer
2024-06-21 0:28 ` Mike Snitzer
2024-06-21 2:18 ` Chuck Lever III
2024-06-19 20:40 ` [PATCH v6 18/18] nfs/nfsd: add Kconfig options to allow localio to be enabled Mike Snitzer
2024-06-20 5:04 ` [PATCH v6 00/18] nfs/nfsd: add support for localio Mike Snitzer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240619204032.93740-13-snitzer@kernel.org \
--to=snitzer@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@suse.de \
--cc=snitzer@hammerspace.com \
--cc=trondmy@hammerspace.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox