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 v3 13/18] nfs/localio: move managing nfsd_open_local_fh symbol to nfs_common
Date: Thu, 13 Jun 2024 23:44:21 -0400 [thread overview]
Message-ID: <20240614034426.31043-14-snitzer@kernel.org> (raw)
In-Reply-To: <20240614034426.31043-1-snitzer@kernel.org>
Get nfsd_open_local_fh and store it in rpc_client during client
creation, put the symbol during nfs_local_disable -- which is also
called during client destruction.
Eliminates the need for nfs_local_open_ctx and extra locking and
refcounting work in fs/nfs/localio.c
Also makes it so the reference to the nfsd_open_local_fh symbol is
managed by the nfs_common module instead of the nfs client modules.
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
---
fs/nfs/client.c | 1 +
fs/nfs/inode.c | 1 -
fs/nfs/internal.h | 15 ++++---
fs/nfs/localio.c | 86 +++-----------------------------------
fs/nfs_common/nfslocalio.c | 26 ++++++++++++
include/linux/nfs.h | 4 --
include/linux/nfs_fs_sb.h | 2 +
include/linux/nfslocalio.h | 8 ++++
8 files changed, 52 insertions(+), 91 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 7044b8b3b332..cbabcdf3d785 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -171,6 +171,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
INIT_LIST_HEAD(&clp->cl_superblocks);
clp->cl_rpcclient = clp->cl_rpcclient_localio = ERR_PTR(-EINVAL);
+ clp->nfsd_open_local_fh = NULL;
clp->cl_flags = cl_init->init_flags;
clp->cl_proto = cl_init->proto;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 58be75294a23..aac8c5302503 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -2518,7 +2518,6 @@ static int __init init_nfs_fs(void)
if (err)
goto out1;
- nfs_local_init();
err = register_nfs_fs();
if (err)
goto out0;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index aed826cdb7a7..1c82f764cffa 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -472,15 +472,21 @@ nfs_init_localioclient(struct nfs_client *clp,
if (IS_ERR(clp->cl_rpcclient_localio))
goto out;
/* No errors! Assume that localio is supported */
+ clp->nfsd_open_local_fh = get_nfsd_open_local_fh();
+ if (!clp->nfsd_open_local_fh) {
+ rpc_shutdown_client(clp->cl_rpcclient_localio);
+ clp->cl_rpcclient_localio = ERR_PTR(-EINVAL);
+ goto out;
+ }
supported = true;
out:
- dfprintk_rcu(CLIENT, "%s: server (%s) %s NFS v%u LOCALIO\n", __func__,
- rpc_peeraddr2str(clp->cl_rpcclient_localio, RPC_DISPLAY_ADDR),
- (supported ? "supports" : "does not support"), vers);
+ dfprintk_rcu(CLIENT, "%s: server (%s) %s NFS v%u LOCALIO, nfsd_open_local_fh is %s.\n",
+ __func__, rpc_peeraddr2str(clp->cl_rpcclient_localio, RPC_DISPLAY_ADDR),
+ (supported ? "supports" : "does not support"), vers,
+ (clp->nfsd_open_local_fh ? "set" : "not set"));
}
/* localio.c */
-extern void nfs_local_init(void);
extern void nfs_local_disable(struct nfs_client *);
extern void nfs_local_probe(struct nfs_client *);
extern struct file *nfs_local_open_fh(struct nfs_client *, const struct cred *,
@@ -497,7 +503,6 @@ extern int nfs_local_commit(struct file *, struct nfs_commit_data *,
extern bool nfs_server_is_local(const struct nfs_client *clp);
#else
-static inline void nfs_local_init(void) {}
static inline void nfs_local_disable(struct nfs_client *clp) {}
static inline void nfs_local_probe(struct nfs_client *clp) {}
static inline struct file *nfs_local_open_fh(struct nfs_client *clp,
diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c
index c6ad31afe6a1..6c67d83427c0 100644
--- a/fs/nfs/localio.c
+++ b/fs/nfs/localio.c
@@ -29,26 +29,6 @@
#define NFSDBG_FACILITY NFSDBG_VFS
-extern int nfsd_open_local_fh(struct rpc_clnt *rpc_clnt,
- const struct cred *cred,
- const struct nfs_fh *nfs_fh, const fmode_t fmode,
- struct file **pfilp);
-/*
- * The localio code needs to call into nfsd to do the filehandle -> struct path
- * mapping, but cannot be statically linked, because that will make the nfs
- * module depend on the nfsd module.
- *
- * Instead, do dynamic linking to the nfsd module. This way the nfs module
- * will only hold a reference on nfsd when it's actually in use. This also
- * allows some sanity checking, like giving up on localio if nfsd isn't loaded.
- */
-
-struct nfs_local_open_ctx {
- spinlock_t lock;
- nfs_to_nfsd_open_t open_f;
- atomic_t refcount;
-};
-
struct nfs_local_kiocb {
struct kiocb kiocb;
struct bio_vec *bvec;
@@ -141,8 +121,6 @@ nfs4errno(int errno)
return NFS4ERR_SERVERFAULT;
}
-static struct nfs_local_open_ctx __local_open_ctx __read_mostly;
-
static bool localio_enabled __read_mostly = true;
module_param(localio_enabled, bool, 0644);
@@ -157,65 +135,12 @@ bool nfs_server_is_local(const struct nfs_client *clp)
}
EXPORT_SYMBOL_GPL(nfs_server_is_local);
-void
-nfs_local_init(void)
-{
- struct nfs_local_open_ctx *ctx = &__local_open_ctx;
-
- ctx->open_f = NULL;
- spin_lock_init(&ctx->lock);
- atomic_set(&ctx->refcount, 0);
-}
-
-static bool
-nfs_local_get_lookup_ctx(void)
-{
- struct nfs_local_open_ctx *ctx = &__local_open_ctx;
- nfs_to_nfsd_open_t fn = NULL;
-
- spin_lock(&ctx->lock);
- if (ctx->open_f == NULL) {
- spin_unlock(&ctx->lock);
-
- fn = symbol_request(nfsd_open_local_fh);
- if (!fn)
- return false;
-
- spin_lock(&ctx->lock);
- /* catch race */
- if (ctx->open_f == NULL) {
- ctx->open_f = fn;
- fn = NULL;
- }
- }
- atomic_inc(&ctx->refcount);
- spin_unlock(&ctx->lock);
- if (fn)
- symbol_put(nfsd_open_local_fh);
- return true;
-}
-
-static void
-nfs_local_put_lookup_ctx(void)
-{
- struct nfs_local_open_ctx *ctx = &__local_open_ctx;
- nfs_to_nfsd_open_t fn;
-
- if (atomic_dec_and_lock(&ctx->refcount, &ctx->lock)) {
- fn = ctx->open_f;
- ctx->open_f = NULL;
- spin_unlock(&ctx->lock);
- if (fn)
- symbol_put(nfsd_open_local_fh);
- }
-}
-
/*
* nfs_local_enable - attempt to enable local i/o for an nfs_client
*/
static void nfs_local_enable(struct nfs_client *clp)
{
- if (nfs_local_get_lookup_ctx()) {
+ if (READ_ONCE(clp->nfsd_open_local_fh)) {
set_bit(NFS_CS_LOCAL_IO, &clp->cl_flags);
trace_nfs_local_enable(clp);
}
@@ -224,12 +149,12 @@ static void nfs_local_enable(struct nfs_client *clp)
/*
* nfs_local_disable - disable local i/o for an nfs_client
*/
-void
-nfs_local_disable(struct nfs_client *clp)
+void nfs_local_disable(struct nfs_client *clp)
{
if (test_and_clear_bit(NFS_CS_LOCAL_IO, &clp->cl_flags)) {
trace_nfs_local_disable(clp);
- nfs_local_put_lookup_ctx();
+ put_nfsd_open_local_fh();
+ clp->nfsd_open_local_fh = NULL;
if (!IS_ERR(clp->cl_rpcclient_localio)) {
rpc_shutdown_client(clp->cl_rpcclient_localio);
clp->cl_rpcclient_localio = ERR_PTR(-EINVAL);
@@ -318,14 +243,13 @@ struct file *
nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
struct nfs_fh *fh, const fmode_t mode)
{
- struct nfs_local_open_ctx *ctx = &__local_open_ctx;
struct file *filp;
int status;
if (mode & ~(FMODE_READ | FMODE_WRITE))
return ERR_PTR(-EINVAL);
- status = ctx->open_f(clp->cl_rpcclient, cred, fh, mode, &filp);
+ status = clp->nfsd_open_local_fh(clp->cl_rpcclient, cred, fh, mode, &filp);
if (status < 0) {
dprintk("%s: open local file failed error=%d\n",
__func__, status);
diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c
index f214cc6754a1..c454c4100976 100644
--- a/fs/nfs_common/nfslocalio.c
+++ b/fs/nfs_common/nfslocalio.c
@@ -40,3 +40,29 @@ bool nfsd_uuid_is_local(const uuid_t *uuid)
return !uuid_is_null(nfsd_uuid);
}
EXPORT_SYMBOL_GPL(nfsd_uuid_is_local);
+
+/*
+ * The nfs localio code needs to call into nfsd to do the filehandle -> struct path
+ * mapping, but cannot be statically linked, because that will make the nfs module
+ * depend on the nfsd module.
+ *
+ * Instead, do dynamic linking to the nfsd module (via nfs_common module). The
+ * nfs_common module will only hold a reference on nfsd when localio is in use.
+ * This allows some sanity checking, like giving up on localio if nfsd isn't loaded.
+ */
+
+extern int nfsd_open_local_fh(struct rpc_clnt *rpc_clnt,
+ const struct cred *cred, const struct nfs_fh *nfs_fh,
+ const fmode_t fmode, struct file **pfilp);
+
+nfs_to_nfsd_open_t get_nfsd_open_local_fh(void)
+{
+ return symbol_request(nfsd_open_local_fh);
+}
+EXPORT_SYMBOL_GPL(get_nfsd_open_local_fh);
+
+void put_nfsd_open_local_fh(void)
+{
+ symbol_put(nfsd_open_local_fh);
+}
+EXPORT_SYMBOL_GPL(put_nfsd_open_local_fh);
diff --git a/include/linux/nfs.h b/include/linux/nfs.h
index 2dacfe9742c6..64ed672a0b34 100644
--- a/include/linux/nfs.h
+++ b/include/linux/nfs.h
@@ -48,10 +48,6 @@ enum nfs3_stable_how {
NFS_INVALID_STABLE_HOW = -1
};
-typedef int (*nfs_to_nfsd_open_t)(struct rpc_clnt *, const struct cred *,
- const struct nfs_fh *, const fmode_t,
- struct file **);
-
#ifdef CONFIG_CRC32
/**
* nfs_fhandle_hash - calculate the crc32 hash for the filehandle
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index efcdb4d8e9de..f5760b05ec87 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -8,6 +8,7 @@
#include <linux/wait.h>
#include <linux/nfs_xdr.h>
#include <linux/sunrpc/xprt.h>
+#include <linux/nfslocalio.h>
#include <linux/atomic.h>
#include <linux/refcount.h>
@@ -131,6 +132,7 @@ struct nfs_client {
struct timespec64 cl_nfssvc_boot;
seqlock_t cl_boot_lock;
struct rpc_clnt * cl_rpcclient_localio; /* localio RPC client handle */
+ nfs_to_nfsd_open_t nfsd_open_local_fh;
};
/*
diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h
index d0bbacd0adcf..b8df1b9f248d 100644
--- a/include/linux/nfslocalio.h
+++ b/include/linux/nfslocalio.h
@@ -7,6 +7,7 @@
#include <linux/list.h>
#include <linux/uuid.h>
+#include <linux/nfs.h>
/*
* Global list of nfsd_uuid_t instances, add/remove
@@ -26,4 +27,11 @@ typedef struct {
bool nfsd_uuid_is_local(const uuid_t *uuid);
+typedef int (*nfs_to_nfsd_open_t)(struct rpc_clnt *, const struct cred *,
+ const struct nfs_fh *, const fmode_t,
+ struct file **);
+
+nfs_to_nfsd_open_t get_nfsd_open_local_fh(void);
+void put_nfsd_open_local_fh(void);
+
#endif /* __LINUX_NFSLOCALIO_H */
--
2.44.0
next prev parent reply other threads:[~2024-06-14 3:44 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-14 3:44 [PATCH v3 00/18] nfs/nfsd: add support for localio Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 01/18] nfs: pass nfs_client to nfs_initiate_pgio Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 02/18] nfs: pass descriptor thru nfs_initiate_pgio path Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 03/18] nfs: pass struct file to nfs_init_pgio and nfs_init_commit Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 04/18] sunrpc: add rpcauth_map_to_svc_cred_local Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 05/18] nfs_common: add NFS LOCALIO protocol extension enablement Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 06/18] nfs/nfsd: add "localio" support Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 07/18] NFS: for localio don't call filesystem read() and write() routines directly Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 08/18] NFS: Enable localio for non-pNFS I/O Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 09/18] pnfs/flexfiles: Enable localio for flexfiles I/O Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 10/18] nfs: implement v3 and v4 client support for NFS_LOCALIO_PROGRAM Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 11/18] nfsd: implement v3 and v4 server " Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 12/18] nfs/nfsd: consolidate {encode,decode}_opaque_fixed in nfs_xdr.h Mike Snitzer
2024-06-14 3:44 ` Mike Snitzer [this message]
2024-06-14 3:44 ` [PATCH v3 14/18] nfs/nfsd: ensure localio server always uses its network namespace Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 15/18] nfsd/localio: manage netns reference in nfsd_open_local_fh Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 16/18] nfsd: prepare to use SRCU to dereference nn->nfsd_serv Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 17/18] nfsd: " Mike Snitzer
2024-06-14 3:44 ` [PATCH v3 18/18] nfsd/localio: use nfsd_serv_get/put in nfsd_open_local_fh 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=20240614034426.31043-14-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