diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-10-04 21:14:03 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-10-05 13:35:30 -0400 |
commit | ff4c92d85c6f2777d2067f8552e7fefb4d1754ae (patch) | |
tree | 77e35603821e5602e96c90644e42e70f097ad79c /net/netlink/genetlink.c | |
parent | 2ee4e27cf25ab647137713ca16377d8d9e138ea2 (diff) | |
download | linux-ff4c92d85c6f2777d2067f8552e7fefb4d1754ae.tar.gz linux-ff4c92d85c6f2777d2067f8552e7fefb4d1754ae.tar.bz2 linux-ff4c92d85c6f2777d2067f8552e7fefb4d1754ae.zip |
genetlink: introduce pre_doit/post_doit hooks
Each family may have some amount of boilerplate
locking code that applies to most, or even all,
commands.
This allows a family to handle such things in
a more generic way, by allowing it to
a) include private flags in each operation
b) specify a pre_doit hook that is called,
before an operation's doit() callback and
may return an error directly,
c) specify a post_doit hook that can undo
locking or similar things done by pre_doit,
and finally
d) include two private pointers in each info
struct passed between all these operations
including doit(). (It's two because I'll
need two in nl80211 -- can be extended.)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r-- | net/netlink/genetlink.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 26ed3e8587c2..1781d99145e2 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -547,8 +547,20 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; info.attrs = family->attrbuf; genl_info_net_set(&info, net); + memset(&info.user_ptr, 0, sizeof(info.user_ptr)); - return ops->doit(skb, &info); + if (family->pre_doit) { + err = family->pre_doit(ops, skb, &info); + if (err) + return err; + } + + err = ops->doit(skb, &info); + + if (family->post_doit) + family->post_doit(ops, skb, &info); + + return err; } static void genl_rcv(struct sk_buff *skb) |