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 <[email protected]> CC: Vladimir Davydov <[email protected]> CC: Konstantin Khorenko <[email protected]> CC: Pavel Emelyanov <[email protected]> CC: Andrey Vagin <[email protected]> --- If there some better idea, please share. drivers/net/venetdev.c | 71 ++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) Index: linux-pcs7.git/drivers/net/venetdev.c =================================================================== --- linux-pcs7.git.orig/drivers/net/venetdev.c +++ linux-pcs7.git/drivers/net/venetdev.c @@ -881,9 +881,13 @@ static int do_ve_ip_map(struct ve_struct 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 [email protected] https://lists.openvz.org/mailman/listinfo/devel
