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---
3name: sunrpc
4protocol: genetlink
5uapi-header: linux/sunrpc_netlink.h
6
7doc: SUNRPC cache upcall support over generic netlink.
8
9definitions:
10 -
11 type: flags
12 name: cache-type
13 entries: [ip_map, unix_gid]
14
15attribute-sets:
16 -
17 name: cache-notify
18 attributes:
19 -
20 name: cache-type
21 type: u32
22 enum: cache-type
23
24operations:
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
35mcast-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
256 struct cache_head **items,256 struct cache_head **items,
257 u64 *seqnos, int max,257 u64 *seqnos, int max,
258 u64 min_seqno);258 u64 min_seqno);
259int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h,
260 u32 cache_type);
259 261
260/* Must store cache_detail in seq_file->private if using next three functions */262/* Must store cache_detail in seq_file->private if using next three functions */
261extern void *cache_seq_start_rcu(struct seq_file *file, loff_t *pos);263extern 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
13enum sunrpc_cache_type {
14 SUNRPC_CACHE_TYPE_IP_MAP = 1,
15 SUNRPC_CACHE_TYPE_UNIX_GID = 2,
16};
17
18enum {
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
25enum {
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
14 addr.o rpcb_clnt.o timer.o xdr.o \14 addr.o rpcb_clnt.o timer.o xdr.o \
15 sunrpc_syms.o cache.o rpc_pipe.o sysfs.o \15 sunrpc_syms.o cache.o rpc_pipe.o sysfs.o \
16 svc_xprt.o \16 svc_xprt.o \
17 xprtmultipath.o17 xprtmultipath.o netlink.o
18sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o18sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o
19sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o19sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o
20sunrpc-$(CONFIG_PROC_FS) += stats.o20sunrpc-$(CONFIG_PROC_FS) += stats.o
net/sunrpc/cache.c+44−0
@@ -33,9 +33,11 @@ · 32 unmodified lines
33#include <linux/sunrpc/cache.h>33#include <linux/sunrpc/cache.h>
34#include <linux/sunrpc/stats.h>34#include <linux/sunrpc/stats.h>
35#include <linux/sunrpc/rpc_pipe_fs.h>35#include <linux/sunrpc/rpc_pipe_fs.h>
36#include <net/genetlink.h>
36#include <trace/events/sunrpc.h>37#include <trace/events/sunrpc.h>
37 38
38#include "netns.h"39#include "netns.h"
40#include "netlink.h"
39#include "fail.h"41#include "fail.h"
40 42
41#define RPCDBG_FACILITY RPCDBG_CACHE43#define RPCDBG_FACILITY RPCDBG_CACHE
@@ -1963,3 +1965,45 @@ int sunrpc_cache_requests_snapshot(struct cache_detail *cd, · 1921 unmodified lines
1963 return i;1965 return i;
1964}1966}
1965EXPORT_SYMBOL_GPL(sunrpc_cache_requests_snapshot);1967EXPORT_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 */
1979int 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}
2009EXPORT_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 */
16static const struct genl_split_ops sunrpc_nl_ops[] = {
17};
18
19static const struct genl_multicast_group sunrpc_nl_mcgrps[] = {
20 [SUNRPC_NLGRP_NONE] = { "none", },
21 [SUNRPC_NLGRP_EXPORTD] = { "exportd", },
22};
23
24struct 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
15enum {
16 SUNRPC_NLGRP_NONE,
17 SUNRPC_NLGRP_EXPORTD,
18};
19
20extern 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
23#include <linux/sunrpc/rpc_pipe_fs.h>23#include <linux/sunrpc/rpc_pipe_fs.h>
24#include <linux/sunrpc/xprtsock.h>24#include <linux/sunrpc/xprtsock.h>
25 25
26#include <net/genetlink.h>
27
26#include "sunrpc.h"28#include "sunrpc.h"
27#include "sysfs.h"29#include "sysfs.h"
28#include "netns.h"30#include "netns.h"
31#include "netlink.h"
29 32
30unsigned int sunrpc_net_id;33unsigned int sunrpc_net_id;
31EXPORT_SYMBOL_GPL(sunrpc_net_id);34EXPORT_SYMBOL_GPL(sunrpc_net_id);
@@ -108,6 +111,10 @@ init_sunrpc(void) · 76 unmodified lines
108 if (err)111 if (err)
109 goto out5;112 goto out5;
110 113
114 err = genl_register_family(&sunrpc_nl_family);
115 if (err)
116 goto out6;
117
111 sunrpc_debugfs_init();118 sunrpc_debugfs_init();
112#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)119#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
113 rpc_register_sysctl();120 rpc_register_sysctl();
@@ -116,6 +123,8 @@ init_sunrpc(void) · 2 unmodified lines
116 init_socket_xprt(); /* clnt sock transport */123 init_socket_xprt(); /* clnt sock transport */
117 return 0;124 return 0;
118 125
126out6:
127 rpc_sysfs_exit();
119out5:128out5:
120 unregister_rpc_pipefs();129 unregister_rpc_pipefs();
121out4:130out4:
@@ -131,6 +140,7 @@ out: · 9 unmodified lines
131static void __exit140static void __exit
132cleanup_sunrpc(void)141cleanup_sunrpc(void)
133{142{
143 genl_unregister_family(&sunrpc_nl_family);
134 rpc_sysfs_exit();144 rpc_sysfs_exit();
135 rpc_cleanup_clids();145 rpc_cleanup_clids();
136 xprt_cleanup_ids();146 xprt_cleanup_ids();