]> www.infradead.org Git - users/hch/dma-mapping.git/commitdiff
rtnetlink: Add bulk registration helpers for rtnetlink message handlers.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Tue, 8 Oct 2024 18:47:32 +0000 (11:47 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 10 Oct 2024 13:39:35 +0000 (15:39 +0200)
Before commit addf9b90de22 ("net: rtnetlink: use rcu to free rtnl message
handlers"), once rtnl_msg_handlers[protocol] was allocated, the following
rtnl_register_module() for the same protocol never failed.

However, after the commit, rtnl_msg_handler[protocol][msgtype] needs to
be allocated in each rtnl_register_module(), so each call could fail.

Many callers of rtnl_register_module() do not handle the returned error,
and we need to add many error handlings.

To handle that easily, let's add wrapper functions for bulk registration
of rtnetlink message handlers.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
include/net/rtnetlink.h
net/core/rtnetlink.c

index b45d57b5968af4d17a1fc002a75a0923aefabf12..2d3eb7cb4dfff0f6f62b2d9a35b433ceaa6c5bfd 100644 (file)
@@ -29,6 +29,15 @@ static inline enum rtnl_kinds rtnl_msgtype_kind(int msgtype)
        return msgtype & RTNL_KIND_MASK;
 }
 
+struct rtnl_msg_handler {
+       struct module *owner;
+       int protocol;
+       int msgtype;
+       rtnl_doit_func doit;
+       rtnl_dumpit_func dumpit;
+       int flags;
+};
+
 void rtnl_register(int protocol, int msgtype,
                   rtnl_doit_func, rtnl_dumpit_func, unsigned int flags);
 int rtnl_register_module(struct module *owner, int protocol, int msgtype,
@@ -36,6 +45,14 @@ int rtnl_register_module(struct module *owner, int protocol, int msgtype,
 int rtnl_unregister(int protocol, int msgtype);
 void rtnl_unregister_all(int protocol);
 
+int __rtnl_register_many(const struct rtnl_msg_handler *handlers, int n);
+void __rtnl_unregister_many(const struct rtnl_msg_handler *handlers, int n);
+
+#define rtnl_register_many(handlers)                           \
+       __rtnl_register_many(handlers, ARRAY_SIZE(handlers))
+#define rtnl_unregister_many(handlers)                         \
+       __rtnl_unregister_many(handlers, ARRAY_SIZE(handlers))
+
 static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
 {
        if (nlmsg_len(nlh) >= sizeof(struct rtgenmsg))
index f0a52098708584aa27461b7ee941fa324adcaf20..e30e7ea0207d0ce82600851c36df0b7fcae64ae4 100644 (file)
@@ -384,6 +384,35 @@ void rtnl_unregister_all(int protocol)
 }
 EXPORT_SYMBOL_GPL(rtnl_unregister_all);
 
+int __rtnl_register_many(const struct rtnl_msg_handler *handlers, int n)
+{
+       const struct rtnl_msg_handler *handler;
+       int i, err;
+
+       for (i = 0, handler = handlers; i < n; i++, handler++) {
+               err = rtnl_register_internal(handler->owner, handler->protocol,
+                                            handler->msgtype, handler->doit,
+                                            handler->dumpit, handler->flags);
+               if (err) {
+                       __rtnl_unregister_many(handlers, i);
+                       break;
+               }
+       }
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(__rtnl_register_many);
+
+void __rtnl_unregister_many(const struct rtnl_msg_handler *handlers, int n)
+{
+       const struct rtnl_msg_handler *handler;
+       int i;
+
+       for (i = n - 1, handler = handlers + n - 1; i >= 0; i--, handler--)
+               rtnl_unregister(handler->protocol, handler->msgtype);
+}
+EXPORT_SYMBOL_GPL(__rtnl_unregister_many);
+
 static LIST_HEAD(link_ops);
 
 static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind)