From patchwork Mon Oct 4 19:14:03 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 66719 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 2CDE6B6EF2 for ; Tue, 5 Oct 2010 06:19:48 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932425Ab0JDTTn (ORCPT ); Mon, 4 Oct 2010 15:19:43 -0400 Received: from he.sipsolutions.net ([78.46.109.217]:47312 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932413Ab0JDTTl (ORCPT ); Mon, 4 Oct 2010 15:19:41 -0400 Received: by sipsolutions.net with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.72) (envelope-from ) id 1P2qZY-00040c-F6; Mon, 04 Oct 2010 21:19:40 +0200 Message-Id: <20101004191838.763690480@sipsolutions.net> User-Agent: quilt/0.48-1 Date: Mon, 04 Oct 2010 21:14:03 +0200 From: Johannes Berg To: John Linville Cc: netdev@vger.kernel.org, linux-wireless@vger.kernel.org Subject: [PATCH 1/4] genetlink: introduce pre_doit/post_doit hooks References: <20101004191402.183055479@sipsolutions.net> Content-Disposition: inline; filename=012-genl-more-boilerplate.patch Mime-Version: 1.0 X-Mailer: Evolution 2.30.3 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Johannes Berg 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 Acked-by: David S. Miller --- include/net/genetlink.h | 18 ++++++++++++++++++ net/netlink/genetlink.c | 14 +++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- wireless-testing.orig/include/net/genetlink.h 2010-10-04 21:13:52.000000000 +0200 +++ wireless-testing/include/net/genetlink.h 2010-10-04 21:18:16.000000000 +0200 @@ -20,6 +20,9 @@ struct genl_multicast_group { u32 id; }; +struct genl_ops; +struct genl_info; + /** * struct genl_family - generic netlink family * @id: protocol family idenfitier @@ -29,6 +32,10 @@ struct genl_multicast_group { * @maxattr: maximum number of attributes supported * @netnsok: set to true if the family can handle network * namespaces and should be presented in all of them + * @pre_doit: called before an operation's doit callback, it may + * do additional, common, filtering and return an error + * @post_doit: called after an operation's doit callback, it may + * undo operations done by pre_doit, for example release locks * @attrbuf: buffer to store parsed attributes * @ops_list: list of all assigned operations * @family_list: family list @@ -41,6 +48,12 @@ struct genl_family { unsigned int version; unsigned int maxattr; bool netnsok; + int (*pre_doit)(struct genl_ops *ops, + struct sk_buff *skb, + struct genl_info *info); + void (*post_doit)(struct genl_ops *ops, + struct sk_buff *skb, + struct genl_info *info); struct nlattr ** attrbuf; /* private */ struct list_head ops_list; /* private */ struct list_head family_list; /* private */ @@ -55,6 +68,8 @@ struct genl_family { * @genlhdr: generic netlink message header * @userhdr: user specific header * @attrs: netlink attributes + * @_net: network namespace + * @user_ptr: user pointers */ struct genl_info { u32 snd_seq; @@ -66,6 +81,7 @@ struct genl_info { #ifdef CONFIG_NET_NS struct net * _net; #endif + void * user_ptr[2]; }; static inline struct net *genl_info_net(struct genl_info *info) @@ -81,6 +97,7 @@ static inline void genl_info_net_set(str /** * struct genl_ops - generic netlink operations * @cmd: command identifier + * @internal_flags: flags used by the family * @flags: flags * @policy: attribute validation policy * @doit: standard command callback @@ -90,6 +107,7 @@ static inline void genl_info_net_set(str */ struct genl_ops { u8 cmd; + u8 internal_flags; unsigned int flags; const struct nla_policy *policy; int (*doit)(struct sk_buff *skb, --- wireless-testing.orig/net/netlink/genetlink.c 2010-10-04 21:13:52.000000000 +0200 +++ wireless-testing/net/netlink/genetlink.c 2010-10-04 21:18:16.000000000 +0200 @@ -547,8 +547,20 @@ static int genl_rcv_msg(struct sk_buff * 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)