History

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().

Jeff Layton committed 7 months ago

Commit af81cb21 parent c13ecd48 files · +188 −1Browse files

Unified · Split

8 files
  1. Documentation/netlink/specs/sunrpc_cache.yaml +40 −0
  2. include/linux/sunrpc/cache.h +2 −0
  3. include/uapi/linux/sunrpc_netlink.h +35 −0
  4. net/sunrpc/Makefile +1 −1
  5. net/sunrpc/cache.c +44 −0
  6. net/sunrpc/netlink.c +34 −0
  7. net/sunrpc/netlink.h +22 −0
  8. net/sunrpc/sunrpc_syms.c +10 −0
Documentation/netlink/specs/sunrpc_cache.yaml+40−0
@@ -0,0 +1,40 @@
1+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2+---
3+name: sunrpc
4+protocol: genetlink
5+uapi-header: linux/sunrpc_netlink.h
6+
7+doc: SUNRPC cache upcall support over generic netlink.
8+
9+definitions:
10+ -
11+ type: flags
12+ name: cache-type
13+ entries: [ip_map, unix_gid]
14+
15+attribute-sets:
16+ -
17+ name: cache-notify
18+ attributes:
19+ -
20+ name: cache-type
21+ type: u32
22+ enum: cache-type
23+
24+operations:
25+ list:
26+ -
27+ name: cache-notify
28+ doc: Notification that there are cache requests that need servicing
29+ attribute-set: cache-notify
30+ mcgrp: exportd
31+ event:
32+ attributes:
33+ - cache-type
34+
35+mcast-groups:
36+ list:
37+ -
38+ name: none
39+ -
40+ name: exportd
include/linux/sunrpc/cache.h+2−0
@@ -256,6 +256,8 @@ int sunrpc_cache_requests_snapshot(struct cache_detail *cd, · 255 unmodified lines
256256 struct cache_head **items,
257257 u64 *seqnos, int max,
258258 u64 min_seqno);
259+int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h,
260+ u32 cache_type);
259261
260262 /* Must store cache_detail in seq_file->private if using next three functions */
261263 extern void *cache_seq_start_rcu(struct seq_file *file, loff_t *pos);
include/uapi/linux/sunrpc_netlink.h+35−0
@@ -0,0 +1,35 @@
1+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
2+/* Do not edit directly, auto-generated from: */
3+/* Documentation/netlink/specs/sunrpc_cache.yaml */
4+/* YNL-GEN uapi header */
5+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
6+
7+#ifndef _UAPI_LINUX_SUNRPC_NETLINK_H
8+#define _UAPI_LINUX_SUNRPC_NETLINK_H
9+
10+#define SUNRPC_FAMILY_NAME "sunrpc"
11+#define SUNRPC_FAMILY_VERSION 1
12+
13+enum sunrpc_cache_type {
14+ SUNRPC_CACHE_TYPE_IP_MAP = 1,
15+ SUNRPC_CACHE_TYPE_UNIX_GID = 2,
16+};
17+
18+enum {
19+ SUNRPC_A_CACHE_NOTIFY_CACHE_TYPE = 1,
20+
21+ __SUNRPC_A_CACHE_NOTIFY_MAX,
22+ SUNRPC_A_CACHE_NOTIFY_MAX = (__SUNRPC_A_CACHE_NOTIFY_MAX - 1)
23+};
24+
25+enum {
26+ SUNRPC_CMD_CACHE_NOTIFY = 1,
27+
28+ __SUNRPC_CMD_MAX,
29+ SUNRPC_CMD_MAX = (__SUNRPC_CMD_MAX - 1)
30+};
31+
32+#define SUNRPC_MCGRP_NONE "none"
33+#define SUNRPC_MCGRP_EXPORTD "exportd"
34+
35+#endif /* _UAPI_LINUX_SUNRPC_NETLINK_H */
net/sunrpc/Makefile+1−1
@@ -14,7 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ · 13 unmodified lines
1414 addr.o rpcb_clnt.o timer.o xdr.o \
1515 sunrpc_syms.o cache.o rpc_pipe.o sysfs.o \
1616 svc_xprt.o \
17− xprtmultipath.o
17+ xprtmultipath.o netlink.o
1818 sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o
1919 sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o
2020 sunrpc-$(CONFIG_PROC_FS) += stats.o
net/sunrpc/cache.c+44−0
@@ -33,9 +33,11 @@ · 32 unmodified lines
3333 #include <linux/sunrpc/cache.h>
3434 #include <linux/sunrpc/stats.h>
3535 #include <linux/sunrpc/rpc_pipe_fs.h>
36+#include <net/genetlink.h>
3637 #include <trace/events/sunrpc.h>
3738
3839 #include "netns.h"
40+#include "netlink.h"
3941 #include "fail.h"
4042
4143 #define RPCDBG_FACILITY RPCDBG_CACHE
@@ -1963,3 +1965,45 @@ int sunrpc_cache_requests_snapshot(struct cache_detail *cd, · 1921 unmodified lines
19631965 return i;
19641966 }
19651967 EXPORT_SYMBOL_GPL(sunrpc_cache_requests_snapshot);
1968+
1969+/**
1970+ * sunrpc_cache_notify - send a netlink notification for a cache event
1971+ * @cd: cache_detail for the cache
1972+ * @h: cache_head entry (unused, reserved for future use)
1973+ * @cache_type: cache type identifier (e.g. SUNRPC_CACHE_TYPE_UNIX_GID)
1974+ *
1975+ * Sends a SUNRPC_CMD_CACHE_NOTIFY multicast message on the "exportd"
1976+ * group if any listeners are present. Returns 0 on success or a
1977+ * negative errno.
1978+ */
1979+int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h,
1980+ u32 cache_type)
1981+{
1982+ struct genlmsghdr *hdr;
1983+ struct sk_buff *msg;
1984+
1985+ if (!genl_has_listeners(&sunrpc_nl_family, cd->net,
1986+ SUNRPC_NLGRP_EXPORTD))
1987+ return -ENOLINK;
1988+
1989+ msg = genlmsg_new(nla_total_size(sizeof(u32)), GFP_KERNEL);
1990+ if (!msg)
1991+ return -ENOMEM;
1992+
1993+ hdr = genlmsg_put(msg, 0, 0, &sunrpc_nl_family, 0,
1994+ SUNRPC_CMD_CACHE_NOTIFY);
1995+ if (!hdr) {
1996+ nlmsg_free(msg);
1997+ return -ENOMEM;
1998+ }
1999+
2000+ if (nla_put_u32(msg, SUNRPC_A_CACHE_NOTIFY_CACHE_TYPE, cache_type)) {
2001+ nlmsg_free(msg);
2002+ return -ENOMEM;
2003+ }
2004+
2005+ genlmsg_end(msg, hdr);
2006+ return genlmsg_multicast_netns(&sunrpc_nl_family, cd->net, msg, 0,
2007+ SUNRPC_NLGRP_EXPORTD, GFP_KERNEL);
2008+}
2009+EXPORT_SYMBOL_GPL(sunrpc_cache_notify);
net/sunrpc/netlink.c+34−0
@@ -0,0 +1,34 @@
1+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2+/* Do not edit directly, auto-generated from: */
3+/* Documentation/netlink/specs/sunrpc_cache.yaml */
4+/* YNL-GEN kernel source */
5+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
6+
7+#include <net/netlink.h>
8+#include <net/genetlink.h>
9+#include <linux/sunrpc/cache.h>
10+
11+#include "netlink.h"
12+
13+#include <uapi/linux/sunrpc_netlink.h>
14+
15+/* Ops table for sunrpc */
16+static const struct genl_split_ops sunrpc_nl_ops[] = {
17+};
18+
19+static const struct genl_multicast_group sunrpc_nl_mcgrps[] = {
20+ [SUNRPC_NLGRP_NONE] = { "none", },
21+ [SUNRPC_NLGRP_EXPORTD] = { "exportd", },
22+};
23+
24+struct genl_family sunrpc_nl_family __ro_after_init = {
25+ .name = SUNRPC_FAMILY_NAME,
26+ .version = SUNRPC_FAMILY_VERSION,
27+ .netnsok = true,
28+ .parallel_ops = true,
29+ .module = THIS_MODULE,
30+ .split_ops = sunrpc_nl_ops,
31+ .n_split_ops = ARRAY_SIZE(sunrpc_nl_ops),
32+ .mcgrps = sunrpc_nl_mcgrps,
33+ .n_mcgrps = ARRAY_SIZE(sunrpc_nl_mcgrps),
34+};
net/sunrpc/netlink.h+22−0
@@ -0,0 +1,22 @@
1+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
2+/* Do not edit directly, auto-generated from: */
3+/* Documentation/netlink/specs/sunrpc_cache.yaml */
4+/* YNL-GEN kernel header */
5+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
6+
7+#ifndef _LINUX_SUNRPC_GEN_H
8+#define _LINUX_SUNRPC_GEN_H
9+
10+#include <net/netlink.h>
11+#include <net/genetlink.h>
12+
13+#include <uapi/linux/sunrpc_netlink.h>
14+
15+enum {
16+ SUNRPC_NLGRP_NONE,
17+ SUNRPC_NLGRP_EXPORTD,
18+};
19+
20+extern struct genl_family sunrpc_nl_family;
21+
22+#endif /* _LINUX_SUNRPC_GEN_H */
net/sunrpc/sunrpc_syms.c+10−0
@@ -23,9 +23,12 @@ · 22 unmodified lines
2323 #include <linux/sunrpc/rpc_pipe_fs.h>
2424 #include <linux/sunrpc/xprtsock.h>
2525
26+#include <net/genetlink.h>
27+
2628 #include "sunrpc.h"
2729 #include "sysfs.h"
2830 #include "netns.h"
31+#include "netlink.h"
2932
3033 unsigned int sunrpc_net_id;
3134 EXPORT_SYMBOL_GPL(sunrpc_net_id);
@@ -108,6 +111,10 @@ init_sunrpc(void) · 76 unmodified lines
108111 if (err)
109112 goto out5;
110113
114+ err = genl_register_family(&sunrpc_nl_family);
115+ if (err)
116+ goto out6;
117+
111118 sunrpc_debugfs_init();
112119 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
113120 rpc_register_sysctl();
@@ -116,6 +123,8 @@ init_sunrpc(void) · 2 unmodified lines
116123 init_socket_xprt(); /* clnt sock transport */
117124 return 0;
118125
126+out6:
127+ rpc_sysfs_exit();
119128 out5:
120129 unregister_rpc_pipefs();
121130 out4:
@@ -131,6 +140,7 @@ out: · 9 unmodified lines
131140 static void __exit
132141 cleanup_sunrpc(void)
133142 {
143+ genl_unregister_family(&sunrpc_nl_family);
134144 rpc_sysfs_exit();
135145 rpc_cleanup_clids();
136146 xprt_cleanup_ids();