Linux NFS development
 help / color / mirror / Atom feed
From: Mike Snitzer <snitzer@kernel.org>
To: Anna Schumaker <anna@kernel.org>, Trond Myklebust <trondmy@kernel.org>
Cc: linux-nfs@vger.kernel.org
Subject: [PATCH 2/3] NFS/localio: probe again for LOCALIO when localio_enabled is set to Y
Date: Mon,  2 Nov 2026 16:52:19 -0500	[thread overview]
Message-ID: <20261102215220.16055-3-snitzer@kernel.org> (raw)
In-Reply-To: <20261102215220.16055-1-snitzer@kernel.org>

localio_enabled is checked on every I/O.  Setting it to N sends the next
I/O of every client over the network, and setting it back to Y resumes
LOCALIO for a client that uses it.  But a client that probed while
localio_enabled was N was disabled by the probe, and nothing probes it
again: NFSv3 probes again only when nfs3_localio_probe_throttle is set,
and NFSv4 only after state recovery.  Such a client stays on the network
after localio_enabled is set to Y.

Give localio_enabled a set handler that, on a change from N to Y, queues
a probe for every ready client, in every network namespace, that does not
use LOCALIO.  On the module command line there are no clients yet, and
nothing is probed.

Tested with NFSv3 and NFSv4.2 on a loopback mount: a client mounted with
localio_enabled=N sent its writes over the network, and after
localio_enabled was set to Y it sent none.

Signed-off-by: Mike Snitzer <snitzer@kernel.org>
---
 Documentation/filesystems/nfs/localio.rst |  3 ++
 fs/nfs/localio.c                          | 51 ++++++++++++++++++++++-
 2 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/Documentation/filesystems/nfs/localio.rst b/Documentation/filesystems/nfs/localio.rst
index 79808b37d7457..e8f44332cc806 100644
--- a/Documentation/filesystems/nfs/localio.rst
+++ b/Documentation/filesystems/nfs/localio.rst
@@ -312,6 +312,9 @@ Module Parameters
 /sys/module/nfs/parameters/localio_enabled (bool)
 controls if LOCALIO is enabled, defaults to Y. If client and server are
 local but 'localio_enabled' is set to N then LOCALIO will not be used.
+It is checked on every I/O: setting it to N sends the next I/O of every
+client over the network, and setting it back to Y resumes LOCALIO.  A
+client that probed while it was N is probed again when it is set to Y.
 
 /sys/module/nfs/parameters/localio_O_DIRECT_semantics (bool)
 controls if O_DIRECT extends down to the underlying filesystem, defaults
diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c
index d5859e8c2a2a8..80a496d6fe0d6 100644
--- a/fs/nfs/localio.c
+++ b/fs/nfs/localio.c
@@ -25,6 +25,7 @@
 #include <linux/nfs_xdr.h>
 
 #include "internal.h"
+#include "netns.h"
 #include "pnfs.h"
 #include "nfstrace.h"
 
@@ -55,7 +56,31 @@ struct nfs_local_fsync_ctx {
 };
 
 static bool localio_enabled __read_mostly = true;
-module_param(localio_enabled, bool, 0644);
+
+static void nfs_local_probe_all(void);
+
+/*
+ * localio_enabled is checked on every I/O, so turning it off stops LOCALIO
+ * at once and turning it back on resumes it for clients that use it.  A
+ * client that probed while it was off was disabled, and nothing probes it
+ * again: turning it on probes every client that does not use LOCALIO.
+ */
+static int localio_enabled_set(const char *val, const struct kernel_param *kp)
+{
+	bool was = READ_ONCE(localio_enabled);
+	int ret;
+
+	ret = param_set_bool(val, kp);
+	if (!ret && !was && READ_ONCE(localio_enabled))
+		nfs_local_probe_all();
+	return ret;
+}
+
+static const struct kernel_param_ops localio_enabled_ops = {
+	.set = localio_enabled_set,
+	.get = param_get_bool,
+};
+module_param_cb(localio_enabled, &localio_enabled_ops, &localio_enabled, 0644);
 
 static void nfs_local_do_read(struct nfs_local_kiocb *iocb,
 			      const struct rpc_call_ops *call_ops);
@@ -222,6 +247,30 @@ void nfs_local_probe_async(struct nfs_client *clp)
 }
 EXPORT_SYMBOL_GPL(nfs_local_probe_async);
 
+/* Probe every client, in every namespace, that does not use LOCALIO. */
+static void nfs_local_probe_all(void)
+{
+	struct nfs_client *clp;
+	struct net *net;
+
+	/* Set on the module command line: there are no clients yet. */
+	if (!nfs_net_id)
+		return;
+
+	down_read(&net_rwsem);
+	for_each_net(net) {
+		struct nfs_net *nn = net_generic(net, nfs_net_id);
+
+		spin_lock(&nn->nfs_client_lock);
+		list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link)
+			if (clp->cl_cons_state == NFS_CS_READY &&
+			    !nfs_client_is_local(clp))
+				nfs_local_probe_async(clp);
+		spin_unlock(&nn->nfs_client_lock);
+	}
+	up_read(&net_rwsem);
+}
+
 static inline void nfs_local_file_put(struct nfsd_file *localio)
 {
 	/* nfs_to_nfsd_file_put_local() expects an __rcu pointer
-- 
2.52.0


  parent reply	other threads:[~2026-11-02 21:52 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02 21:52 [PATCH 0/3] NFS/localio: make the LOCALIO probe safe, repeatable and bounded Mike Snitzer
2026-11-02 21:52 ` [PATCH 1/3] NFS/localio: hold the client across an asynchronous LOCALIO probe Mike Snitzer
2026-11-02 21:52 ` Mike Snitzer [this message]
2026-11-02 21:52 ` [PATCH 3/3] NFS/localio: give the LOCALIO probe a short timeout of its own Mike Snitzer
2026-11-06 22:02   ` Anna Schumaker
2026-11-09 15:10     ` Mike Snitzer
2026-11-09 15:57       ` Anna Schumaker

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=20261102215220.16055-3-snitzer@kernel.org \
    --to=snitzer@kernel.org \
    --cc=anna@kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=trondmy@kernel.org \
    /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