aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
authorJeff Layton <jlayton@kernel.org>2026-03-25 10:40:33 -0400
committerChuck Lever <chuck.lever@oracle.com>2026-05-28 11:31:26 -0400
commit6ba255c4321f962f03786c5e2d179b076af2cd10 (patch)
tree73827427f13bf4313e2b21b3f3f898343a356357 /net
parente46fb7920a0b4f61caf137a65496eae5607c54c6 (diff)
downloadlinux-next-history-6ba255c4321f962f03786c5e2d179b076af2cd10.tar.gz
sunrpc: add SUNRPC_CMD_CACHE_FLUSH netlink command
Add a new SUNRPC_CMD_CACHE_FLUSH generic netlink command that allows userspace to flush the sunrpc auth caches (ip_map and unix_gid) without writing to /proc/net/rpc/*/flush. An optional SUNRPC_A_CACHE_FLUSH_MASK u32 attribute selects which caches to flush (bit 1 = ip_map, bit 2 = unix_gid). If the attribute is omitted, all sunrpc caches are flushed. This is used by exportfs to replace its /proc-based cache_flush() with a netlink equivalent, with /proc fallback for older kernels. Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/netlink.c12
-rw-r--r--net/sunrpc/netlink.h1
-rw-r--r--net/sunrpc/svcauth_unix.c32
3 files changed, 45 insertions, 0 deletions
diff --git a/net/sunrpc/netlink.c b/net/sunrpc/netlink.c
index 3ac6b0cac5fec..5ccf0967809c4 100644
--- a/net/sunrpc/netlink.c
+++ b/net/sunrpc/netlink.c
@@ -49,6 +49,11 @@ static const struct nla_policy sunrpc_unix_gid_set_reqs_nl_policy[SUNRPC_A_UNIX_
[SUNRPC_A_UNIX_GID_REQS_REQUESTS] = NLA_POLICY_NESTED(sunrpc_unix_gid_nl_policy),
};
+/* SUNRPC_CMD_CACHE_FLUSH - do */
+static const struct nla_policy sunrpc_cache_flush_nl_policy[SUNRPC_A_CACHE_FLUSH_MASK + 1] = {
+ [SUNRPC_A_CACHE_FLUSH_MASK] = NLA_POLICY_MASK(NLA_U32, 0x3),
+};
+
/* Ops table for sunrpc */
static const struct genl_split_ops sunrpc_nl_ops[] = {
{
@@ -79,6 +84,13 @@ static const struct genl_split_ops sunrpc_nl_ops[] = {
.maxattr = SUNRPC_A_UNIX_GID_REQS_REQUESTS,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
+ {
+ .cmd = SUNRPC_CMD_CACHE_FLUSH,
+ .doit = sunrpc_nl_cache_flush_doit,
+ .policy = sunrpc_cache_flush_nl_policy,
+ .maxattr = SUNRPC_A_CACHE_FLUSH_MASK,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
};
static const struct genl_multicast_group sunrpc_nl_mcgrps[] = {
diff --git a/net/sunrpc/netlink.h b/net/sunrpc/netlink.h
index 2aec57d27a586..2c1012303d48b 100644
--- a/net/sunrpc/netlink.h
+++ b/net/sunrpc/netlink.h
@@ -23,6 +23,7 @@ int sunrpc_nl_unix_gid_get_reqs_dumpit(struct sk_buff *skb,
struct netlink_callback *cb);
int sunrpc_nl_unix_gid_set_reqs_doit(struct sk_buff *skb,
struct genl_info *info);
+int sunrpc_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info);
enum {
SUNRPC_NLGRP_NONE,
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 7703523d42461..64a2658faddbe 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -818,6 +818,38 @@ int sunrpc_nl_unix_gid_set_reqs_doit(struct sk_buff *skb,
return ret;
}
+/**
+ * sunrpc_nl_cache_flush_doit - flush sunrpc caches via netlink
+ * @skb: reply buffer
+ * @info: netlink metadata and command arguments
+ *
+ * Flush the ip_map and/or unix_gid caches. If SUNRPC_A_CACHE_FLUSH_MASK
+ * is provided, only flush the caches indicated by the bitmask (bit 1 =
+ * ip_map, bit 2 = unix_gid). If omitted, flush both.
+ *
+ * Return 0 on success or a negative errno.
+ */
+int sunrpc_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info)
+{
+ struct sunrpc_net *sn;
+ u32 mask = ~0U;
+
+ sn = net_generic(genl_info_net(info), sunrpc_net_id);
+
+ if (info->attrs[SUNRPC_A_CACHE_FLUSH_MASK])
+ mask = nla_get_u32(info->attrs[SUNRPC_A_CACHE_FLUSH_MASK]);
+
+ if ((mask & SUNRPC_CACHE_TYPE_IP_MAP) &&
+ sn->ip_map_cache)
+ cache_purge(sn->ip_map_cache);
+
+ if ((mask & SUNRPC_CACHE_TYPE_UNIX_GID) &&
+ sn->unix_gid_cache)
+ cache_purge(sn->unix_gid_cache);
+
+ return 0;
+}
+
static const struct cache_detail unix_gid_cache_template = {
.owner = THIS_MODULE,
.hash_size = GID_HASHMAX,