public inbox for linux-nfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Jeff Layton <jlayton@kernel.org>
To: Steve Dickson <steved@redhat.com>
Cc: Chuck Lever <chuck.lever@oracle.com>, NeilBrown <neil@brown.name>,
	 Olga Kornievskaia <okorniev@redhat.com>,
	Dai Ngo <Dai.Ngo@oracle.com>,  Tom Talpey <tom@talpey.com>,
	Trond Myklebust <trondmy@kernel.org>,
	 Anna Schumaker <anna@kernel.org>,
	linux-nfs@vger.kernel.org,  Jeff Layton <jlayton@kernel.org>
Subject: [PATCH nfs-utils v2 14/16] exportfs: add netlink support for cache flush with /proc fallback
Date: Mon, 30 Mar 2026 09:38:34 -0400	[thread overview]
Message-ID: <20260330-exportd-netlink-v2-14-cc9bd5db2408@kernel.org> (raw)
In-Reply-To: <20260330-exportd-netlink-v2-0-cc9bd5db2408@kernel.org>

Move cache_flush() from support/nfs/cacheio.c to a new file
support/export/cache_flush.c, which has access to libnl.

The new implementation tries netlink first:
- Sends SUNRPC_CMD_CACHE_FLUSH to flush auth.unix.ip and auth.unix.gid
- Sends NFSD_CMD_CACHE_FLUSH to flush nfsd.fh and nfsd.export
- Flushes sunrpc caches before nfsd caches to maintain dependency order

If the sunrpc genl family cannot be resolved (older kernel), falls back
to the original /proc/net/rpc/*/flush write path.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
 support/export/Makefile.am   |   2 +-
 support/export/cache_flush.c | 164 +++++++++++++++++++++++++++++++++++++++++++
 support/nfs/cacheio.c        |  49 +------------
 3 files changed, 166 insertions(+), 49 deletions(-)

diff --git a/support/export/Makefile.am b/support/export/Makefile.am
index ae7ace44112b889f1c461c5473fb1bd42a42f182..33416176c41eb6eadd1880f7c7432b4ca2d8c973 100644
--- a/support/export/Makefile.am
+++ b/support/export/Makefile.am
@@ -12,7 +12,7 @@ EXTRA_DIST	= mount.x
 noinst_LIBRARIES = libexport.a
 libexport_a_SOURCES = client.c export.c hostname.c \
 		      xtab.c mount_clnt.c mount_xdr.c \
-		      cache.c auth.c v4root.c fsloc.c \
+		      cache.c cache_flush.c auth.c v4root.c fsloc.c \
 		      v4clients.c
 libexport_a_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS) -I$(top_srcdir)/support/reexport \
 		       $(LIBNL3_CFLAGS) $(LIBNLGENL3_CFLAGS)
diff --git a/support/export/cache_flush.c b/support/export/cache_flush.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d7f12b212967e5b3d1a2357de07bc3ba5f0b674
--- /dev/null
+++ b/support/export/cache_flush.c
@@ -0,0 +1,164 @@
+/*
+ * support/export/cache_flush.c
+ *
+ * Flush knfsd caches via netlink with /proc fallback.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "nfslib.h"
+#include "xlog.h"
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+
+#ifdef USE_SYSTEM_NFSD_NETLINK_H
+#include <linux/nfsd_netlink.h>
+#else
+#include "nfsd_netlink.h"
+#endif
+
+#ifdef USE_SYSTEM_SUNRPC_NETLINK_H
+#include <linux/sunrpc_netlink.h>
+#else
+#include "sunrpc_netlink.h"
+#endif
+
+static int nl_send_flush(struct nl_sock *sock, int family, int cmd)
+{
+	struct nl_msg *msg;
+	int ret;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	if (!genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family,
+			 0, 0, cmd, 0)) {
+		nlmsg_free(msg);
+		return -ENOMEM;
+	}
+
+	/* No mask attribute = flush all caches in this family */
+	ret = nl_send_auto(sock, msg);
+	if (ret >= 0)
+		ret = nl_wait_for_ack(sock);
+	nlmsg_free(msg);
+	return ret;
+}
+
+static int cache_nl_flush(void)
+{
+	struct nl_sock *sock;
+	int family, ret, val = 1;
+
+	sock = nl_socket_alloc();
+	if (!sock)
+		return -1;
+
+	if (genl_connect(sock)) {
+		nl_socket_free(sock);
+		return -1;
+	}
+
+	setsockopt(nl_socket_get_fd(sock), SOL_NETLINK, NETLINK_EXT_ACK,
+		   &val, sizeof(val));
+
+	/* Flush sunrpc caches first (dependency order) */
+	family = genl_ctrl_resolve(sock, SUNRPC_FAMILY_NAME);
+	if (family < 0) {
+		xlog(D_NETLINK, "sunrpc genl family not found, "
+		     "skipping netlink flush");
+		nl_socket_free(sock);
+		return -1;
+	}
+
+	ret = nl_send_flush(sock, family, SUNRPC_CMD_CACHE_FLUSH);
+	if (ret < 0) {
+		xlog(D_NETLINK, "sunrpc cache flush failed: %d", ret);
+		nl_socket_free(sock);
+		return -1;
+	}
+
+	/* Flush nfsd caches */
+	family = genl_ctrl_resolve(sock, NFSD_FAMILY_NAME);
+	if (family < 0) {
+		xlog(D_NETLINK, "nfsd genl family not found, "
+		     "skipping nfsd cache flush");
+		nl_socket_free(sock);
+		return 0;
+	}
+
+	ret = nl_send_flush(sock, family, NFSD_CMD_CACHE_FLUSH);
+	nl_socket_free(sock);
+	if (ret < 0) {
+		xlog(D_NETLINK, "nfsd cache flush failed: %d", ret);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void cache_proc_flush(void)
+{
+	int c;
+	char stime[32];
+	char path[200];
+	time_t now;
+	/* Note: the order of these caches is important.
+	 * They need to be flushed in dependency order. So
+	 * a cache that references items in another cache,
+	 * as nfsd.fh entries reference items in nfsd.export,
+	 * must be flushed before the cache that it references.
+	 */
+	static char *cachelist[] = {
+		"auth.unix.ip",
+		"auth.unix.gid",
+		"nfsd.fh",
+		"nfsd.export",
+		NULL
+	};
+	now = time(0);
+
+	/* Since v4.16-rc2-3-g3b68e6ee3cbd the timestamp written is ignored.
+	 * It is safest always to flush caches if there is any doubt.
+	 * For earlier kernels, writing the next second from now is
+	 * the best we can do.
+	 */
+	sprintf(stime, "%" PRId64 "\n", (int64_t)now+1);
+	for (c=0; cachelist[c]; c++) {
+		int fd;
+		sprintf(path, "/proc/net/rpc/%s/flush", cachelist[c]);
+		fd = open(path, O_RDWR);
+		if (fd >= 0) {
+			if (write(fd, stime, strlen(stime)) != (ssize_t)strlen(stime)) {
+				xlog_warn("Writing to '%s' failed: errno %d (%s)",
+				path, errno, strerror(errno));
+			}
+			close(fd);
+		}
+	}
+}
+
+void
+cache_flush(void)
+{
+	if (cache_nl_flush() == 0) {
+		xlog(D_NETLINK, "cache flush via netlink succeeded");
+		return;
+	}
+	/* Fallback: /proc path */
+	cache_proc_flush();
+}
diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c
index bd4da0e5ad93f963bf8090062541f34ededd1e03..95eeabbdb978cd227da9877b81e5ed2d65dedaf9 100644
--- a/support/nfs/cacheio.c
+++ b/support/nfs/cacheio.c
@@ -203,51 +203,4 @@ int qword_get_uint(char **bpp, unsigned int *anint)
 	return 0;
 }
 
-/* flush the kNFSd caches.
- * Set the flush time to the mtime of the etab state file or
- * if force, to now.
- * the caches to flush are:
- *  auth.unix.ip nfsd.export nfsd.fh
- */
-
-void
-cache_flush(void)
-{
-	int c;
-	char stime[32];
-	char path[200];
-	time_t now;
-	/* Note: the order of these caches is important.
-	 * They need to be flushed in dependancy order. So
-	 * a cache that references items in another cache,
-	 * as nfsd.fh entries reference items in nfsd.export,
-	 * must be flushed before the cache that it references.
-	 */
-	static char *cachelist[] = {
-		"auth.unix.ip",
-		"auth.unix.gid",
-		"nfsd.fh",
-		"nfsd.export",
-		NULL
-	};
-	now = time(0);
-
-	/* Since v4.16-rc2-3-g3b68e6ee3cbd the timestamp written is ignored.
-	 * It is safest always to flush caches if there is any doubt.
-	 * For earlier kernels, writing the next second from now is
-	 * the best we can do.
-	 */
-	sprintf(stime, "%" PRId64 "\n", (int64_t)now+1);
-	for (c=0; cachelist[c]; c++) {
-		int fd;
-		sprintf(path, "/proc/net/rpc/%s/flush", cachelist[c]);
-		fd = open(path, O_RDWR);
-		if (fd >= 0) {
-			if (write(fd, stime, strlen(stime)) != (ssize_t)strlen(stime)) {
-				xlog_warn("Writing to '%s' failed: errno %d (%s)",
-				path, errno, strerror(errno));
-			}
-			close(fd);
-		}
-	}
-}
+/* cache_flush() has moved to support/export/cache.c for netlink support */

-- 
2.53.0


  parent reply	other threads:[~2026-03-30 13:38 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-30 13:38 [PATCH nfs-utils v2 00/16] exportfs/exportd/mountd: allow them to use netlink for up/downcalls Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 01/16] nfsdctl: move *_netlink.h to support/include/ Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 02/16] support/export: remove unnecessary static variables in nfsd_fh expkey lookup Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 03/16] exportfs: remove obsolete legacy mode documentation from manpage Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 04/16] support/include: update netlink headers for all cache upcalls Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 05/16] build: add libnl3 and netlink header support for exportd and mountd Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 06/16] xlog: claim D_FAC3 as D_NETLINK Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 07/16] exportd/mountd: add netlink support for svc_export cache Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 08/16] exportd/mountd: add netlink support for the nfsd.fh cache Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 09/16] exportd/mountd: add netlink support for the auth.unix.ip cache Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 10/16] exportd/mountd: add netlink support for the auth.unix.gid cache Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 11/16] mountd/exportd: only use /proc interfaces if netlink setup fails Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 12/16] support/export: check for pending requests after opening netlink sockets Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 13/16] exportd/mountd: use cache type from notifications to target scanning Jeff Layton
2026-03-30 13:38 ` Jeff Layton [this message]
2026-03-30 13:38 ` [PATCH nfs-utils v2 15/16] exportfs: use netlink to probe kernel support, skip export_test Jeff Layton
2026-03-30 13:38 ` [PATCH nfs-utils v2 16/16] mountd/exportd/exportfs: add --no-netlink option to disable netlink Jeff Layton
2026-04-03 12:55 ` [PATCH nfs-utils v2 00/16] exportfs/exportd/mountd: allow them to use netlink for up/downcalls Steve Dickson

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=20260330-exportd-netlink-v2-14-cc9bd5db2408@kernel.org \
    --to=jlayton@kernel.org \
    --cc=Dai.Ngo@oracle.com \
    --cc=anna@kernel.org \
    --cc=chuck.lever@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=neil@brown.name \
    --cc=okorniev@redhat.com \
    --cc=steved@redhat.com \
    --cc=tom@talpey.com \
    --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