[Devel] [PATCH RHEL7 COMMIT] venet: Cleanup ip address on ve exit

Konstantin Khorenko khorenko at virtuozzo.com
Thu May 28 06:38:28 PDT 2015


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 <gorcunov at 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 <gorcunov at odin.com>
    Acked-by: Andrey Vagin <avagin at odin.com>
    
    CC: Vladimir Davydov <vdavydov at odin.com>
    CC: Konstantin Khorenko <khorenko at odin.com>
    CC: Pavel Emelyanov <xemul at 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);
 



More information about the Devel mailing list