The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-123.1.2.vz7.5.7 ------> commit de376c7c241bb28faec8413bac9b3d991e51853c Author: Cyrill Gorcunov <gorcu...@odin.com> Date: Thu May 28 17:38:28 2015 +0400
venet: Cleanup ip address on ve exit While been playing with c/r of a container with IP assigned I found that VE exit (ve_drop_context) is happening earlier than venet::exit routine which means the ve::ve_netns = nil when we enter into ip releasing procedure. | zap_pid_ns_processes | ve_stop_ns | ve_exit_ns | ve_drop_context(ve); | put_net(ve->ve_netns); | ve->ve_netns = NULL; Releasing ve context that early looks logical because ve::ve_netns is a part of ve structure itself, in turn ip address and venet device is rather a side feature provided by venet module. So because we do not create nested venet devices and adding some additional ioctl makes code only harder to read I propose to use VE exit hook to cleanup ip address. With the patch applied I can checkpoint/restore container with venet configured. Signed-off-by: Cyrill Gorcunov <gorcu...@odin.com> Acked-by: Andrey Vagin <ava...@odin.com> CC: Vladimir Davydov <vdavy...@odin.com> CC: Konstantin Khorenko <khore...@odin.com> CC: Pavel Emelyanov <xe...@odin.com> --- drivers/net/venetdev.c | 71 +++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/drivers/net/venetdev.c b/drivers/net/venetdev.c index bb7f0be..6b7d8fc7 100644 --- a/drivers/net/venetdev.c +++ b/drivers/net/venetdev.c @@ -881,9 +881,13 @@ static int do_ve_ip_map(struct ve_struct *ve, int op, struct ve_addr_struct *add switch (op) { case VE_IP_ADD: - err = -ESRCH; - if (ve->is_running) - err = veip_entry_add(ve, addr); + /* + * FIXME We should check if VE + * is either running or in restore + * state instead of allowing adding + * address arbitrary. + */ + err = veip_entry_add(ve, addr); break; case VE_IP_DEL: @@ -1113,51 +1117,39 @@ err: return err; } -static __net_exit void venet_exit_net(struct list_head *net_exit_list) +static struct pernet_operations venet_net_ops = { + .init = venet_init_net, +}; + +/* + * VE context dropping is happening earlier than + * pernet_operations::exit method so we can't + * rely on it and do the cleanup earlier. + */ +static void venet_stop_notifier(void *data) { - struct net *net; - struct ve_struct *env; - struct net_device *dev; - LIST_HEAD(netdev_kill_list); + struct ve_struct *env = data; - list_for_each_entry(net, net_exit_list, exit_list) { - env = net->owner_ve; - if (env->ve_netns != net) - continue; + if (env->ve_netns) { + struct net_device *dev = env->_venet_dev; venet_ext_clean(env); veip_stop(env); - dev = env->_venet_dev; - if (dev == NULL) - continue; - - rtnl_lock(); - unregister_netdevice_queue(dev, &netdev_kill_list); - rtnl_unlock(); - } - - rtnl_lock(); - unregister_netdevice_many(&netdev_kill_list); - rtnl_unlock(); - - list_for_each_entry(net, net_exit_list, exit_list) { - env = net->owner_ve; - if (env->ve_netns != net) - continue; - - dev = env->_venet_dev; - if (dev == NULL) - continue; - - env->_venet_dev = NULL; - free_netdev(dev); + if (dev) { + env->_venet_dev = NULL; + rtnl_lock(); + unregister_netdevice(dev); + rtnl_unlock(); + free_netdev(dev); + } } } -static struct pernet_operations venet_net_ops = { - .init = venet_init_net, - .exit_batch = venet_exit_net, +static struct ve_hook venet_stop_hook = { + .fini = venet_stop_notifier, + .priority = HOOK_PRIO_FINISHING, + .owner = THIS_MODULE, }; static int venet_changelink(struct net_device *dev, struct nlattr *tb[], @@ -1241,6 +1233,7 @@ __init int venet_init(void) vzioctl_register(&venetcalls); vzmon_register_veaddr_print_cb(veaddr_seq_print); + ve_hook_register(VE_SS_CHAIN, &venet_stop_hook); return rtnl_link_register(&venet_link_ops); _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel