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() which mirrors the nfsd_cache_notify()
pattern: check for listeners on the exportd multicast group, build
and send SUNRPC_CMD_CACHE_NOTIFY 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>
---
Documentation/netlink/specs/sunrpc_cache.yaml | 40 ++++++++++++++++
fs/nfsd/netlink.c | 2 +-
include/uapi/linux/sunrpc_netlink.h | 35 ++++++++++++++
net/sunrpc/Makefile | 2 +-
net/sunrpc/netlink.c | 66 +++++++++++++++++++++++++++
net/sunrpc/netlink.h | 25 ++++++++++
net/sunrpc/sunrpc_syms.c | 10 ++++
7 files changed, 178 insertions(+), 2 deletions(-)
diff --git a/Documentation/netlink/specs/sunrpc_cache.yaml b/Documentation/netlink/specs/sunrpc_cache.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f4aa699598bca9ce0215bbc418d9ddcae25c0110
--- /dev/null
+++ b/Documentation/netlink/specs/sunrpc_cache.yaml
@@ -0,0 +1,40 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+---
+name: sunrpc
+protocol: genetlink
+uapi-header: linux/sunrpc_netlink.h
+
+doc: SUNRPC cache upcall support over generic netlink.
+
+definitions:
+ -
+ type: flags
+ name: cache-type
+ entries: [ip_map, unix_gid]
+
+attribute-sets:
+ -
+ name: cache-notify
+ attributes:
+ -
+ name: cache-type
+ type: u32
+ enum: cache-type
+
+operations:
+ list:
+ -
+ name: cache-notify
+ doc: Notification that there are cache requests that need servicing
+ attribute-set: cache-notify
+ mcgrp: exportd
+ event:
+ attributes:
+ - cache-type
+
+mcast-groups:
+ list:
+ -
+ name: none
+ -
+ name: exportd
diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c
index 4e08c1a6b3943cda5b44c2b64bcf3a00173a08db..81c943345d13db849483bf0d6773458115ff0134 100644
--- a/fs/nfsd/netlink.c
+++ b/fs/nfsd/netlink.c
@@ -59,7 +59,7 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
.cmd = NFSD_CMD_THREADS_SET,
.doit = nfsd_nl_threads_set_doit,
.policy = nfsd_threads_set_nl_policy,
- .maxattr = NFSD_A_SERVER_MAX,
+ .maxattr = NFSD_A_SERVER_FH_KEY,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
diff --git a/include/uapi/linux/sunrpc_netlink.h b/include/uapi/linux/sunrpc_netlink.h
new file mode 100644
index 0000000000000000000000000000000000000000..6135d9b3eef155a9192d9710c8c690283ec49073
--- /dev/null
+++ b/include/uapi/linux/sunrpc_netlink.h
@@ -0,0 +1,35 @@
+/* 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 uapi header */
+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
+
+#ifndef _UAPI_LINUX_SUNRPC_NETLINK_H
+#define _UAPI_LINUX_SUNRPC_NETLINK_H
+
+#define SUNRPC_FAMILY_NAME "sunrpc"
+#define SUNRPC_FAMILY_VERSION 1
+
+enum sunrpc_cache_type {
+ SUNRPC_CACHE_TYPE_IP_MAP = 1,
+ SUNRPC_CACHE_TYPE_UNIX_GID = 2,
+};
+
+enum {
+ SUNRPC_A_CACHE_NOTIFY_CACHE_TYPE = 1,
+
+ __SUNRPC_A_CACHE_NOTIFY_MAX,
+ SUNRPC_A_CACHE_NOTIFY_MAX = (__SUNRPC_A_CACHE_NOTIFY_MAX - 1)
+};
+
+enum {
+ SUNRPC_CMD_CACHE_NOTIFY = 1,
+
+ __SUNRPC_CMD_MAX,
+ SUNRPC_CMD_MAX = (__SUNRPC_CMD_MAX - 1)
+};
+
+#define SUNRPC_MCGRP_NONE "none"
+#define SUNRPC_MCGRP_EXPORTD "exportd"
+
+#endif /* _UAPI_LINUX_SUNRPC_NETLINK_H */
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index f89c10fe7e6acc71d47273200d85425a2891a08a..96727df3aa85435a2de63a8483eab9d75d5b3495 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/netlink.c b/net/sunrpc/netlink.c
new file mode 100644
index 0000000000000000000000000000000000000000..e59ee82dfab358fc367045d9f04c394000c812ec
--- /dev/null
+++ b/net/sunrpc/netlink.c
@@ -0,0 +1,66 @@
+// 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),
+};
+
+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(GENLMSG_DEFAULT_SIZE, 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.h b/net/sunrpc/netlink.h
new file mode 100644
index 0000000000000000000000000000000000000000..efb05f87b89513fe738964a1b27637a09f9b88a9
--- /dev/null
+++ b/net/sunrpc/netlink.h
@@ -0,0 +1,25 @@
+/* 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;
+
+int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h,
+ u32 cache_type);
+
+#endif /* _LINUX_SUNRPC_GEN_H */
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index bab6cab2940524a970422b62b3fa4212c61c4f43..ab88ce46afb556cb0a397fe5c9df3901813ad01e 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 @@ init_sunrpc(void)
static void __exit
cleanup_sunrpc(void)
{
+ genl_unregister_family(&sunrpc_nl_family);
rpc_sysfs_exit();
rpc_cleanup_clids();
xprt_cleanup_ids();
--
2.53.0
On 3/16/26 11:14 AM, Jeff Layton wrote:
> diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c
> index 4e08c1a6b3943cda5b44c2b64bcf3a00173a08db..81c943345d13db849483bf0d6773458115ff0134 100644
> --- a/fs/nfsd/netlink.c
> +++ b/fs/nfsd/netlink.c
> @@ -59,7 +59,7 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
> .cmd = NFSD_CMD_THREADS_SET,
> .doit = nfsd_nl_threads_set_doit,
> .policy = nfsd_threads_set_nl_policy,
> - .maxattr = NFSD_A_SERVER_MAX,
> + .maxattr = NFSD_A_SERVER_FH_KEY,
> .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
> },
> {
This hunk is clearly not related to adding "a generic netlink family for
cache upcalls". Should I apply it instead to the appropriate FH-signing
patch, which is still in my nfsd-testing branch?
--
Chuck Lever
On Thu, 2026-03-19 at 15:14 -0400, Chuck Lever wrote:
> On 3/16/26 11:14 AM, Jeff Layton wrote:
>
> > diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c
> > index 4e08c1a6b3943cda5b44c2b64bcf3a00173a08db..81c943345d13db849483bf0d6773458115ff0134 100644
> > --- a/fs/nfsd/netlink.c
> > +++ b/fs/nfsd/netlink.c
> > @@ -59,7 +59,7 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
> > .cmd = NFSD_CMD_THREADS_SET,
> > .doit = nfsd_nl_threads_set_doit,
> > .policy = nfsd_threads_set_nl_policy,
> > - .maxattr = NFSD_A_SERVER_MAX,
> > + .maxattr = NFSD_A_SERVER_FH_KEY,
> > .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
> > },
> > {
>
> This hunk is clearly not related to adding "a generic netlink family for
> cache upcalls". Should I apply it instead to the appropriate FH-signing
> patch, which is still in my nfsd-testing branch?
>
I noticed that too. I think this is due to a change in the ynl tool.
The new way seems more correct since the "*_MAX" value is fluid.
If you wanted, we could just regenerate the files with the new tool and
commit those changes first and then layer the new stuff on top.
--
Jeff Layton <jlayton@kernel.org>
On 3/19/26 3:19 PM, Jeff Layton wrote:
> On Thu, 2026-03-19 at 15:14 -0400, Chuck Lever wrote:
>> On 3/16/26 11:14 AM, Jeff Layton wrote:
>>
>>> diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c
>>> index 4e08c1a6b3943cda5b44c2b64bcf3a00173a08db..81c943345d13db849483bf0d6773458115ff0134 100644
>>> --- a/fs/nfsd/netlink.c
>>> +++ b/fs/nfsd/netlink.c
>>> @@ -59,7 +59,7 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
>>> .cmd = NFSD_CMD_THREADS_SET,
>>> .doit = nfsd_nl_threads_set_doit,
>>> .policy = nfsd_threads_set_nl_policy,
>>> - .maxattr = NFSD_A_SERVER_MAX,
>>> + .maxattr = NFSD_A_SERVER_FH_KEY,
>>> .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
>>> },
>>> {
>>
>> This hunk is clearly not related to adding "a generic netlink family for
>> cache upcalls". Should I apply it instead to the appropriate FH-signing
>> patch, which is still in my nfsd-testing branch?
>>
>
> I noticed that too. I think this is due to a change in the ynl tool.
> The new way seems more correct since the "*_MAX" value is fluid.
>
> If you wanted, we could just regenerate the files with the new tool and
> commit those changes first and then layer the new stuff on top.
I checked the tool, it hasn't changed.
--
Chuck Lever
On 3/19/26 3:20 PM, Chuck Lever wrote:
> On 3/19/26 3:19 PM, Jeff Layton wrote:
>> On Thu, 2026-03-19 at 15:14 -0400, Chuck Lever wrote:
>>> On 3/16/26 11:14 AM, Jeff Layton wrote:
>>>
>>>> diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c
>>>> index 4e08c1a6b3943cda5b44c2b64bcf3a00173a08db..81c943345d13db849483bf0d6773458115ff0134 100644
>>>> --- a/fs/nfsd/netlink.c
>>>> +++ b/fs/nfsd/netlink.c
>>>> @@ -59,7 +59,7 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
>>>> .cmd = NFSD_CMD_THREADS_SET,
>>>> .doit = nfsd_nl_threads_set_doit,
>>>> .policy = nfsd_threads_set_nl_policy,
>>>> - .maxattr = NFSD_A_SERVER_MAX,
>>>> + .maxattr = NFSD_A_SERVER_FH_KEY,
>>>> .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
>>>> },
>>>> {
>>>
>>> This hunk is clearly not related to adding "a generic netlink family for
>>> cache upcalls". Should I apply it instead to the appropriate FH-signing
>>> patch, which is still in my nfsd-testing branch?
>>>
>>
>> I noticed that too. I think this is due to a change in the ynl tool.
>> The new way seems more correct since the "*_MAX" value is fluid.
>>
>> If you wanted, we could just regenerate the files with the new tool and
>> commit those changes first and then layer the new stuff on top.
>
> I checked the tool, it hasn't changed.
I think "NFSD: Add a key for signing filehandles" introduced this
anomaly, so I've gone back to that patch and re-ran the tool. This was
the only change that was generated, so I applied it and pushed it to
nfsd-testing.
--
Chuck Lever
On 3/16/26 11:14 AM, Jeff Layton wrote:
> 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() which mirrors the nfsd_cache_notify()
> pattern: check for listeners on the exportd multicast group, build
> and send SUNRPC_CMD_CACHE_NOTIFY 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>
> ---
> Documentation/netlink/specs/sunrpc_cache.yaml | 40 ++++++++++++++++
> fs/nfsd/netlink.c | 2 +-
> include/uapi/linux/sunrpc_netlink.h | 35 ++++++++++++++
> net/sunrpc/Makefile | 2 +-
> net/sunrpc/netlink.c | 66 +++++++++++++++++++++++++++
> net/sunrpc/netlink.h | 25 ++++++++++
> net/sunrpc/sunrpc_syms.c | 10 ++++
> 7 files changed, 178 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/netlink/specs/sunrpc_cache.yaml b/Documentation/netlink/specs/sunrpc_cache.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..f4aa699598bca9ce0215bbc418d9ddcae25c0110
> --- /dev/null
> +++ b/Documentation/netlink/specs/sunrpc_cache.yaml
> @@ -0,0 +1,40 @@
> +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
> +---
> +name: sunrpc
> +protocol: genetlink
> +uapi-header: linux/sunrpc_netlink.h
> +
> +doc: SUNRPC cache upcall support over generic netlink.
> +
> +definitions:
> + -
> + type: flags
> + name: cache-type
> + entries: [ip_map, unix_gid]
> +
> +attribute-sets:
> + -
> + name: cache-notify
> + attributes:
> + -
> + name: cache-type
> + type: u32
> + enum: cache-type
> +
> +operations:
> + list:
> + -
> + name: cache-notify
> + doc: Notification that there are cache requests that need servicing
> + attribute-set: cache-notify
> + mcgrp: exportd
> + event:
> + attributes:
> + - cache-type
> +
> +mcast-groups:
> + list:
> + -
> + name: none
> + -
> + name: exportd
> diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c
> index 4e08c1a6b3943cda5b44c2b64bcf3a00173a08db..81c943345d13db849483bf0d6773458115ff0134 100644
> --- a/fs/nfsd/netlink.c
> +++ b/fs/nfsd/netlink.c
> @@ -59,7 +59,7 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
> .cmd = NFSD_CMD_THREADS_SET,
> .doit = nfsd_nl_threads_set_doit,
> .policy = nfsd_threads_set_nl_policy,
> - .maxattr = NFSD_A_SERVER_MAX,
> + .maxattr = NFSD_A_SERVER_FH_KEY,
> .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
> },
> {
> diff --git a/include/uapi/linux/sunrpc_netlink.h b/include/uapi/linux/sunrpc_netlink.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..6135d9b3eef155a9192d9710c8c690283ec49073
> --- /dev/null
> +++ b/include/uapi/linux/sunrpc_netlink.h
> @@ -0,0 +1,35 @@
> +/* 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 uapi header */
> +/* To regenerate run: tools/net/ynl/ynl-regen.sh */
> +
> +#ifndef _UAPI_LINUX_SUNRPC_NETLINK_H
> +#define _UAPI_LINUX_SUNRPC_NETLINK_H
> +
> +#define SUNRPC_FAMILY_NAME "sunrpc"
> +#define SUNRPC_FAMILY_VERSION 1
> +
> +enum sunrpc_cache_type {
> + SUNRPC_CACHE_TYPE_IP_MAP = 1,
> + SUNRPC_CACHE_TYPE_UNIX_GID = 2,
> +};
> +
> +enum {
> + SUNRPC_A_CACHE_NOTIFY_CACHE_TYPE = 1,
> +
> + __SUNRPC_A_CACHE_NOTIFY_MAX,
> + SUNRPC_A_CACHE_NOTIFY_MAX = (__SUNRPC_A_CACHE_NOTIFY_MAX - 1)
> +};
> +
> +enum {
> + SUNRPC_CMD_CACHE_NOTIFY = 1,
> +
> + __SUNRPC_CMD_MAX,
> + SUNRPC_CMD_MAX = (__SUNRPC_CMD_MAX - 1)
> +};
> +
> +#define SUNRPC_MCGRP_NONE "none"
> +#define SUNRPC_MCGRP_EXPORTD "exportd"
> +
> +#endif /* _UAPI_LINUX_SUNRPC_NETLINK_H */
> diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
> index f89c10fe7e6acc71d47273200d85425a2891a08a..96727df3aa85435a2de63a8483eab9d75d5b3495 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/netlink.c b/net/sunrpc/netlink.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..e59ee82dfab358fc367045d9f04c394000c812ec
> --- /dev/null
> +++ b/net/sunrpc/netlink.c
> @@ -0,0 +1,66 @@
> +// 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),
> +};
> +
> +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(GENLMSG_DEFAULT_SIZE, 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);
Is sunrpc_cache_notify() hand-written? If it is, can you find another
initial landing place for it (I think it is moved out in a later patch)?
> diff --git a/net/sunrpc/netlink.h b/net/sunrpc/netlink.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..efb05f87b89513fe738964a1b27637a09f9b88a9
> --- /dev/null
> +++ b/net/sunrpc/netlink.h
> @@ -0,0 +1,25 @@
> +/* 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;
> +
> +int sunrpc_cache_notify(struct cache_detail *cd, struct cache_head *h,
> + u32 cache_type);
Ditto...
> +
> +#endif /* _LINUX_SUNRPC_GEN_H */
> diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
> index bab6cab2940524a970422b62b3fa4212c61c4f43..ab88ce46afb556cb0a397fe5c9df3901813ad01e 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 @@ init_sunrpc(void)
> static void __exit
> cleanup_sunrpc(void)
> {
> + genl_unregister_family(&sunrpc_nl_family);
> rpc_sysfs_exit();
> rpc_cleanup_clids();
> xprt_cleanup_ids();
>
--
Chuck Lever
© 2016 - 2026 Red Hat, Inc.