genl_lock is not exported from older kernel. Following patch add
genl_exec() which can run any function (passed as arg) with
genl_lock held.

Signed-off-by: Pravin B Shelar <pshe...@nicira.com>
---
 datapath/datapath.c                           |    9 ++-
 datapath/linux/compat/genetlink.inc           |  102 +++++++++++++++++++++++++
 datapath/linux/compat/include/net/genetlink.h |    6 ++
 3 files changed, 116 insertions(+), 1 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index c86c20b..025d932 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -2049,10 +2049,14 @@ static int __init dp_init(void)
        pr_info("Open vSwitch switching datapath %s, built "__DATE__" 
"__TIME__"\n",
                VERSION BUILDNR);
 
-       err = ovs_tnl_init();
+       err = genl_exec_init();
        if (err)
                goto error;
 
+       err = ovs_tnl_init();
+       if (err)
+               goto error_genl_exec;
+
        err = ovs_flow_init();
        if (err)
                goto error_tnl_exit;
@@ -2079,6 +2083,8 @@ error_flow_exit:
        ovs_flow_exit();
 error_tnl_exit:
        ovs_tnl_exit();
+error_genl_exec:
+       genl_exec_exit();
 error:
        return err;
 }
@@ -2091,6 +2097,7 @@ static void dp_cleanup(void)
        ovs_vport_exit();
        ovs_flow_exit();
        ovs_tnl_exit();
+       genl_exec_exit();
 }
 
 module_init(dp_init);
diff --git a/datapath/linux/compat/genetlink.inc 
b/datapath/linux/compat/genetlink.inc
index bf96980..b4de70e 100644
--- a/datapath/linux/compat/genetlink.inc
+++ b/datapath/linux/compat/genetlink.inc
@@ -146,3 +146,105 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 
group, int code)
 {
 }
 #endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+
+static DEFINE_MUTEX(genl_exec_lock);
+
+static genl_exec_func_t         genl_exec_function;
+static int              genl_exec_function_ret;
+static void            *genl_exec_data;
+static struct completion done;
+
+
+static int genl_exec_cmd(struct sk_buff *dummy, struct genl_info *dummy2)
+{
+       if (genl_exec_function)
+               genl_exec_function_ret = genl_exec_function(genl_exec_data);
+       complete(&done);
+       return 0;
+}
+
+enum genl_exec_attr {
+       GENL_EXEC_UNSPEC,
+       GENL_EXEC_RUN,
+       GENL_EXEC_MAX,
+};
+
+static struct genl_family genl_exec_family = {
+       .id = GENL_ID_GENERATE,
+       .hdrsize = 0,
+       .name = "GENL EXEC FAMILY",
+       .version = 1,
+       .maxattr = GENL_EXEC_MAX,
+};
+
+static struct genl_ops genl_exec_ops[] = {
+       {
+        .cmd = GENL_EXEC_RUN,
+        .doit = genl_exec_cmd,
+        .flags = CAP_NET_ADMIN,
+       },
+};
+
+int genl_exec_init(void)
+{
+       int err;
+
+       err = genl_register_family_with_ops(&genl_exec_family,
+                                           genl_exec_ops,
+                                           ARRAY_SIZE(genl_exec_ops));
+       return err;
+}
+
+void genl_exec_exit(void)
+{
+       genl_unregister_family(&genl_exec_family);
+}
+
+/* genl_lock() is not exported from older kernel.
+ * Following function allows any function to be executed with
+ * genl_lock held. */
+
+int genl_exec(genl_exec_func_t func, void *data)
+{
+       struct sk_buff *skb;
+
+       skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!skb)
+               return -ENOMEM;
+
+       genlmsg_put(skb, 0, 0, &genl_exec_family, NLM_F_REQUEST, GENL_EXEC_RUN);
+
+       mutex_lock(&genl_exec_lock);
+       genl_exec_function = func;
+       genl_exec_data = data;
+       init_completion(&done);
+       genlmsg_unicast(&init_net, skb, 0);
+       wait_for_completion(&done);
+       genl_exec_function = NULL;
+       mutex_unlock(&genl_exec_lock);
+
+       return genl_exec_function_ret;
+}
+
+#else
+
+int genl_exec(genl_exec_func_t func, void *data)
+{
+       int ret;
+
+       genl_lock();
+       ret = func(data);
+       genl_unlock();
+       return ret;
+}
+int genl_exec_init(void)
+{
+       return 0;
+}
+void genl_exec_exit(void)
+{
+}
+
+#endif
diff --git a/datapath/linux/compat/include/net/genetlink.h 
b/datapath/linux/compat/include/net/genetlink.h
index a1ff7c1..1bbb559 100644
--- a/datapath/linux/compat/include/net/genetlink.h
+++ b/datapath/linux/compat/include/net/genetlink.h
@@ -170,4 +170,10 @@ static inline struct net *genl_info_net(struct genl_info 
*info)
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
 #define genlmsg_unicast(ignore_net, skb, pid)   genlmsg_unicast(skb, pid)
 #endif
+
+typedef int (*genl_exec_func_t)(void *data);
+int genl_exec(genl_exec_func_t func, void *data);
+int genl_exec_init(void);
+void genl_exec_exit(void);
+
 #endif /* genetlink.h */
-- 
1.7.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to