diff options
| author | Tom Herbert <tom@herbertland.com> | 2015-12-15 15:41:37 -0800 |
|---|---|---|
| committer | Moyster <oysterized@gmail.com> | 2018-04-13 14:50:23 +0200 |
| commit | 39977a83d4d8cd5e8b22ca9111a4b05851c4c418 (patch) | |
| tree | 44724ad1234d82041938322134ddcc557c4eff8b | |
| parent | 9fb6012d26b2d4335a3a3d19ec73a8a1c5a09de6 (diff) | |
BACKPORT: netlink: add a start callback for starting a netlink dump
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>
(cherry picked from commit 142afbc6b2f33832f332ce5b561aa817edfff0b4)
Change-Id: Ibaaffde651e76be2defeaa081ae56ca9e8f93602
| -rw-r--r-- | include/linux/netlink.h | 2 | ||||
| -rw-r--r-- | include/net/genetlink.h | 2 | ||||
| -rw-r--r-- | net/netlink/af_netlink.c | 4 | ||||
| -rw-r--r-- | net/netlink/genetlink.c | 16 |
4 files changed, 24 insertions, 0 deletions
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 9516dad45..b3c6501ae 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -103,6 +103,7 @@ int netlink_sendskb(struct sock *sk, struct sk_buff *skb); 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); @@ -125,6 +126,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; diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 8e0b6c856..d0c5bb84a 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -105,6 +105,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 @@ -116,6 +117,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); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 20fda4ee1..2c1c841f0 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2567,6 +2567,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; @@ -2579,6 +2580,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); diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index c7408dd8f..44feb83e0 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -544,6 +544,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) { struct genl_ops *ops = cb->data; @@ -605,6 +619,7 @@ static int genl_family_rcv_msg(struct genl_family *family, struct netlink_dump_control c = { .module = family->module, .data = ops, + .start = genl_lock_start, .dump = genl_lock_dumpit, .done = genl_lock_done, }; @@ -616,6 +631,7 @@ static int genl_family_rcv_msg(struct genl_family *family, } else { struct netlink_dump_control c = { .module = family->module, + .start = genl_lock_start, .dump = ops->dumpit, .done = ops->done, }; |
