From: Eric W. Biederman <ebiederm@xmission.com> The motivation for an additional notifier in batched netdevice notification (rt_do_flush) only needs to be called once per batch not once per namespace. For further batching improvements I need a guarantee that the netdevices are unregistered in order allowing me to unregister an all of the network devices in a network namespace at the same time with the guarantee that the loopback device is really and truly unregistered last. Additionally it appears that we moved the route cache flush after the final synchronize_net, which seems wrong and there was no explanation. So I have restored the original location of the final synchronize_net. Cc: Octavian Purdila <opurdila@ixiacom.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- include/linux/notifier.h | 2 +- include/net/route.h | 1 + net/core/dev.c | 36 +++++++++--------------------------- net/ipv4/fib_frontend.c | 4 +++- net/ipv4/route.c | 6 ++++++ 5 files changed, 20 insertions(+), 29 deletions(-) diff --git a/include/linux/notifier.h b/include/linux/notifier.h index b0c3671..fee6c2f 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -202,7 +202,7 @@ static inline int notifier_to_errno(int ret) #define NETDEV_BONDING_OLDTYPE 0x000E #define NETDEV_BONDING_NEWTYPE 0x000F #define NETDEV_POST_INIT 0x0010 -#define NETDEV_UNREGISTER_PERNET 0x0011 +#define NETDEV_UNREGISTER_BATCH 0x0011 #define SYS_DOWN 0x0001 /* Notify of system down */ #define SYS_RESTART SYS_DOWN diff --git a/include/net/route.h b/include/net/route.h index cfb4c07..bce6dd6 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -108,6 +108,7 @@ extern int ip_rt_init(void); extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, __be32 src, struct net_device *dev); extern void rt_cache_flush(struct net *net, int how); +extern void rt_cache_flush_batch(void); extern ...
From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/phonet/pn_dev.c | 16 ++++++----------
1 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index d87388c..bc4a33b 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -313,19 +313,14 @@ static struct notifier_block phonet_device_notifier = {
/* Per-namespace Phonet devices handling */
static int phonet_init_net(struct net *net)
{
- struct phonet_net *pnn = kzalloc(sizeof(*pnn), GFP_KERNEL);
- if (!pnn)
- return -ENOMEM;
+ struct phonet_net *pnn = net_generic(net, phonet_net_id);
- if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops)) {
- kfree(pnn);
+ if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops))
return -ENOMEM;
- }
INIT_LIST_HEAD(&pnn->pndevs.list);
mutex_init(&pnn->pndevs.lock);
mutex_init(&pnn->routes.lock);
- net_assign_generic(net, phonet_net_id, pnn);
return 0;
}
@@ -349,18 +344,19 @@ static void phonet_exit_net(struct net *net)
rtnl_unlock();
proc_net_remove(net, "phonet");
- kfree(pnn);
}
static struct pernet_operations phonet_net_ops = {
.init = phonet_init_net,
.exit = phonet_exit_net,
+ .id = &phonet_net_id,
+ .size = sizeof(struct phonet_net),
};
/* Initialize Phonet devices list */
int __init phonet_device_init(void)
{
- int err = register_pernet_gen_device(&phonet_net_id, &phonet_net_ops);
+ int err = register_pernet_device(&phonet_net_ops);
if (err)
return err;
@@ -375,7 +371,7 @@ void phonet_device_exit(void)
{
rtnl_unregister_all(PF_PHONET);
unregister_netdevice_notifier(&phonet_device_notifier);
- unregister_pernet_gen_device(phonet_net_id, &phonet_net_ops);
+ unregister_pernet_device(&phonet_net_ops);
}
int phonet_route_add(struct net_device ...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/net/bonding/bond_main.c | 32 +++++++++-----------------------
1 files changed, 9 insertions(+), 23 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 726bd75..ac3fe20 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5103,42 +5103,28 @@ out_netdev:
static int bond_net_init(struct net *net)
{
- struct bond_net *bn;
- int err;
-
- err = -ENOMEM;
- bn = kzalloc(sizeof(struct bond_net), GFP_KERNEL);
- if (bn == NULL)
- goto out;
+ struct bond_net *bn = net_generic(net, bond_net_id);
bn->net = net;
INIT_LIST_HEAD(&bn->dev_list);
- err = net_assign_generic(net, bond_net_id, bn);
- if (err)
- goto out_free;
-
bond_create_proc_dir(bn);
-out:
- return err;
-out_free:
- kfree(bn);
- goto out;
+
+ return 0;
}
static void bond_net_exit(struct net *net)
{
- struct bond_net *bn;
-
- bn = net_generic(net, bond_net_id);
+ struct bond_net *bn = net_generic(net, bond_net_id);
bond_destroy_proc_dir(bn);
- kfree(bn);
}
static struct pernet_operations bond_net_ops = {
.init = bond_net_init,
.exit = bond_net_exit,
+ .id = &bond_net_id,
+ .size = sizeof(struct bond_net),
};
static int __init bonding_init(void)
@@ -5152,7 +5138,7 @@ static int __init bonding_init(void)
if (res)
goto out;
- res = register_pernet_gen_subsys(&bond_net_id, &bond_net_ops);
+ res = register_pernet_subsys(&bond_net_ops);
if (res)
goto out;
@@ -5178,7 +5164,7 @@ out:
err:
rtnl_link_unregister(&bond_link_ops);
err_link:
- unregister_pernet_gen_subsys(bond_net_id, &bond_net_ops);
+ unregister_pernet_subsys(&bond_net_ops);
goto out;
}
@@ -5192,7 +5178,7 @@ static void __exit bonding_exit(void)
...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/net/pppol2tp.c | 36 +++++++-----------------------------
1 files changed, 7 insertions(+), 29 deletions(-)
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index c58b50f..9fbb2eb 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -2605,53 +2605,31 @@ static struct pppox_proto pppol2tp_proto = {
static __net_init int pppol2tp_init_net(struct net *net)
{
- struct pppol2tp_net *pn;
+ struct pppol2tp_net *pn = pppol2tp_pernet(net);
struct proc_dir_entry *pde;
- int err;
-
- pn = kzalloc(sizeof(*pn), GFP_KERNEL);
- if (!pn)
- return -ENOMEM;
INIT_LIST_HEAD(&pn->pppol2tp_tunnel_list);
rwlock_init(&pn->pppol2tp_tunnel_list_lock);
- err = net_assign_generic(net, pppol2tp_net_id, pn);
- if (err)
- goto out;
-
pde = proc_net_fops_create(net, "pppol2tp", S_IRUGO, &pppol2tp_proc_fops);
#ifdef CONFIG_PROC_FS
- if (!pde) {
- err = -ENOMEM;
- goto out;
- }
+ if (!pde)
+ return -ENOMEM;
#endif
return 0;
-
-out:
- kfree(pn);
- return err;
}
static __net_exit void pppol2tp_exit_net(struct net *net)
{
- struct pppoe_net *pn;
-
proc_net_remove(net, "pppol2tp");
- pn = net_generic(net, pppol2tp_net_id);
- /*
- * if someone has cached our net then
- * further net_generic call will return NULL
- */
- net_assign_generic(net, pppol2tp_net_id, NULL);
- kfree(pn);
}
static struct pernet_operations pppol2tp_net_ops = {
.init = pppol2tp_init_net,
.exit = pppol2tp_exit_net,
+ .id = &pppol2tp_net_id,
+ .size = sizeof(struct pppol2tp_net),
};
static int __init pppol2tp_init(void)
@@ -2665,7 +2643,7 @@ static int __init pppol2tp_init(void)
if (err)
goto out_unregister_pppol2tp_proto;
- err = register_pernet_gen_device(&pppol2tp_net_id, ...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/ipv4/ipip.c | 24 ++++++------------------
1 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 7242ffc..eda04fe 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -775,17 +775,8 @@ static void ipip_destroy_tunnels(struct ipip_net *ipn, struct list_head *head)
static int ipip_init_net(struct net *net)
{
+ struct ipip_net *ipn = net_generic(net, ipip_net_id);
int err;
- struct ipip_net *ipn;
-
- err = -ENOMEM;
- ipn = kzalloc(sizeof(struct ipip_net), GFP_KERNEL);
- if (ipn == NULL)
- goto err_alloc;
-
- err = net_assign_generic(net, ipip_net_id, ipn);
- if (err < 0)
- goto err_assign;
ipn->tunnels[0] = ipn->tunnels_wc;
ipn->tunnels[1] = ipn->tunnels_l;
@@ -812,29 +803,26 @@ err_reg_dev:
free_netdev(ipn->fb_tunnel_dev);
err_alloc_dev:
/* nothing */
-err_assign:
- kfree(ipn);
-err_alloc:
return err;
}
static void ipip_exit_net(struct net *net)
{
- struct ipip_net *ipn;
+ struct ipip_net *ipn = net_generic(net, ipip_net_id);
LIST_HEAD(list);
- ipn = net_generic(net, ipip_net_id);
rtnl_lock();
ipip_destroy_tunnels(ipn, &list);
unregister_netdevice_queue(ipn->fb_tunnel_dev, &list);
unregister_netdevice_many(&list);
rtnl_unlock();
- kfree(ipn);
}
static struct pernet_operations ipip_net_ops = {
.init = ipip_init_net,
.exit = ipip_exit_net,
+ .id = &ipip_net_id,
+ .size = sizeof(struct ipip_net),
};
static int __init ipip_init(void)
@@ -848,7 +836,7 @@ static int __init ipip_init(void)
return -EAGAIN;
}
- err = register_pernet_gen_device(&ipip_net_id, &ipip_net_ops);
+ err = register_pernet_device(&ipip_net_ops);
if (err)
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
@@ -860,7 +848,7 @@ ...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/ipv6/ip6_tunnel.c | 25 ++++++-------------------
1 files changed, 6 insertions(+), 19 deletions(-)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index e5c0f6b..d453d07 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1409,17 +1409,8 @@ static void ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n)
static int ip6_tnl_init_net(struct net *net)
{
+ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
int err;
- struct ip6_tnl_net *ip6n;
-
- err = -ENOMEM;
- ip6n = kzalloc(sizeof(struct ip6_tnl_net), GFP_KERNEL);
- if (ip6n == NULL)
- goto err_alloc;
-
- err = net_assign_generic(net, ip6_tnl_net_id, ip6n);
- if (err < 0)
- goto err_assign;
ip6n->tnls[0] = ip6n->tnls_wc;
ip6n->tnls[1] = ip6n->tnls_r_l;
@@ -1442,27 +1433,23 @@ static int ip6_tnl_init_net(struct net *net)
err_register:
free_netdev(ip6n->fb_tnl_dev);
err_alloc_dev:
- /* nothing */
-err_assign:
- kfree(ip6n);
-err_alloc:
return err;
}
static void ip6_tnl_exit_net(struct net *net)
{
- struct ip6_tnl_net *ip6n;
+ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
- ip6n = net_generic(net, ip6_tnl_net_id);
rtnl_lock();
ip6_tnl_destroy_tunnels(ip6n);
rtnl_unlock();
- kfree(ip6n);
}
static struct pernet_operations ip6_tnl_net_ops = {
.init = ip6_tnl_init_net,
.exit = ip6_tnl_exit_net,
+ .id = &ip6_tnl_net_id,
+ .size = sizeof(struct ip6_tnl_net),
};
/**
@@ -1487,7 +1474,7 @@ static int __init ip6_tunnel_init(void)
goto unreg_ip4ip6;
}
- err = register_pernet_gen_device(&ip6_tnl_net_id, &ip6_tnl_net_ops);
+ err = register_pernet_device(&ip6_tnl_net_ops);
if (err < 0)
goto err_pernet;
return 0;
@@ -1511,7 +1498,7 @@ static void __exit ...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/netfilter/nf_conntrack_proto_gre.c | 20 ++++++--------------
1 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 91d0e71..c99cfba 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -300,32 +300,24 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
static int proto_gre_net_init(struct net *net)
{
- struct netns_proto_gre *net_gre;
- int rv;
+ struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
- net_gre = kmalloc(sizeof(struct netns_proto_gre), GFP_KERNEL);
- if (!net_gre)
- return -ENOMEM;
rwlock_init(&net_gre->keymap_lock);
INIT_LIST_HEAD(&net_gre->keymap_list);
- rv = net_assign_generic(net, proto_gre_net_id, net_gre);
- if (rv < 0)
- kfree(net_gre);
- return rv;
+ return 0;
}
static void proto_gre_net_exit(struct net *net)
{
- struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
-
nf_ct_gre_keymap_flush(net);
- kfree(net_gre);
}
static struct pernet_operations proto_gre_net_ops = {
.init = proto_gre_net_init,
.exit = proto_gre_net_exit,
+ .id = &proto_gre_net_id,
+ .size = sizeof(struct netns_proto_gre),
};
static int __init nf_ct_proto_gre_init(void)
@@ -335,7 +327,7 @@ static int __init nf_ct_proto_gre_init(void)
rv = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4);
if (rv < 0)
return rv;
- rv = register_pernet_gen_subsys(&proto_gre_net_id, &proto_gre_net_ops);
+ rv = register_pernet_subsys(&proto_gre_net_ops);
if (rv < 0)
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
return rv;
@@ -344,7 +336,7 @@ static int __init ...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/netfilter/nf_conntrack_proto_dccp.c | 31 ++++++++-----------------------
1 files changed, 8 insertions(+), 23 deletions(-)
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index 80abdf2..98916ef 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -810,12 +810,7 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
static __net_init int dccp_net_init(struct net *net)
{
- struct dccp_net *dn;
- int err;
-
- dn = kmalloc(sizeof(*dn), GFP_KERNEL);
- if (!dn)
- return -ENOMEM;
+ struct dccp_net *dn = dccp_pernet(net);
/* default values */
dn->dccp_loose = 1;
@@ -827,16 +822,11 @@ static __net_init int dccp_net_init(struct net *net)
dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ;
dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL;
- err = net_assign_generic(net, dccp_net_id, dn);
- if (err)
- goto out;
-
#ifdef CONFIG_SYSCTL
- err = -ENOMEM;
dn->sysctl_table = kmemdup(dccp_sysctl_table,
sizeof(dccp_sysctl_table), GFP_KERNEL);
if (!dn->sysctl_table)
- goto out;
+ return -ENOMEM;
dn->sysctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
dn->sysctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
@@ -851,15 +841,11 @@ static __net_init int dccp_net_init(struct net *net)
nf_net_netfilter_sysctl_path, dn->sysctl_table);
if (!dn->sysctl_header) {
kfree(dn->sysctl_table);
- goto out;
+ return -ENOMEM;
}
#endif
return 0;
-
-out:
- kfree(dn);
- return err;
}
static __net_exit void dccp_net_exit(struct net *net)
@@ -869,21 +855,20 @@ static __net_exit void dccp_net_exit(struct net *net)
unregister_net_sysctl_table(dn->sysctl_header);
...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/key/af_key.c | 25 ++++++-------------------
1 files changed, 6 insertions(+), 19 deletions(-)
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 478c8b3..84209fb 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -3765,28 +3765,14 @@ static struct xfrm_mgr pfkeyv2_mgr =
static int __net_init pfkey_net_init(struct net *net)
{
- struct netns_pfkey *net_pfkey;
+ struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
int rv;
- net_pfkey = kmalloc(sizeof(struct netns_pfkey), GFP_KERNEL);
- if (!net_pfkey) {
- rv = -ENOMEM;
- goto out_kmalloc;
- }
INIT_HLIST_HEAD(&net_pfkey->table);
atomic_set(&net_pfkey->socks_nr, 0);
- rv = net_assign_generic(net, pfkey_net_id, net_pfkey);
- if (rv < 0)
- goto out_assign;
+
rv = pfkey_init_proc(net);
- if (rv < 0)
- goto out_proc;
- return 0;
-out_proc:
-out_assign:
- kfree(net_pfkey);
-out_kmalloc:
return rv;
}
@@ -3796,17 +3782,18 @@ static void __net_exit pfkey_net_exit(struct net *net)
pfkey_exit_proc(net);
BUG_ON(!hlist_empty(&net_pfkey->table));
- kfree(net_pfkey);
}
static struct pernet_operations pfkey_net_ops = {
.init = pfkey_net_init,
.exit = pfkey_net_exit,
+ .id = &pfkey_net_id,
+ .size = sizeof(struct netns_pfkey),
};
static void __exit ipsec_pfkey_exit(void)
{
- unregister_pernet_gen_subsys(pfkey_net_id, &pfkey_net_ops);
+ unregister_pernet_subsys(&pfkey_net_ops);
xfrm_unregister_km(&pfkeyv2_mgr);
sock_unregister(PF_KEY);
proto_unregister(&key_proto);
@@ -3825,7 +3812,7 @@ static int __init ipsec_pfkey_init(void)
err = xfrm_register_km(&pfkeyv2_mgr);
if (err != 0)
goto out_sock_unregister;
- err = register_pernet_gen_subsys(&pfkey_net_id, &pfkey_net_ops);
+ err = ...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/net/pppoe.c | 38 ++++++++------------------------------
1 files changed, 8 insertions(+), 30 deletions(-)
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index a1dcba2..a4ed776 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -1139,59 +1139,37 @@ static struct pppox_proto pppoe_proto = {
static __net_init int pppoe_init_net(struct net *net)
{
- struct pppoe_net *pn;
+ struct pppoe_net *pn = pppoe_pernet(net);
struct proc_dir_entry *pde;
- int err;
-
- pn = kzalloc(sizeof(*pn), GFP_KERNEL);
- if (!pn)
- return -ENOMEM;
rwlock_init(&pn->hash_lock);
- err = net_assign_generic(net, pppoe_net_id, pn);
- if (err)
- goto out;
-
pde = proc_net_fops_create(net, "pppoe", S_IRUGO, &pppoe_seq_fops);
#ifdef CONFIG_PROC_FS
- if (!pde) {
- err = -ENOMEM;
- goto out;
- }
+ if (!pde)
+ return -ENOMEM;
#endif
return 0;
-
-out:
- kfree(pn);
- return err;
}
static __net_exit void pppoe_exit_net(struct net *net)
{
- struct pppoe_net *pn;
-
proc_net_remove(net, "pppoe");
- pn = net_generic(net, pppoe_net_id);
- /*
- * if someone has cached our net then
- * further net_generic call will return NULL
- */
- net_assign_generic(net, pppoe_net_id, NULL);
- kfree(pn);
}
static struct pernet_operations pppoe_net_ops = {
.init = pppoe_init_net,
.exit = pppoe_exit_net,
+ .id = &pppoe_net_id,
+ .size = sizeof(struct pppoe_net),
};
static int __init pppoe_init(void)
{
int err;
- err = register_pernet_gen_device(&pppoe_net_id, &pppoe_net_ops);
+ err = register_pernet_device(&pppoe_net_ops);
if (err)
goto out;
@@ -1212,7 +1190,7 @@ static int __init pppoe_init(void)
out_unregister_pppoe_proto:
proto_unregister(&pppoe_sk_proto);
...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/net/ppp_generic.c | 30 +++++++-----------------------
1 files changed, 7 insertions(+), 23 deletions(-)
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 0a56a77..f671bb8 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -864,12 +864,7 @@ static const struct file_operations ppp_device_fops = {
static __net_init int ppp_init_net(struct net *net)
{
- struct ppp_net *pn;
- int err;
-
- pn = kzalloc(sizeof(*pn), GFP_KERNEL);
- if (!pn)
- return -ENOMEM;
+ struct ppp_net *pn = net_generic(net, ppp_net_id);
idr_init(&pn->units_idr);
mutex_init(&pn->all_ppp_mutex);
@@ -879,32 +874,21 @@ static __net_init int ppp_init_net(struct net *net)
spin_lock_init(&pn->all_channels_lock);
- err = net_assign_generic(net, ppp_net_id, pn);
- if (err) {
- kfree(pn);
- return err;
- }
-
return 0;
}
static __net_exit void ppp_exit_net(struct net *net)
{
- struct ppp_net *pn;
+ struct ppp_net *pn = net_generic(net, ppp_net_id);
- pn = net_generic(net, ppp_net_id);
idr_destroy(&pn->units_idr);
- /*
- * if someone has cached our net then
- * further net_generic call will return NULL
- */
- net_assign_generic(net, ppp_net_id, NULL);
- kfree(pn);
}
static struct pernet_operations ppp_net_ops = {
.init = ppp_init_net,
.exit = ppp_exit_net,
+ .id = &ppp_net_id,
+ .size = sizeof(struct ppp_net),
};
#define PPP_MAJOR 108
@@ -917,7 +901,7 @@ static int __init ppp_init(void)
printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
- err = register_pernet_gen_device(&ppp_net_id, &ppp_net_ops);
+ err = register_pernet_device(&ppp_net_ops);
if (err) {
printk(KERN_ERR "failed to register PPP pernet device (%d)\n", err);
...From: Eric W. Biederman <ebiederm@xmission.com>
No that all of the callers have been updated to set fields in
struct pernet_operations, and simplified to let the network
namespace core handle the allocation and freeing of the storage
for them, remove the surpurpflous methods and update the docs
to the new style.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
include/net/net_namespace.h | 22 ----------------------
include/net/netns/generic.h | 8 +++++---
2 files changed, 5 insertions(+), 25 deletions(-)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 080774b..24a8c55 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -264,28 +264,6 @@ extern void unregister_pernet_subsys(struct pernet_operations *);
extern int register_pernet_device(struct pernet_operations *);
extern void unregister_pernet_device(struct pernet_operations *);
-static inline int register_pernet_gen_subsys(int *id, struct pernet_operations *ops)
-{
- ops->id = id;
- return register_pernet_subsys(ops);
-}
-
-static inline void unregister_pernet_gen_subsys(int id, struct pernet_operations *ops)
-{
- return unregister_pernet_subsys(ops);
-}
-
-static inline int register_pernet_gen_device(int *id, struct pernet_operations *ops)
-{
- ops->id = id;
- return register_pernet_device(ops);
-}
-
-static inline void unregister_pernet_gen_device(int id, struct pernet_operations *ops)
-{
- return unregister_pernet_device(ops);
-}
-
struct ctl_path;
struct ctl_table;
struct ctl_table_header;
diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h
index 0c04fd2..ff4982a 100644
--- a/include/net/netns/generic.h
+++ b/include/net/netns/generic.h
@@ -12,9 +12,11 @@
* stuff on the struct net without explicit struct net modification
*
* The rules are simple:
- * 1. register the ops with register_pernet_gen_device to get the id
- * of your private pointer;
- * 2. call net_assign_generic() to put the ...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/ipv4/ip_gre.c | 24 ++++++------------------
1 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index c5f6af5..f36ce15 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1309,17 +1309,8 @@ static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
static int ipgre_init_net(struct net *net)
{
+ struct ipgre_net *ign = net_generic(net, ipgre_net_id);
int err;
- struct ipgre_net *ign;
-
- err = -ENOMEM;
- ign = kzalloc(sizeof(struct ipgre_net), GFP_KERNEL);
- if (ign == NULL)
- goto err_alloc;
-
- err = net_assign_generic(net, ipgre_net_id, ign);
- if (err < 0)
- goto err_assign;
ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
ipgre_tunnel_setup);
@@ -1340,10 +1331,6 @@ static int ipgre_init_net(struct net *net)
err_reg_dev:
free_netdev(ign->fb_tunnel_dev);
err_alloc_dev:
- /* nothing */
-err_assign:
- kfree(ign);
-err_alloc:
return err;
}
@@ -1357,12 +1344,13 @@ static void ipgre_exit_net(struct net *net)
ipgre_destroy_tunnels(ign, &list);
unregister_netdevice_many(&list);
rtnl_unlock();
- kfree(ign);
}
static struct pernet_operations ipgre_net_ops = {
.init = ipgre_init_net,
.exit = ipgre_exit_net,
+ .id = &ipgre_net_id,
+ .size = sizeof(struct ipgre_net),
};
static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1682,7 +1670,7 @@ static int __init ipgre_init(void)
return -EAGAIN;
}
- err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops);
+ err = register_pernet_device(&ipgre_net_ops);
if (err < 0)
goto gen_device_failed;
@@ -1700,7 +1688,7 @@ out:
tap_ops_failed:
rtnl_link_unregister(&ipgre_link_ops);
...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/ipv6/sit.c | 25 ++++++-------------------
1 files changed, 6 insertions(+), 19 deletions(-)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index d9deaa7..976e682 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1164,17 +1164,8 @@ static void sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head)
static int sit_init_net(struct net *net)
{
+ struct sit_net *sitn = net_generic(net, sit_net_id);
int err;
- struct sit_net *sitn;
-
- err = -ENOMEM;
- sitn = kzalloc(sizeof(struct sit_net), GFP_KERNEL);
- if (sitn == NULL)
- goto err_alloc;
-
- err = net_assign_generic(net, sit_net_id, sitn);
- if (err < 0)
- goto err_assign;
sitn->tunnels[0] = sitn->tunnels_wc;
sitn->tunnels[1] = sitn->tunnels_l;
@@ -1201,37 +1192,33 @@ err_reg_dev:
dev_put(sitn->fb_tunnel_dev);
free_netdev(sitn->fb_tunnel_dev);
err_alloc_dev:
- /* nothing */
-err_assign:
- kfree(sitn);
-err_alloc:
return err;
}
static void sit_exit_net(struct net *net)
{
- struct sit_net *sitn;
+ struct sit_net *sitn = net_generic(net, sit_net_id);
LIST_HEAD(list);
- sitn = net_generic(net, sit_net_id);
rtnl_lock();
sit_destroy_tunnels(sitn, &list);
unregister_netdevice_queue(sitn->fb_tunnel_dev, &list);
unregister_netdevice_many(&list);
rtnl_unlock();
- kfree(sitn);
}
static struct pernet_operations sit_net_ops = {
.init = sit_init_net,
.exit = sit_exit_net,
+ .id = &sit_net_id,
+ .size = sizeof(struct sit_net),
};
static void __exit sit_cleanup(void)
{
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
- unregister_pernet_gen_device(sit_net_id, &sit_net_ops);
+ unregister_pernet_device(&sit_net_ops);
rcu_barrier(); /* Wait for completion of call_rcu()'s */
}
@@ -1246,7 +1233,7 @@ ...From: Eric W. Biederman <ebiederm@xmission.com>
Take advantage of the new pernet automatic storage management,
and stop using compatibility network namespace functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/8021q/vlan.c | 33 +++++++--------------------------
1 files changed, 7 insertions(+), 26 deletions(-)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 225aa2f..91e9073 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -686,47 +686,28 @@ out:
static int vlan_init_net(struct net *net)
{
+ struct vlan_net *vn = net_generic(net, vlan_net_id);
int err;
- struct vlan_net *vn;
-
- err = -ENOMEM;
- vn = kzalloc(sizeof(struct vlan_net), GFP_KERNEL);
- if (vn == NULL)
- goto err_alloc;
-
- err = net_assign_generic(net, vlan_net_id, vn);
- if (err < 0)
- goto err_assign;
vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
err = vlan_proc_init(net);
- if (err < 0)
- goto err_proc;
- return 0;
-
-err_proc:
- /* nothing */
-err_assign:
- kfree(vn);
-err_alloc:
return err;
}
static void vlan_exit_net(struct net *net)
{
- struct vlan_net *vn;
-
- vn = net_generic(net, vlan_net_id);
rtnl_kill_links(net, &vlan_link_ops);
+
vlan_proc_cleanup(net);
- kfree(vn);
}
static struct pernet_operations vlan_net_ops = {
.init = vlan_init_net,
.exit = vlan_exit_net,
+ .id = &vlan_net_id,
+ .size = sizeof(struct vlan_net),
};
static int __init vlan_proto_init(void)
@@ -736,7 +717,7 @@ static int __init vlan_proto_init(void)
pr_info("%s v%s %s\n", vlan_fullname, vlan_version, vlan_copyright);
pr_info("All bugs added by %s\n", vlan_buggyright);
- err = register_pernet_gen_device(&vlan_net_id, &vlan_net_ops);
+ err = register_pernet_device(&vlan_net_ops);
if (err < 0)
goto err0;
@@ -761,7 +742,7 @@ err4:
err3:
unregister_netdevice_notifier(&vlan_notifier_block);
err2:
- unregister_pernet_gen_device(vlan_net_id, ...This implies that the devices we want to batch unregister needs to be part of the same namespace. It might be worth mentioning that in the unregister_netdevice_many() function comments. And, fortunately, it seems that all of the current batch unregister users comply with this requirement. --
No it does not. For the route cache flush we have already done the delayed invalidate per namespace. So we only need to walk the route cache once and simply remove the entries that have been invalidated. For other cases if we really need it, I pass in the first entry of the unregistration list so we can recover the list if needed. The implication is that namespaces are not what is important when batching so it doesn't make sense to turn our list into a pretzel providing information The case I am working on for this patchset is batching of the destruction of devices across namespace cleanup. This change reduces my total number of walks of the route cache from many down to one. Eric --
Right ! I thought that we need to do the cache cleaning per namespace, now my patch looks really stupid :) --
From: "Eric W. Biederman" <ebiederm@xmission.com> I think the idea was that it's important for all pending stale RCU references to the device to be gone before we send out the notifier. And that's why the synchronize_net() comes first. This needs more thought. --
The only case the affects (today) is the invalidation of the route/flow cache.
The routing table until the addition of NETDEV_UNREGISTER_PERNET happened
in the notifier NETDEV_UNREGISTER, which comes before the final synchronize_net.
The routing cache has rcu references to the network device.
So it appears to me that with the current pernet batched routing code cleanup we
can end up calling kfree before all of the call_rcu functions triggered by
rt_do_flush will be run.
netdev_run_todo()
kobject_put()
netdev_release()
kfree()
NETDEV_UNREGISTER_PERCPU
rt_cache_flush(xxx, 0)
rt_do_flush()
rt_free
call_rcu
So it appears to me that moving the final syncrhonize_net() back where it was before
the NETDEV_UNREGISTER_PERNET changes (as I did) is necessary for correctness.
Eric
--
From: ebiederm@xmission.com (Eric W. Biederman) Ok, it appears your right. Thanks for the analysis. I'll look over the rest of your series now. --
