diff options
author | Tom Herbert <tom@herbertland.com> | 2015-12-15 18:41:37 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-12-15 23:25:20 -0500 |
commit | fc9e50f5a5a4e1fa9ba2756f745a13e693cf6a06 (patch) | |
tree | 168120764bcdbba0aad5859c9044f7dd84eb4350 /net/netlink | |
parent | 3502cad73c4bbf8f6365d539e814159275252c59 (diff) |
netlink: add a start callback for starting a netlink dump
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>
Diffstat (limited to 'net/netlink')
-rw-r--r-- | net/netlink/af_netlink.c | 4 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 16 |
2 files changed, 20 insertions, 0 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 59651af8cc27..81dc1bb6e016 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -2915,6 +2915,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
2915 | 2915 | ||
2916 | cb = &nlk->cb; | 2916 | cb = &nlk->cb; |
2917 | memset(cb, 0, sizeof(*cb)); | 2917 | memset(cb, 0, sizeof(*cb)); |
2918 | cb->start = control->start; | ||
2918 | cb->dump = control->dump; | 2919 | cb->dump = control->dump; |
2919 | cb->done = control->done; | 2920 | cb->done = control->done; |
2920 | cb->nlh = nlh; | 2921 | cb->nlh = nlh; |
@@ -2927,6 +2928,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
2927 | 2928 | ||
2928 | mutex_unlock(nlk->cb_mutex); | 2929 | mutex_unlock(nlk->cb_mutex); |
2929 | 2930 | ||
2931 | if (cb->start) | ||
2932 | cb->start(cb); | ||
2933 | |||
2930 | ret = netlink_dump(sk); | 2934 | ret = netlink_dump(sk); |
2931 | sock_put(sk); | 2935 | sock_put(sk); |
2932 | 2936 | ||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index bc0e504f33a6..8e63662c6fb0 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -513,6 +513,20 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, | |||
513 | } | 513 | } |
514 | EXPORT_SYMBOL(genlmsg_put); | 514 | EXPORT_SYMBOL(genlmsg_put); |
515 | 515 | ||
516 | static int genl_lock_start(struct netlink_callback *cb) | ||
517 | { | ||
518 | /* our ops are always const - netlink API doesn't propagate that */ | ||
519 | const struct genl_ops *ops = cb->data; | ||
520 | int rc = 0; | ||
521 | |||
522 | if (ops->start) { | ||
523 | genl_lock(); | ||
524 | rc = ops->start(cb); | ||
525 | genl_unlock(); | ||
526 | } | ||
527 | return rc; | ||
528 | } | ||
529 | |||
516 | static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) | 530 | static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) |
517 | { | 531 | { |
518 | /* our ops are always const - netlink API doesn't propagate that */ | 532 | /* 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, | |||
577 | .module = family->module, | 591 | .module = family->module, |
578 | /* we have const, but the netlink API doesn't */ | 592 | /* we have const, but the netlink API doesn't */ |
579 | .data = (void *)ops, | 593 | .data = (void *)ops, |
594 | .start = genl_lock_start, | ||
580 | .dump = genl_lock_dumpit, | 595 | .dump = genl_lock_dumpit, |
581 | .done = genl_lock_done, | 596 | .done = genl_lock_done, |
582 | }; | 597 | }; |
@@ -588,6 +603,7 @@ static int genl_family_rcv_msg(struct genl_family *family, | |||
588 | } else { | 603 | } else { |
589 | struct netlink_dump_control c = { | 604 | struct netlink_dump_control c = { |
590 | .module = family->module, | 605 | .module = family->module, |
606 | .start = ops->start, | ||
591 | .dump = ops->dumpit, | 607 | .dump = ops->dumpit, |
592 | .done = ops->done, | 608 | .done = ops->done, |
593 | }; | 609 | }; |