ovl: cleanup non-empty directories in ovl_indexdir_cleanup()
authorAmir Goldstein <amir73il@gmail.com>
Fri, 3 Apr 2020 04:58:49 +0000 (07:58 +0300)
committerMiklos Szeredi <mszeredi@redhat.com>
Wed, 13 May 2020 09:11:24 +0000 (11:11 +0200)
Teach ovl_indexdir_cleanup() to remove temp directories containing
whiteouts to prepare for using index dir instead of work dir for removing
merge directories.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/readdir.c

index 0db23ba..723d177 100644 (file)
@@ -484,12 +484,6 @@ struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index)
        return upper;
 }
 
-/* Is this a leftover from create/whiteout of directory index entry? */
-static bool ovl_is_temp_index(struct dentry *index)
-{
-       return index->d_name.name[0] == '#';
-}
-
 /*
  * Verify that an index entry name matches the origin file handle stored in
  * OVL_XATTR_ORIGIN and that origin file handle can be decoded to lower path.
@@ -507,11 +501,6 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index)
        if (!d_inode(index))
                return 0;
 
-       /* Cleanup leftover from index create/cleanup attempt */
-       err = -ESTALE;
-       if (ovl_is_temp_index(index))
-               goto fail;
-
        err = -EINVAL;
        if (index->d_name.len < sizeof(struct ovl_fb)*2)
                goto fail;
index e6f3670..e00b1ff 100644 (file)
@@ -394,8 +394,8 @@ void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list);
 void ovl_cache_free(struct list_head *list);
 void ovl_dir_cache_free(struct inode *inode);
 int ovl_check_d_type_supported(struct path *realpath);
-void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
-                        struct dentry *dentry, int level);
+int ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
+                       struct dentry *dentry, int level);
 int ovl_indexdir_cleanup(struct ovl_fs *ofs);
 
 /* inode.c */
index e452ff7..20f5310 100644 (file)
@@ -1071,14 +1071,13 @@ out:
        ovl_cache_free(&list);
 }
 
-void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
+int ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
                         struct dentry *dentry, int level)
 {
        int err;
 
        if (!d_is_dir(dentry) || level > 1) {
-               ovl_cleanup(dir, dentry);
-               return;
+               return ovl_cleanup(dir, dentry);
        }
 
        err = ovl_do_rmdir(dir, dentry);
@@ -1088,8 +1087,10 @@ void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
                inode_unlock(dir);
                ovl_workdir_cleanup_recurse(&path, level + 1);
                inode_lock_nested(dir, I_MUTEX_PARENT);
-               ovl_cleanup(dir, dentry);
+               err = ovl_cleanup(dir, dentry);
        }
+
+       return err;
 }
 
 int ovl_indexdir_cleanup(struct ovl_fs *ofs)
@@ -1128,6 +1129,13 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs)
                        index = NULL;
                        break;
                }
+               /* Cleanup leftover from index create/cleanup attempt */
+               if (index->d_name.name[0] == '#') {
+                       err = ovl_workdir_cleanup(dir, path.mnt, index, 1);
+                       if (err)
+                               break;
+                       goto next;
+               }
                err = ovl_verify_index(ofs, index);
                if (!err) {
                        goto next;