[CRIU] [PATCH 4/5] files: Cleanup ghost subdirectories
Andrei Vagin
avagin at gmail.com
Wed Feb 27 09:49:18 MSK 2019
On Tue, Feb 26, 2019 at 12:13:34PM +0300, Cyrill Gorcunov wrote:
> In case if some of ghost directories has transient entries
> which we had to creat while restoring they cause inability
> to remove toplevel directory due to ENOTEMPTY error raised.
>
> To address this we do the following:
>
> - when ghost entries are created remember which
> dentries were created in @remap->subdirs
>
> - when we're cleaning them up we remove these
> transient entries up to @remap->subdirs
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
> ---
> criu/files-reg.c | 51 ++++++++++++++++++++++++++++++++++++----
> criu/include/files-reg.h | 2 ++
> 2 files changed, 49 insertions(+), 4 deletions(-)
>
> diff --git a/criu/files-reg.c b/criu/files-reg.c
> index a36b60142760..f304efa8c770 100644
> --- a/criu/files-reg.c
> +++ b/criu/files-reg.c
> @@ -355,6 +355,7 @@ static int ghost_apply_metadata(const char *path, GhostFileEntry *gfe)
>
> static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, struct cr_img *img)
> {
> + const char *subdir = NULL;
> struct mount_info *mi;
> char path[PATH_MAX];
> int ret, root_len;
> @@ -391,7 +392,8 @@ static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, struct cr_im
> if ((ret = mknod(path, gfe->mode, gfe->rdev)) < 0)
> msg = "Can't create node for ghost dev";
> } else if (S_ISDIR(gfe->mode)) {
> - if ((ret = mkdirpat(AT_FDCWD, path, gfe->mode)) < 0)
> + ret = mkdirpat_precise(AT_FDCWD, path, gfe->mode, &subdir);
> + if (ret < 0)
> msg = "Can't make ghost dir";
> } else {
> if ((ret = mkreg_ghost(path, gfe, img)) < 0)
> @@ -415,6 +417,14 @@ static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, struct cr_im
> strcpy(gf->remap.rpath, path + root_len);
> pr_debug("Remap rpath is %s\n", gf->remap.rpath);
>
> + /*
> + * Save nested dirs for better cleanup.
> + */
> + if (subdir && subdir != path) {
> + gf->remap.subdir = gf->remap.rpath;
> + gf->remap.subdir += subdir - path - root_len;
> + }
> +
> ret = -1;
> if (ghost_apply_metadata(path, gfe))
> goto err;
> @@ -758,6 +768,9 @@ static int order_remap_dirs(void)
> pr_debug("remap: ghost ord %3s %s\n",
> ri->rfi->remap->is_dir ? "dir" : "fil",
> ri->rfi->path);
> + if (ri->rfi->remap->subdir)
> + pr_debug("remap:\tnew subdir %s\n",
> + ri->rfi->remap->subdir);
> }
> }
>
> @@ -783,6 +796,31 @@ int prepare_remaps(void)
> return ret ? : order_remap_dirs();
> }
>
> +static int cleanup_subdir(int dirfd, struct file_remap *remap)
> +{
> + char *pos;
> + int ret;
> +
> + if (!remap->subdir)
> + return 0;
> +
> + /*
> + * Note that we're modifying @remap->rpath but
> + * caller is dropping this variable a bit later
> + * anyway!
> + */
> + for (pos = strrchr(remap->subdir, '/'); pos;
> + pos = strrchr(pos, '/')) {
> + *pos = '\0';
> + pr_debug("\tUnlink remap subdir %s\n", remap->rpath);
> + ret = unlinkat(dirfd, remap->rpath, AT_REMOVEDIR);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> static int clean_ghost_dir(int rmntns_root, struct remap_info *ri)
> {
> struct file_remap *remap = ri->rfi->remap;
> @@ -791,10 +829,15 @@ static int clean_ghost_dir(int rmntns_root, struct remap_info *ri)
> * When deleting ghost directories here is two issues:
> * - names might duplicate, so we may receive ENOENT
> * and should not treat it as an error
> + * - some ghost directories might have transient entries
> + * which we have to make during former path restoration
> */
> - if (ret)
> - return errno == ENOENT ? 0 : -errno;
> - return 0;
> + if (ret) {
> + if (errno == ENOENT)
> + ret = 0;
> + } else
> + ret = cleanup_subdir(rmntns_root, remap);
should we call cleanup_subdir() if errno == ENOENT?
> + return ret;
> }
>
> static int clean_one_remap(struct remap_info *ri)
> diff --git a/criu/include/files-reg.h b/criu/include/files-reg.h
> index ec142db8c882..9b1339353878 100644
> --- a/criu/include/files-reg.h
> +++ b/criu/include/files-reg.h
> @@ -10,6 +10,7 @@ struct cr_imgset;
> struct fd_parms;
>
> struct file_remap {
> + char *subdir;
> char *rpath;
> bool is_dir;
> int rmnt_id;
> @@ -20,6 +21,7 @@ struct file_remap {
> static inline void file_remap_init(struct file_remap *remap)
> {
> remap->rpath = NULL;
> + remap->subdir = NULL;
> remap->is_dir = false;
> remap->uid = -1;
> remap->gid = -1;
> --
> 2.20.1
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list