Skip to content

Commit af81cb2

Browse files
jtlaytonchucklever
authored andcommitted
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>
1 parent c13ecd4 commit af81cb2

8 files changed

Lines changed: 188 additions & 1 deletion

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ int sunrpc_cache_requests_snapshot(struct cache_detail *cd,
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);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@
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,
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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@
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)
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)
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 @@ init_sunrpc(void)
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();

0 commit comments

Comments
 (0)