Stas,
please see my comment below.

On 28.09.2015 16:16, Stanislav Kinsburskiy wrote:
> From: Stanislav Kinsburskiy <[email protected]>
> 
> There could be a unix socket (thanks to supervisord), which was unlinked, but
> also a hardlink to it was created prior to unlink.
> This basically means, that unlinked socket and it's hardlink points to the
> same inode.
> In such a case we can't just recreate unlinked socket in /tmp directory, like
> we did before. Becuase it this case connect to linked dentry will fail becuase
> of different inode.
> We have to try to find another dentry, poiting to this inode and dump it's
> path, which will be used to recreate unlinked socket on restore.
> We need also to dump dentry mount, so we can lookup it on restore. BTW, in
> this case socket will be restored via unix_bind_to_mntref() instead of
> unix_bind_to_path().
> 
> Signed-off-by: Stanislav Kinsburskiy <[email protected]>
> ---
>  include/linux/cpt_image.h |    5 ++++
>  kernel/cpt/cpt_socket.c   |   52 
> +++++++++++++++++++++++++++++++--------------
>  2 files changed, 41 insertions(+), 16 deletions(-)
> 
> diff --git a/include/linux/cpt_image.h b/include/linux/cpt_image.h
> index 30a625d..75fa878 100644
> --- a/include/linux/cpt_image.h
> +++ b/include/linux/cpt_image.h
> @@ -963,6 +963,11 @@ struct cpt_sock_image
>  
>       __u32   cpt_i_uid;
>       __u32   cpt_i_gid;
> +
> +     __u32   cpt_d_alias[128/4];
> +
> +     __u32   cpt_d_aliaslen;
> +     __u32   __cpt_pad15;
>  } __attribute__ ((aligned (8)));

size of this structure increases ==> CPT image version should be increased ==> 
it's impossible to migrate from new kernels to old ones.
Am I missed something?

>  struct cpt_sockmc_image {
> diff --git a/kernel/cpt/cpt_socket.c b/kernel/cpt/cpt_socket.c
> index 863aefe..88b4bd7 100644
> --- a/kernel/cpt/cpt_socket.c
> +++ b/kernel/cpt/cpt_socket.c
> @@ -543,28 +543,47 @@ static int cpt_dump_unix_socket(struct sock *sk, struct 
> cpt_sock_image *v, cpt_c
>  
>       if (unix_sk(sk)->dentry) {
>               struct dentry *d = unix_sk(sk)->dentry;
> +             unsigned long pg = __get_free_page(GFP_KERNEL);
> +             struct path p;
> +             char *path, *cpt_path;
> +             int err = 0;
> +             __u32 *path_len;
> +
> +             if (!pg)
> +                     return -ENOMEM;
> +
>               v->cpt_i_uid = d->d_inode->i_uid;
>               v->cpt_i_gid = d->d_inode->i_gid;
>  
>               if (IS_ROOT(d) || !d_unhashed(d)) {
> -                     int err = 0;
> -                     struct path p = {unix_sk(sk)->mnt, d};
> -                     char *path;
> -                     unsigned long pg = __get_free_page(GFP_KERNEL);
> +                     p.dentry = dget(d);
> +                     cpt_path = ((char*)v->cpt_laddr) + 2;
> +                     path_len = &v->cpt_laddrlen;
> +             } else {
> +                     v->cpt_sockflags |= CPT_SOCK_DELETED;
> +                     v->cpt_d_aliaslen = 0;
> +                     p.dentry = NULL;
>  
> -                     if (!pg)
> -                             return -ENOMEM;
> +                     if (d->d_inode->i_nlink != 0) {
> +                             p.dentry = get_linked_dentry(d, 
> unix_sk(sk)->mnt, ctx);
> +                             cpt_path = (char *)v->cpt_d_alias;
> +                             path_len = &v->cpt_d_aliaslen;
> +                     }
> +             }
> +
> +             if (!IS_ERR_OR_NULL(p.dentry)) {
> +                     p.mnt = unix_sk(sk)->mnt;
>  
>                       path = d_path(&p, (char *)pg, PAGE_SIZE);
>  
>                       if (!IS_ERR(path)) {
>                               int len = strlen(path);
>                               if (len < 126) {
> -                                     strcpy(((char*)v->cpt_laddr)+2, path); 
> -                                     v->cpt_laddrlen = len + 2;
> -                             } else {
> -                                     wprintk_ctx("af_unix path is too long: 
> %s (%s)\n", path, ((char*)v->cpt_laddr)+2);
> -                             }
> +                                     strcpy(cpt_path, path);
> +                                     *path_len = len + 2;
> +                             } else
> +                                     wprintk_ctx("af_unix path is too long: 
> %s (%s)\n", path, cpt_path);
> +
>                               if (cpt_need_delayfs(unix_sk(sk)->mnt))
>                                       v->cpt_sockflags |= CPT_SOCK_DELAYED;
>  
> @@ -575,11 +594,12 @@ static int cpt_dump_unix_socket(struct sock *sk, struct 
> cpt_sock_image *v, cpt_c
>                               eprintk_ctx("cannot get path of an af_unix 
> socket\n");
>                               err = PTR_ERR(path);
>                       }
> -                     free_page(pg);
> -                     if (err)
> -                             return err;
> -             } else
> -                     v->cpt_sockflags |= CPT_SOCK_DELETED;
> +                     dput(p.dentry);
> +             }
> +
> +             free_page(pg);
> +             if (err)
> +                     return err;
>       }
>  
>       /* If the socket is connected, find its peer. If peer is not
> 
> _______________________________________________
> Devel mailing list
> [email protected]
> https://lists.openvz.org/mailman/listinfo/devel
> 
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to