mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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>
This commit is contained in:
parent
3502cad73c
commit
fc9e50f5a5
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -2915,6 +2915,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;
|
||||
@ -2927,6 +2928,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);
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user