Commit 27248d2f authored by Tom Herbert's avatar Tom Herbert Committed by Greg Kroah-Hartman

netlink: add a start callback for starting a netlink dump

commit fc9e50f5 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: default avatarTom Herbert <tom@herbertland.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 08c15ad2
...@@ -131,6 +131,7 @@ netlink_skb_clone(struct sk_buff *skb, gfp_t gfp_mask) ...@@ -131,6 +131,7 @@ netlink_skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
struct netlink_callback { struct netlink_callback {
struct sk_buff *skb; struct sk_buff *skb;
const struct nlmsghdr *nlh; const struct nlmsghdr *nlh;
int (*start)(struct netlink_callback *);
int (*dump)(struct sk_buff * skb, int (*dump)(struct sk_buff * skb,
struct netlink_callback *cb); struct netlink_callback *cb);
int (*done)(struct netlink_callback *cb); int (*done)(struct netlink_callback *cb);
...@@ -153,6 +154,7 @@ struct nlmsghdr * ...@@ -153,6 +154,7 @@ struct nlmsghdr *
__nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int flags); __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int flags);
struct netlink_dump_control { struct netlink_dump_control {
int (*start)(struct netlink_callback *);
int (*dump)(struct sk_buff *skb, struct netlink_callback *); int (*dump)(struct sk_buff *skb, struct netlink_callback *);
int (*done)(struct netlink_callback *); int (*done)(struct netlink_callback *);
void *data; void *data;
......
...@@ -114,6 +114,7 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net) ...@@ -114,6 +114,7 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net)
* @flags: flags * @flags: flags
* @policy: attribute validation policy * @policy: attribute validation policy
* @doit: standard command callback * @doit: standard command callback
* @start: start callback for dumps
* @dumpit: callback for dumpers * @dumpit: callback for dumpers
* @done: completion callback for dumps * @done: completion callback for dumps
* @ops_list: operations list * @ops_list: operations list
...@@ -122,6 +123,7 @@ struct genl_ops { ...@@ -122,6 +123,7 @@ struct genl_ops {
const struct nla_policy *policy; const struct nla_policy *policy;
int (*doit)(struct sk_buff *skb, int (*doit)(struct sk_buff *skb,
struct genl_info *info); struct genl_info *info);
int (*start)(struct netlink_callback *cb);
int (*dumpit)(struct sk_buff *skb, int (*dumpit)(struct sk_buff *skb,
struct netlink_callback *cb); struct netlink_callback *cb);
int (*done)(struct netlink_callback *cb); int (*done)(struct netlink_callback *cb);
......
...@@ -2203,6 +2203,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, ...@@ -2203,6 +2203,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
cb = &nlk->cb; cb = &nlk->cb;
memset(cb, 0, sizeof(*cb)); memset(cb, 0, sizeof(*cb));
cb->start = control->start;
cb->dump = control->dump; cb->dump = control->dump;
cb->done = control->done; cb->done = control->done;
cb->nlh = nlh; cb->nlh = nlh;
...@@ -2216,6 +2217,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, ...@@ -2216,6 +2217,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
mutex_unlock(nlk->cb_mutex); mutex_unlock(nlk->cb_mutex);
if (cb->start)
cb->start(cb);
ret = netlink_dump(sk); ret = netlink_dump(sk);
sock_put(sk); sock_put(sk);
......
...@@ -513,6 +513,20 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, ...@@ -513,6 +513,20 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
} }
EXPORT_SYMBOL(genlmsg_put); 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) static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
{ {
/* our ops are always const - netlink API doesn't propagate that */ /* 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,6 +591,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
.module = family->module, .module = family->module,
/* we have const, but the netlink API doesn't */ /* we have const, but the netlink API doesn't */
.data = (void *)ops, .data = (void *)ops,
.start = genl_lock_start,
.dump = genl_lock_dumpit, .dump = genl_lock_dumpit,
.done = genl_lock_done, .done = genl_lock_done,
}; };
...@@ -588,6 +603,7 @@ static int genl_family_rcv_msg(struct genl_family *family, ...@@ -588,6 +603,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
} else { } else {
struct netlink_dump_control c = { struct netlink_dump_control c = {
.module = family->module, .module = family->module,
.start = ops->start,
.dump = ops->dumpit, .dump = ops->dumpit,
.done = ops->done, .done = ops->done,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment