diff options
| author | Jeff Layton <jlayton@kernel.org> | 2026-03-25 10:40:28 -0400 |
|---|---|---|
| committer | Chuck Lever <chuck.lever@oracle.com> | 2026-05-28 11:31:26 -0400 |
| commit | 1ca10c4eb275e90a487106fdc3cc9f59a43754c4 (patch) | |
| tree | c67e5322f914819448e8758a994e72e7737ac6c9 /net | |
| parent | f64c462a041c5b87c1945eb3f3f6e4fc8035c594 (diff) | |
| download | linux-next-history-1ca10c4eb275e90a487106fdc3cc9f59a43754c4.tar.gz | |
sunrpc: add a generic netlink family for cache upcalls
The auth.unix.ip and auth.unix.gid caches live in the sunrpc module,
so they cannot use the nfsd generic netlink family. Create a new
"sunrpc" generic netlink family with its own "exportd" multicast
group to support cache upcall notifications for sunrpc-resident
caches.
Define a YAML spec (sunrpc_cache.yaml) with a cache-type enum
(ip_map, unix_gid), a cache-notify multicast event, and the
corresponding uapi header.
Implement sunrpc_cache_notify() in cache.c, which checks for
listeners on the exportd multicast group, builds and sends a
SUNRPC_CMD_CACHE_NOTIFY message with the cache-type attribute.
Register/unregister the sunrpc_nl_family in init_sunrpc() and
cleanup_sunrpc().
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/Makefile | 2 | ||||
| -rw-r--r-- | net/sunrpc/cache.c | 44 | ||||
| -rw-r--r-- | net/sunrpc/netlink.c | 34 | ||||
| -rw-r--r-- | net/sunrpc/netlink.h | 22 | ||||
| -rw-r--r-- | net/sunrpc/sunrpc_syms.c | 10 |
5 files changed, 111 insertions, 1 deletions
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile index f89c10fe7e6ac..96727df3aa854 100644 --- a/net/sunrpc/Makefile +++ b/net/sunrpc/Makefile @@ -14,7 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o sysfs.o \ svc_xprt.o \ - xprtmultipath.o + xprtmultipath.o netlink.o sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o sunrpc-$(CONFIG_PROC_FS) += stats.o diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 1ae5469ffe506..305c6e67f0527 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -33,9 +33,11 @@ #include <linux/sunrpc/cache.h> #include <linux/sunrpc/stats.h> #include <linux/sunrpc/rpc_pipe_fs.h> +#include <net/genetlink.h> #include <trace/events/sunrpc.h> #include "netns.h" +#include "netlink.h" #include "fail.h" #define RPCDBG_FACILITY RPCDBG_CACHE @@ -1960,3 +1962,45 @@ int sunrpc_cache_requests_snapshot(struct cache_detail *cd, return i; } EXPORT_SYMBOL_GPL(sunrpc_cache_requests_snapshot); + +/** + * sunrpc_cache_notify - send a netlink notification for a cache event + * @cd: cache_detail for the cache + * @h: cache_head entry (unused, reserved for future use) + * @cache_type: cache type identifier (e.g. SUNRPC_CACHE_TYPE_UNIX_GID) + * + * Sends a SUNRPC_CMD_CACHE_NOTIFY multicast message on the "exportd" + * group if any listeners are present. Returns 0 on success or a + * negative errno. + */ +int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h, + u32 cache_type) +{ + struct genlmsghdr *hdr; + struct sk_buff *msg; + + if (!genl_has_listeners(&sunrpc_nl_family, cd->net, + SUNRPC_NLGRP_EXPORTD)) + return -ENOLINK; + + msg = genlmsg_new(nla_total_size(sizeof(u32)), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + hdr = genlmsg_put(msg, 0, 0, &sunrpc_nl_family, 0, + SUNRPC_CMD_CACHE_NOTIFY); + if (!hdr) { + nlmsg_free(msg); + return -ENOMEM; + } + + if (nla_put_u32(msg, SUNRPC_A_CACHE_NOTIFY_CACHE_TYPE, cache_type)) { + nlmsg_free(msg); + return -ENOMEM; + } + + genlmsg_end(msg, hdr); + return genlmsg_multicast_netns(&sunrpc_nl_family, cd->net, msg, 0, + SUNRPC_NLGRP_EXPORTD, GFP_KERNEL); +} +EXPORT_SYMBOL_GPL(sunrpc_cache_notify); diff --git a/net/sunrpc/netlink.c b/net/sunrpc/netlink.c new file mode 100644 index 0000000000000..952de6de85e3f --- /dev/null +++ b/net/sunrpc/netlink.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/sunrpc_cache.yaml */ +/* YNL-GEN kernel source */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ + +#include <net/netlink.h> +#include <net/genetlink.h> +#include <linux/sunrpc/cache.h> + +#include "netlink.h" + +#include <uapi/linux/sunrpc_netlink.h> + +/* Ops table for sunrpc */ +static const struct genl_split_ops sunrpc_nl_ops[] = { +}; + +static const struct genl_multicast_group sunrpc_nl_mcgrps[] = { + [SUNRPC_NLGRP_NONE] = { "none", }, + [SUNRPC_NLGRP_EXPORTD] = { "exportd", }, +}; + +struct genl_family sunrpc_nl_family __ro_after_init = { + .name = SUNRPC_FAMILY_NAME, + .version = SUNRPC_FAMILY_VERSION, + .netnsok = true, + .parallel_ops = true, + .module = THIS_MODULE, + .split_ops = sunrpc_nl_ops, + .n_split_ops = ARRAY_SIZE(sunrpc_nl_ops), + .mcgrps = sunrpc_nl_mcgrps, + .n_mcgrps = ARRAY_SIZE(sunrpc_nl_mcgrps), +}; diff --git a/net/sunrpc/netlink.h b/net/sunrpc/netlink.h new file mode 100644 index 0000000000000..74cf5183d745d --- /dev/null +++ b/net/sunrpc/netlink.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/sunrpc_cache.yaml */ +/* YNL-GEN kernel header */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ + +#ifndef _LINUX_SUNRPC_GEN_H +#define _LINUX_SUNRPC_GEN_H + +#include <net/netlink.h> +#include <net/genetlink.h> + +#include <uapi/linux/sunrpc_netlink.h> + +enum { + SUNRPC_NLGRP_NONE, + SUNRPC_NLGRP_EXPORTD, +}; + +extern struct genl_family sunrpc_nl_family; + +#endif /* _LINUX_SUNRPC_GEN_H */ diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index bab6cab294052..ab88ce46afb55 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -23,9 +23,12 @@ #include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/sunrpc/xprtsock.h> +#include <net/genetlink.h> + #include "sunrpc.h" #include "sysfs.h" #include "netns.h" +#include "netlink.h" unsigned int sunrpc_net_id; EXPORT_SYMBOL_GPL(sunrpc_net_id); @@ -108,6 +111,10 @@ init_sunrpc(void) if (err) goto out5; + err = genl_register_family(&sunrpc_nl_family); + if (err) + goto out6; + sunrpc_debugfs_init(); #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) rpc_register_sysctl(); @@ -116,6 +123,8 @@ init_sunrpc(void) init_socket_xprt(); /* clnt sock transport */ return 0; +out6: + rpc_sysfs_exit(); out5: unregister_rpc_pipefs(); out4: @@ -131,6 +140,7 @@ out: static void __exit cleanup_sunrpc(void) { + genl_unregister_family(&sunrpc_nl_family); rpc_sysfs_exit(); rpc_cleanup_clids(); xprt_cleanup_ids(); |
