On Wed, May 20, 2015 at 08:21:59PM +0300, Cyrill Gorcunov wrote:
> 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.

Is it posibale to unload the venet module? Is it ok with this patch?

> 
> Signed-off-by: Cyrill Gorcunov <gorcu...@odin.com>
> CC: Vladimir Davydov <vdavy...@odin.com>
> CC: Konstantin Khorenko <khore...@odin.com>
> CC: Pavel Emelyanov <xe...@odin.com>
> CC: Andrey Vagin <ava...@odin.com>
> ---
> 
> 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
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to