]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netlink: add a start callback for starting a netlink dump
authorTom Herbert <tom@herbertland.com>
Tue, 15 Dec 2015 23:41:37 +0000 (15:41 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Dec 2017 10:22:49 +0000 (11:22 +0100)
commit fc9e50f5a5a4e1fa9ba2756f745a13e693cf6a06 upstream.

The start callback allows the caller to set up a context for the
dump callbacks. Presumably, the context can then be destroyed in
the done callback.

Signed-off-by: Tom Herbert <tom@herbertland.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/linux/netlink.h
include/net/genetlink.h
net/netlink/af_netlink.c
net/netlink/genetlink.c

index 639e9b8b0e4d9ff2c9b10ce5b44a8a328abe2a31..0b41959aab9f8fa4c5901b3ad054e63746c4b74a 100644 (file)
@@ -131,6 +131,7 @@ netlink_skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
 struct netlink_callback {
        struct sk_buff          *skb;
        const struct nlmsghdr   *nlh;
+       int                     (*start)(struct netlink_callback *);
        int                     (*dump)(struct sk_buff * skb,
                                        struct netlink_callback *cb);
        int                     (*done)(struct netlink_callback *cb);
@@ -153,6 +154,7 @@ struct nlmsghdr *
 __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int flags);
 
 struct netlink_dump_control {
+       int (*start)(struct netlink_callback *);
        int (*dump)(struct sk_buff *skb, struct netlink_callback *);
        int (*done)(struct netlink_callback *);
        void *data;
index 1b6b6dcb018def094a36786bc5cd3d03e26fa453..43c0e771f417ae3c36f4fb7a0390f9569f7c9433 100644 (file)
@@ -114,6 +114,7 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net)
  * @flags: flags
  * @policy: attribute validation policy
  * @doit: standard command callback
+ * @start: start callback for dumps
  * @dumpit: callback for dumpers
  * @done: completion callback for dumps
  * @ops_list: operations list
@@ -122,6 +123,7 @@ struct genl_ops {
        const struct nla_policy *policy;
        int                    (*doit)(struct sk_buff *skb,
                                       struct genl_info *info);
+       int                    (*start)(struct netlink_callback *cb);
        int                    (*dumpit)(struct sk_buff *skb,
                                         struct netlink_callback *cb);
        int                    (*done)(struct netlink_callback *cb);
index 9ecdd61c64632b3f4e09e48b3c7049ed1667b8bd..a87afc4f3c91ee29c086901a9d3ac815564a7ae1 100644 (file)
@@ -2203,6 +2203,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 
        cb = &nlk->cb;
        memset(cb, 0, sizeof(*cb));
+       cb->start = control->start;
        cb->dump = control->dump;
        cb->done = control->done;
        cb->nlh = nlh;
@@ -2216,6 +2217,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 
        mutex_unlock(nlk->cb_mutex);
 
+       if (cb->start)
+               cb->start(cb);
+
        ret = netlink_dump(sk);
        sock_put(sk);
 
index bc0e504f33a68ee92897cb3c45241d4d3348deba..8e63662c6fb0fc236da90883ff34b79d05308fcc 100644 (file)
@@ -513,6 +513,20 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
 }
 EXPORT_SYMBOL(genlmsg_put);
 
+static int genl_lock_start(struct netlink_callback *cb)
+{
+       /* our ops are always const - netlink API doesn't propagate that */
+       const struct genl_ops *ops = cb->data;
+       int rc = 0;
+
+       if (ops->start) {
+               genl_lock();
+               rc = ops->start(cb);
+               genl_unlock();
+       }
+       return rc;
+}
+
 static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 {
        /* our ops are always const - netlink API doesn't propagate that */
@@ -577,6 +591,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
                                .module = family->module,
                                /* we have const, but the netlink API doesn't */
                                .data = (void *)ops,
+                               .start = genl_lock_start,
                                .dump = genl_lock_dumpit,
                                .done = genl_lock_done,
                        };
@@ -588,6 +603,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
                } else {
                        struct netlink_dump_control c = {
                                .module = family->module,
+                               .start = ops->start,
                                .dump = ops->dumpit,
                                .done = ops->done,
                        };