Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[sfrench/cifs-2.6.git] / net / core / flow_dissector.c
index 3eff84824c8b451144fab6be6c772bf29d1c5345..5dceed467f6413555d4cd62991132542bbcfd864 100644 (file)
@@ -160,12 +160,10 @@ out:
        return ret;
 }
 
-int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr)
+static int flow_dissector_bpf_prog_detach(struct net *net)
 {
        struct bpf_prog *attached;
-       struct net *net;
 
-       net = current->nsproxy->net_ns;
        mutex_lock(&flow_dissector_mutex);
        attached = rcu_dereference_protected(net->flow_dissector_prog,
                                             lockdep_is_held(&flow_dissector_mutex));
@@ -179,6 +177,24 @@ int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr)
        return 0;
 }
 
+int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr)
+{
+       return flow_dissector_bpf_prog_detach(current->nsproxy->net_ns);
+}
+
+static void __net_exit flow_dissector_pernet_pre_exit(struct net *net)
+{
+       /* We're not racing with attach/detach because there are no
+        * references to netns left when pre_exit gets called.
+        */
+       if (rcu_access_pointer(net->flow_dissector_prog))
+               flow_dissector_bpf_prog_detach(net);
+}
+
+static struct pernet_operations flow_dissector_pernet_ops __net_initdata = {
+       .pre_exit = flow_dissector_pernet_pre_exit,
+};
+
 /**
  * __skb_flow_get_ports - extract the upper layer ports and return them
  * @skb: sk_buff to extract the ports from
@@ -1836,7 +1852,7 @@ static int __init init_default_flow_dissectors(void)
        skb_flow_dissector_init(&flow_keys_basic_dissector,
                                flow_keys_basic_dissector_keys,
                                ARRAY_SIZE(flow_keys_basic_dissector_keys));
-       return 0;
-}
 
+       return register_pernet_subsys(&flow_dissector_pernet_ops);
+}
 core_initcall(init_default_flow_dissectors);