From ec012f3b85159102662264bb5c3436c849d2b1b9 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:30:41 +0300 Subject: [PATCH 01/12] net: Convert broute_net_ops, frame_filter_net_ops and frame_nat_net_ops These pernet_operations use ebt_register_table() and ebt_unregister_table() to act on the tables, which are used as argument in ebt_do_table(), called from ebtables hooks. Since there are no net-related bridge packets in-flight, when the init and exit methods are called, these pernet_operations are safe to be executed in parallel with any other. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtable_broute.c | 1 + net/bridge/netfilter/ebtable_filter.c | 1 + net/bridge/netfilter/ebtable_nat.c | 1 + 3 files changed, 3 insertions(+) diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index 276b60262981..f070b5e5b9dd 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c @@ -77,6 +77,7 @@ static void __net_exit broute_net_exit(struct net *net) static struct pernet_operations broute_net_ops = { .init = broute_net_init, .exit = broute_net_exit, + .async = true, }; static int __init ebtable_broute_init(void) diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index c41da5fac84f..4151afc8efcc 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c @@ -105,6 +105,7 @@ static void __net_exit frame_filter_net_exit(struct net *net) static struct pernet_operations frame_filter_net_ops = { .init = frame_filter_net_init, .exit = frame_filter_net_exit, + .async = true, }; static int __init ebtable_filter_init(void) diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 08df7406ecb3..b8da2dfe2ec5 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c @@ -105,6 +105,7 @@ static void __net_exit frame_nat_net_exit(struct net *net) static struct pernet_operations frame_nat_net_ops = { .init = frame_nat_net_init, .exit = frame_nat_net_exit, + .async = true, }; static int __init ebtable_nat_init(void) From 3822034569ac8ae39556e50fa165dc7d4276f452 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:30:50 +0300 Subject: [PATCH 02/12] net: Convert log pernet_operations These pernet_operations use nf_log_set() and nf_log_unset() in their methods: nf_log_bridge_net_ops nf_log_arp_net_ops nf_log_ipv4_net_ops nf_log_ipv6_net_ops nf_log_netdev_net_ops Nobody can send such a packet to a net before it's became registered, nobody can send a packet after all netdevices are unregistered. So, these pernet_operations are able to be marked as async. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/bridge/netfilter/nf_log_bridge.c | 1 + net/ipv4/netfilter/nf_log_arp.c | 1 + net/ipv4/netfilter/nf_log_ipv4.c | 1 + net/ipv6/netfilter/nf_log_ipv6.c | 1 + net/netfilter/nf_log_netdev.c | 1 + 5 files changed, 5 insertions(+) diff --git a/net/bridge/netfilter/nf_log_bridge.c b/net/bridge/netfilter/nf_log_bridge.c index bd2b3c78f59b..91bfc2ac055a 100644 --- a/net/bridge/netfilter/nf_log_bridge.c +++ b/net/bridge/netfilter/nf_log_bridge.c @@ -48,6 +48,7 @@ static void __net_exit nf_log_bridge_net_exit(struct net *net) static struct pernet_operations nf_log_bridge_net_ops = { .init = nf_log_bridge_net_init, .exit = nf_log_bridge_net_exit, + .async = true, }; static int __init nf_log_bridge_init(void) diff --git a/net/ipv4/netfilter/nf_log_arp.c b/net/ipv4/netfilter/nf_log_arp.c index df5c2a2061a4..162293469ac2 100644 --- a/net/ipv4/netfilter/nf_log_arp.c +++ b/net/ipv4/netfilter/nf_log_arp.c @@ -122,6 +122,7 @@ static void __net_exit nf_log_arp_net_exit(struct net *net) static struct pernet_operations nf_log_arp_net_ops = { .init = nf_log_arp_net_init, .exit = nf_log_arp_net_exit, + .async = true, }; static int __init nf_log_arp_init(void) diff --git a/net/ipv4/netfilter/nf_log_ipv4.c b/net/ipv4/netfilter/nf_log_ipv4.c index 4388de0e5380..7a06de140f3c 100644 --- a/net/ipv4/netfilter/nf_log_ipv4.c +++ b/net/ipv4/netfilter/nf_log_ipv4.c @@ -358,6 +358,7 @@ static void __net_exit nf_log_ipv4_net_exit(struct net *net) static struct pernet_operations nf_log_ipv4_net_ops = { .init = nf_log_ipv4_net_init, .exit = nf_log_ipv4_net_exit, + .async = true, }; static int __init nf_log_ipv4_init(void) diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c index b397a8fe88b9..0220e584589c 100644 --- a/net/ipv6/netfilter/nf_log_ipv6.c +++ b/net/ipv6/netfilter/nf_log_ipv6.c @@ -390,6 +390,7 @@ static void __net_exit nf_log_ipv6_net_exit(struct net *net) static struct pernet_operations nf_log_ipv6_net_ops = { .init = nf_log_ipv6_net_init, .exit = nf_log_ipv6_net_exit, + .async = true, }; static int __init nf_log_ipv6_init(void) diff --git a/net/netfilter/nf_log_netdev.c b/net/netfilter/nf_log_netdev.c index 350eb147754d..254c2c6bde48 100644 --- a/net/netfilter/nf_log_netdev.c +++ b/net/netfilter/nf_log_netdev.c @@ -47,6 +47,7 @@ static void __net_exit nf_log_netdev_net_exit(struct net *net) static struct pernet_operations nf_log_netdev_net_ops = { .init = nf_log_netdev_net_init, .exit = nf_log_netdev_net_exit, + .async = true, }; static int __init nf_log_netdev_init(void) From c60a246cd366b5da5a12cc972a25e41bc536706f Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:31:00 +0300 Subject: [PATCH 03/12] net: Convert arp_tables_net_ops and ip6_tables_net_ops These pernet_operations call xt_proto_init() and xt_proto_fini(), which just register and unregister /proc entries. They are safe to be marked as async. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/ipv4/netfilter/arp_tables.c | 1 + net/ipv6/netfilter/ip6_tables.c | 1 + 2 files changed, 2 insertions(+) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index e3e420f3ba7b..c36ffce3c812 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1635,6 +1635,7 @@ static void __net_exit arp_tables_net_exit(struct net *net) static struct pernet_operations arp_tables_net_ops = { .init = arp_tables_net_init, .exit = arp_tables_net_exit, + .async = true, }; static int __init arp_tables_init(void) diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 62358b93bbac..4de8ac1e5af4 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1928,6 +1928,7 @@ static void __net_exit ip6_tables_net_exit(struct net *net) static struct pernet_operations ip6_tables_net_ops = { .init = ip6_tables_net_init, .exit = ip6_tables_net_exit, + .async = true, }; static int __init ip6_tables_init(void) From d217472410a033cdef5b8fba4393b466ee3c3bbc Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:31:10 +0300 Subject: [PATCH 04/12] net: Convert caif_net_ops Init method just allocates memory for new cfg, and assigns net_generic(net, caif_net_id). Despite there is synchronize_rcu() on error path in cfcnfg_create(), in real this function does not use global lists, so it looks like this synchronize_rcu() is some legacy inheritance. Exit method removes caif devices under rtnl_lock(). There could be a problem, if someone from foreign net pernet_operations dereference caif_net_id of this net. It's dereferenced in get_cfcnfg() and caif_device_list(). get_cfcnfg() is used from netdevice notifiers, where they are called under rtnl_lock(). The notifiers can't be called from foreign nets pernet_operations. Also, it's used from caif_disconnect_client() and from caif_connect_client(). The both of the functions work with caif socket, and there is the only possibility to have a socket, when the net is dead. This may happen only of the socket was created as kern using sk_alloc(). Grep by PF_CAIF shows we do not create kern caif sockets, so get_cfcnfg() is safe. caif_device_list() is used in netdevice notifiers and exit method under rtnl lock. Also, from caif_get() used in the netdev notifiers and in caif_flow_cb(). The last item is skb destructor. Since there are no kernel caif sockets nobody can send net a packet in parallel with init/exit, so this is also safe. So, these pernet_operations are safe to be async. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/caif/caif_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index e0adcd123f48..7a78268cc572 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -544,6 +544,7 @@ static struct pernet_operations caif_net_ops = { .exit = caif_exit_net, .id = &caif_net_id, .size = sizeof(struct caif_net), + .async = true, }; /* Initialize Caif devices list */ From 111da7adc1276d44d20c3973f4b39d62f83df056 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:31:19 +0300 Subject: [PATCH 05/12] net: Convert cangw_pernet_ops These pernet_operations have a deal with cgw_list, and the rest of accesses are made under rtnl_lock(). The only exception is cgw_dump_jobs(), which is accessed under rcu_read_lock(). cgw_dump_jobs() is called on netlink request, and it does not seem, foreign pernet_operations want to send a net such the messages. So, we mark them as async. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/can/gw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/can/gw.c b/net/can/gw.c index 398dd0395ad9..08e97668d5cf 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -1010,6 +1010,7 @@ static void __net_exit cangw_pernet_exit(struct net *net) static struct pernet_operations cangw_pernet_ops = { .init = cangw_pernet_init, .exit = cangw_pernet_exit, + .async = true, }; static __init int cgw_module_init(void) From 5368bd72cd7aacd0e3f80f61e9b2a096fc81cc10 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:31:28 +0300 Subject: [PATCH 06/12] net: Convert dccp_v4_ops These pernet_operations create and destroy net::dccp::v4_ctl_sk. It looks like another pernet_operations don't want to send dccp packets to dying or creating net. Batch method similar to ipv4/ipv6 sockets and it has to be safe to be executed in parallel with anything else. So, we mark them as async. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index e65fcb45c3f6..13ad28ab1e79 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1031,6 +1031,7 @@ static struct pernet_operations dccp_v4_ops = { .init = dccp_v4_init_net, .exit = dccp_v4_exit_net, .exit_batch = dccp_v4_exit_batch, + .async = true, }; static int __init dccp_v4_init(void) From 16b0c0c4d9a799979b0d3f387821c93bcc301f79 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:31:37 +0300 Subject: [PATCH 07/12] net: Convert dccp_v6_ops These pernet_operations looks similar to dccp_v4_ops, and they are also safe to be marked as async. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/dccp/ipv6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 5df7857fc0f3..2f48c020f8c3 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1116,6 +1116,7 @@ static struct pernet_operations dccp_v6_ops = { .init = dccp_v6_init_net, .exit = dccp_v6_exit_net, .exit_batch = dccp_v6_exit_batch, + .async = true, }; static int __init dccp_v6_init(void) From 6c6c566e6dd80bec6f5bbb9c36e397ed9b109cdb Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:31:47 +0300 Subject: [PATCH 08/12] net: Convert fou_net_ops These pernet_operations initialize and destroy pernet net_generic(net, fou_net_id) list. The rest of net_generic(net, fou_net_id) accesses may happen after netlink message, and in-tree pernet_operations do not send FOU_GENL_NAME messages. So, these pernet_operations are safe to be marked as async. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/ipv4/fou.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 1540db65241a..d3e1a9af478b 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -1081,6 +1081,7 @@ static struct pernet_operations fou_net_ops = { .exit = fou_exit_net, .id = &fou_net_id, .size = sizeof(struct fou_net), + .async = true, }; static int __init fou_init(void) From a5a179b6dff15ae0b89cb601b0a0242cff60b8e3 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:31:55 +0300 Subject: [PATCH 09/12] net: Convert ip_set_net_ops These pernet_operations initialize and destroy net_generic(net, ip_set_net_id)-related data. Since ip_set is under CONFIG_IP_SET, it's easy to watch drivers, which depend on this config. All of them are in net/netfilter/ipset directory, except of net/netfilter/xt_set.c. There are no more drivers, which use ip_set, and all of the above don't register another pernet_operations. Also, there are is no indirect users, as header file include/linux/netfilter/ipset/ip_set.h does not define indirect users by something like this: #ifdef CONFIG_IP_SET extern func(void); #else static inline func(void); #endif So, there are no more pernet operations, dereferencing net_generic(net, ip_set_net_id). ip_set_net_ops are OK to be executed in parallel for several net, so we mark them as async. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/netfilter/ipset/ip_set_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 975a85a48d39..2523ebe2b3cc 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -2094,7 +2094,8 @@ static struct pernet_operations ip_set_net_ops = { .init = ip_set_net_init, .exit = ip_set_net_exit, .id = &ip_set_net_id, - .size = sizeof(struct ip_set_net) + .size = sizeof(struct ip_set_net), + .async = true, }; static int __init From 467d14b3073960645902ea0d18c1cbe645013638 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:32:06 +0300 Subject: [PATCH 10/12] net: Convert nf_conntrack_net_ops These pernet_operations register and unregister sysctl and /proc entries. Exit batch method also waits till all per-net conntracks are dead. Thus, they are safe to be marked as async. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_standalone.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 9123fdec5e14..3cdce391362e 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -705,6 +705,7 @@ static void nf_conntrack_pernet_exit(struct list_head *net_exit_list) static struct pernet_operations nf_conntrack_net_ops = { .init = nf_conntrack_pernet_init, .exit_batch = nf_conntrack_pernet_exit, + .async = true, }; static int __init nf_conntrack_standalone_init(void) From b04a3d098c4ca176849ee579880c63c052ce6776 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:32:15 +0300 Subject: [PATCH 11/12] net: Convert ctnetlink_net_ops These pernet_operations register and unregister two conntrack notifiers, and they seem to be safe to be executed in parallel. General/not related to async pernet_operations JFI: ctnetlink_net_exit_batch() actions are grouped in batch, and this could look like there is synchronize_rcu() is forgotten. But there is synchronize_rcu() on module exit patch (in ctnetlink_exit()), so this batch may be reworked as simple .exit method. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_netlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index dd177ebee9aa..8884d302d33a 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -3417,6 +3417,7 @@ static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list) static struct pernet_operations ctnetlink_net_ops = { .init = ctnetlink_net_init, .exit_batch = ctnetlink_net_exit_batch, + .async = true, }; static int __init ctnetlink_init(void) From c29babb7fe26e1507e8c236abbfed6e944e42651 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 5 Mar 2018 14:32:23 +0300 Subject: [PATCH 12/12] net: Convert proto_gre_net_ops These pernet_operations register and unregister sysctl. nf_conntrack_l4proto_gre4->init_net is simple memory initializer. Also, exit method removes gre keymap_list, which is per-net. This looks safe to be executed in parallel with other pernet_operations. Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_proto_gre.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index d049ea5a3770..9bcd72fe91f9 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -406,6 +406,7 @@ static struct pernet_operations proto_gre_net_ops = { .exit = proto_gre_net_exit, .id = &proto_gre_net_id, .size = sizeof(struct netns_proto_gre), + .async = true, }; static int __init nf_ct_proto_gre_init(void)