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

Reply via email to