Bump kernel to 4.4.159
authorRISCi_ATOM <bob@bobcall.me>
Mon, 1 Oct 2018 13:58:55 +0000 (09:58 -0400)
committerRISCi_ATOM <bob@bobcall.me>
Mon, 1 Oct 2018 13:58:55 +0000 (09:58 -0400)
 - Removed ar71xx/203-MIPS-ath79-fix-restart.patch : upstreamed
 - Removed generic/051-000{1,2,5}-ovl-*.patch : Upstreamed, excluding is_merge rename

include/kernel-version.mk
target/linux/ar71xx/patches-4.4/203-MIPS-ath79-fix-restart.patch [deleted file]
target/linux/generic/patches-4.4/051-0001-ovl-rename-is_merge-to-is_lowest.patch [deleted file]
target/linux/generic/patches-4.4/051-0002-ovl-override-creds-with-the-ones-from-the-superblock.patch [deleted file]
target/linux/generic/patches-4.4/051-0005-ovl-proper-cleanup-of-workdir.patch [deleted file]

index a33e54975ad08415d5c5bca80cacd85051f9850b..91422a3287612ff50e96652ec9f33b49eaa3689e 100644 (file)
@@ -2,9 +2,9 @@
 
 LINUX_RELEASE?=1
 
-LINUX_VERSION-4.4 = .153
+LINUX_VERSION-4.4 = .159
 
-LINUX_KERNEL_HASH-4.4.153 = e2b8bcbf5d0f70ce90fb4b19407331e6d31cd0700fa2d1bec32c4659e7fcbba4
+LINUX_KERNEL_HASH-4.4.159 = d464fea1f888ada3a55c3aea1c05ba9fd2d4edd7ffb152369faace18a285998b
 
 ifdef KERNEL_PATCHVER
   LINUX_VERSION:=$(KERNEL_PATCHVER)$(strip $(LINUX_VERSION-$(KERNEL_PATCHVER)))
diff --git a/target/linux/ar71xx/patches-4.4/203-MIPS-ath79-fix-restart.patch b/target/linux/ar71xx/patches-4.4/203-MIPS-ath79-fix-restart.patch
deleted file mode 100644 (file)
index 77773ea..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
---- a/arch/mips/ath79/setup.c
-+++ b/arch/mips/ath79/setup.c
-@@ -44,6 +44,7 @@ static char ath79_sys_type[ATH79_SYS_TYP
- static void ath79_restart(char *command)
- {
-+      local_irq_disable();
-       ath79_device_reset_set(AR71XX_RESET_FULL_CHIP);
-       for (;;)
-               if (cpu_wait)
---- a/arch/mips/include/asm/mach-ath79/ath79.h
-+++ b/arch/mips/include/asm/mach-ath79/ath79.h
-@@ -134,6 +134,7 @@ static inline u32 ath79_pll_rr(unsigned
- static inline void ath79_reset_wr(unsigned reg, u32 val)
- {
-       __raw_writel(val, ath79_reset_base + reg);
-+      (void) __raw_readl(ath79_reset_base + reg); /* flush */
- }
- static inline u32 ath79_reset_rr(unsigned reg)
diff --git a/target/linux/generic/patches-4.4/051-0001-ovl-rename-is_merge-to-is_lowest.patch b/target/linux/generic/patches-4.4/051-0001-ovl-rename-is_merge-to-is_lowest.patch
deleted file mode 100644 (file)
index 79140b9..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-From 56656e960b555cb98bc414382566dcb59aae99a2 Mon Sep 17 00:00:00 2001
-From: Miklos Szeredi <mszeredi@redhat.com>
-Date: Mon, 21 Mar 2016 17:31:46 +0100
-Subject: [PATCH] ovl: rename is_merge to is_lowest
-
-The 'is_merge' is an historical naming from when only a single lower layer
-could exist.  With the introduction of multiple lower layers the meaning of
-this flag was changed to mean only the "lowest layer" (while all lower
-layers were being merged).
-
-So now 'is_merge' is inaccurate and hence renaming to 'is_lowest'
-
-Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
----
- fs/overlayfs/readdir.c | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
---- a/fs/overlayfs/readdir.c
-+++ b/fs/overlayfs/readdir.c
-@@ -36,7 +36,7 @@ struct ovl_dir_cache {
- struct ovl_readdir_data {
-       struct dir_context ctx;
--      bool is_merge;
-+      bool is_lowest;
-       struct rb_root root;
-       struct list_head *list;
-       struct list_head middle;
-@@ -139,9 +139,9 @@ static int ovl_cache_entry_add_rb(struct
-       return 0;
- }
--static int ovl_fill_lower(struct ovl_readdir_data *rdd,
--                        const char *name, int namelen,
--                        loff_t offset, u64 ino, unsigned int d_type)
-+static int ovl_fill_lowest(struct ovl_readdir_data *rdd,
-+                         const char *name, int namelen,
-+                         loff_t offset, u64 ino, unsigned int d_type)
- {
-       struct ovl_cache_entry *p;
-@@ -193,10 +193,10 @@ static int ovl_fill_merge(struct dir_con
-               container_of(ctx, struct ovl_readdir_data, ctx);
-       rdd->count++;
--      if (!rdd->is_merge)
-+      if (!rdd->is_lowest)
-               return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type);
-       else
--              return ovl_fill_lower(rdd, name, namelen, offset, ino, d_type);
-+              return ovl_fill_lowest(rdd, name, namelen, offset, ino, d_type);
- }
- static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
-@@ -289,7 +289,7 @@ static int ovl_dir_read_merged(struct de
-               .ctx.actor = ovl_fill_merge,
-               .list = list,
-               .root = RB_ROOT,
--              .is_merge = false,
-+              .is_lowest = false,
-       };
-       int idx, next;
-@@ -306,7 +306,7 @@ static int ovl_dir_read_merged(struct de
-                        * allows offsets to be reasonably constant
-                        */
-                       list_add(&rdd.middle, rdd.list);
--                      rdd.is_merge = true;
-+                      rdd.is_lowest = true;
-                       err = ovl_dir_read(&realpath, &rdd);
-                       list_del(&rdd.middle);
-               }
diff --git a/target/linux/generic/patches-4.4/051-0002-ovl-override-creds-with-the-ones-from-the-superblock.patch b/target/linux/generic/patches-4.4/051-0002-ovl-override-creds-with-the-ones-from-the-superblock.patch
deleted file mode 100644 (file)
index 208bc61..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-From 3fe6e52f062643676eb4518d68cee3bc1272091b Mon Sep 17 00:00:00 2001
-From: Antonio Murdaca <amurdaca@redhat.com>
-Date: Thu, 7 Apr 2016 15:48:25 +0200
-Subject: [PATCH] ovl: override creds with the ones from the superblock mounter
-
-In user namespace the whiteout creation fails with -EPERM because the
-current process isn't capable(CAP_SYS_ADMIN) when setting xattr.
-
-A simple reproducer:
-
-$ mkdir upper lower work merged lower/dir
-$ sudo mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged
-$ unshare -m -p -f -U -r bash
-
-Now as root in the user namespace:
-
-\# touch merged/dir/{1,2,3} # this will force a copy up of lower/dir
-\# rm -fR merged/*
-
-This ends up failing with -EPERM after the files in dir has been
-correctly deleted:
-
-unlinkat(4, "2", 0)                     = 0
-unlinkat(4, "1", 0)                     = 0
-unlinkat(4, "3", 0)                     = 0
-close(4)                                = 0
-unlinkat(AT_FDCWD, "merged/dir", AT_REMOVEDIR) = -1 EPERM (Operation not
-permitted)
-
-Interestingly, if you don't place files in merged/dir you can remove it,
-meaning if upper/dir does not exist, creating the char device file works
-properly in that same location.
-
-This patch uses ovl_sb_creator_cred() to get the cred struct from the
-superblock mounter and override the old cred with these new ones so that
-the whiteout creation is possible because overlay is wrong in assuming that
-the creds it will get with prepare_creds will be in the initial user
-namespace.  The old cap_raise game is removed in favor of just overriding
-the old cred struct.
-
-This patch also drops from ovl_copy_up_one() the following two lines:
-
-override_cred->fsuid = stat->uid;
-override_cred->fsgid = stat->gid;
-
-This is because the correct uid and gid are taken directly with the stat
-struct and correctly set with ovl_set_attr().
-
-Signed-off-by: Antonio Murdaca <runcom@redhat.com>
-Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
----
- fs/overlayfs/copy_up.c   | 26 +------------------
- fs/overlayfs/dir.c       | 67 ++++--------------------------------------------
- fs/overlayfs/overlayfs.h |  1 +
- fs/overlayfs/readdir.c   | 14 +++-------
- fs/overlayfs/super.c     | 18 ++++++++++++-
- 5 files changed, 27 insertions(+), 99 deletions(-)
-
---- a/fs/overlayfs/copy_up.c
-+++ b/fs/overlayfs/copy_up.c
-@@ -317,7 +317,6 @@ int ovl_copy_up_one(struct dentry *paren
-       struct dentry *upperdir;
-       struct dentry *upperdentry;
-       const struct cred *old_cred;
--      struct cred *override_cred;
-       char *link = NULL;
-       if (WARN_ON(!workdir))
-@@ -336,28 +335,7 @@ int ovl_copy_up_one(struct dentry *paren
-                       return PTR_ERR(link);
-       }
--      err = -ENOMEM;
--      override_cred = prepare_creds();
--      if (!override_cred)
--              goto out_free_link;
--
--      override_cred->fsuid = stat->uid;
--      override_cred->fsgid = stat->gid;
--      /*
--       * CAP_SYS_ADMIN for copying up extended attributes
--       * CAP_DAC_OVERRIDE for create
--       * CAP_FOWNER for chmod, timestamp update
--       * CAP_FSETID for chmod
--       * CAP_CHOWN for chown
--       * CAP_MKNOD for mknod
--       */
--      cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
--      cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
--      cap_raise(override_cred->cap_effective, CAP_FOWNER);
--      cap_raise(override_cred->cap_effective, CAP_FSETID);
--      cap_raise(override_cred->cap_effective, CAP_CHOWN);
--      cap_raise(override_cred->cap_effective, CAP_MKNOD);
--      old_cred = override_creds(override_cred);
-+      old_cred = ovl_override_creds(dentry->d_sb);
-       err = -EIO;
-       if (lock_rename(workdir, upperdir) != NULL) {
-@@ -380,9 +358,7 @@ int ovl_copy_up_one(struct dentry *paren
- out_unlock:
-       unlock_rename(workdir, upperdir);
-       revert_creds(old_cred);
--      put_cred(override_cred);
--out_free_link:
-       if (link)
-               free_page((unsigned long) link);
---- a/fs/overlayfs/dir.c
-+++ b/fs/overlayfs/dir.c
-@@ -408,28 +408,13 @@ static int ovl_create_or_link(struct den
-               err = ovl_create_upper(dentry, inode, &stat, link, hardlink);
-       } else {
-               const struct cred *old_cred;
--              struct cred *override_cred;
--              err = -ENOMEM;
--              override_cred = prepare_creds();
--              if (!override_cred)
--                      goto out_iput;
--
--              /*
--               * CAP_SYS_ADMIN for setting opaque xattr
--               * CAP_DAC_OVERRIDE for create in workdir, rename
--               * CAP_FOWNER for removing whiteout from sticky dir
--               */
--              cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
--              cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
--              cap_raise(override_cred->cap_effective, CAP_FOWNER);
--              old_cred = override_creds(override_cred);
-+              old_cred = ovl_override_creds(dentry->d_sb);
-               err = ovl_create_over_whiteout(dentry, inode, &stat, link,
-                                              hardlink);
-               revert_creds(old_cred);
--              put_cred(override_cred);
-       }
-       if (!err)
-@@ -659,32 +644,11 @@ static int ovl_do_remove(struct dentry *
-       if (OVL_TYPE_PURE_UPPER(type)) {
-               err = ovl_remove_upper(dentry, is_dir);
-       } else {
--              const struct cred *old_cred;
--              struct cred *override_cred;
--
--              err = -ENOMEM;
--              override_cred = prepare_creds();
--              if (!override_cred)
--                      goto out_drop_write;
--
--              /*
--               * CAP_SYS_ADMIN for setting xattr on whiteout, opaque dir
--               * CAP_DAC_OVERRIDE for create in workdir, rename
--               * CAP_FOWNER for removing whiteout from sticky dir
--               * CAP_FSETID for chmod of opaque dir
--               * CAP_CHOWN for chown of opaque dir
--               */
--              cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
--              cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
--              cap_raise(override_cred->cap_effective, CAP_FOWNER);
--              cap_raise(override_cred->cap_effective, CAP_FSETID);
--              cap_raise(override_cred->cap_effective, CAP_CHOWN);
--              old_cred = override_creds(override_cred);
-+              const struct cred *old_cred = ovl_override_creds(dentry->d_sb);
-               err = ovl_remove_and_whiteout(dentry, is_dir);
-               revert_creds(old_cred);
--              put_cred(override_cred);
-       }
- out_drop_write:
-       ovl_drop_write(dentry);
-@@ -723,7 +687,6 @@ static int ovl_rename2(struct inode *old
-       bool new_is_dir = false;
-       struct dentry *opaquedir = NULL;
-       const struct cred *old_cred = NULL;
--      struct cred *override_cred = NULL;
-       err = -EINVAL;
-       if (flags & ~(RENAME_EXCHANGE | RENAME_NOREPLACE))
-@@ -792,26 +755,8 @@ static int ovl_rename2(struct inode *old
-       old_opaque = !OVL_TYPE_PURE_UPPER(old_type);
-       new_opaque = !OVL_TYPE_PURE_UPPER(new_type);
--      if (old_opaque || new_opaque) {
--              err = -ENOMEM;
--              override_cred = prepare_creds();
--              if (!override_cred)
--                      goto out_drop_write;
--
--              /*
--               * CAP_SYS_ADMIN for setting xattr on whiteout, opaque dir
--               * CAP_DAC_OVERRIDE for create in workdir
--               * CAP_FOWNER for removing whiteout from sticky dir
--               * CAP_FSETID for chmod of opaque dir
--               * CAP_CHOWN for chown of opaque dir
--               */
--              cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
--              cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
--              cap_raise(override_cred->cap_effective, CAP_FOWNER);
--              cap_raise(override_cred->cap_effective, CAP_FSETID);
--              cap_raise(override_cred->cap_effective, CAP_CHOWN);
--              old_cred = override_creds(override_cred);
--      }
-+      if (old_opaque || new_opaque)
-+              old_cred = ovl_override_creds(old->d_sb);
-       if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {
-               opaquedir = ovl_check_empty_and_clear(new);
-@@ -942,10 +887,8 @@ out_dput_old:
- out_unlock:
-       unlock_rename(new_upperdir, old_upperdir);
- out_revert_creds:
--      if (old_opaque || new_opaque) {
-+      if (old_opaque || new_opaque)
-               revert_creds(old_cred);
--              put_cred(override_cred);
--      }
- out_drop_write:
-       ovl_drop_write(old);
- out:
---- a/fs/overlayfs/overlayfs.h
-+++ b/fs/overlayfs/overlayfs.h
-@@ -150,6 +150,7 @@ void ovl_drop_write(struct dentry *dentr
- bool ovl_dentry_is_opaque(struct dentry *dentry);
- void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque);
- bool ovl_is_whiteout(struct dentry *dentry);
-+const struct cred *ovl_override_creds(struct super_block *sb);
- void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry);
- struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
-                         unsigned int flags);
---- a/fs/overlayfs/readdir.c
-+++ b/fs/overlayfs/readdir.c
-@@ -36,6 +36,7 @@ struct ovl_dir_cache {
- struct ovl_readdir_data {
-       struct dir_context ctx;
-+      struct dentry *dentry;
-       bool is_lowest;
-       struct rb_root root;
-       struct list_head *list;
-@@ -205,17 +206,8 @@ static int ovl_check_whiteouts(struct de
-       struct ovl_cache_entry *p;
-       struct dentry *dentry;
-       const struct cred *old_cred;
--      struct cred *override_cred;
--
--      override_cred = prepare_creds();
--      if (!override_cred)
--              return -ENOMEM;
--      /*
--       * CAP_DAC_OVERRIDE for lookup
--       */
--      cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
--      old_cred = override_creds(override_cred);
-+      old_cred = ovl_override_creds(rdd->dentry->d_sb);
-       err = mutex_lock_killable(&dir->d_inode->i_mutex);
-       if (!err) {
-@@ -231,7 +223,6 @@ static int ovl_check_whiteouts(struct de
-               mutex_unlock(&dir->d_inode->i_mutex);
-       }
-       revert_creds(old_cred);
--      put_cred(override_cred);
-       return err;
- }
-@@ -287,6 +278,7 @@ static int ovl_dir_read_merged(struct de
-       struct path realpath;
-       struct ovl_readdir_data rdd = {
-               .ctx.actor = ovl_fill_merge,
-+              .dentry = dentry,
-               .list = list,
-               .root = RB_ROOT,
-               .is_lowest = false,
---- a/fs/overlayfs/super.c
-+++ b/fs/overlayfs/super.c
-@@ -42,6 +42,8 @@ struct ovl_fs {
-       long lower_namelen;
-       /* pathnames of lower and upper dirs, for show_options */
-       struct ovl_config config;
-+      /* creds of process who forced instantiation of super block */
-+      const struct cred *creator_cred;
- };
- struct ovl_dir_cache;
-@@ -246,6 +248,13 @@ bool ovl_is_whiteout(struct dentry *dent
-       return inode && IS_WHITEOUT(inode);
- }
-+const struct cred *ovl_override_creds(struct super_block *sb)
-+{
-+      struct ovl_fs *ofs = sb->s_fs_info;
-+
-+      return override_creds(ofs->creator_cred);
-+}
-+
- static bool ovl_is_opaquedir(struct dentry *dentry)
- {
-       int res;
-@@ -587,6 +596,7 @@ static void ovl_put_super(struct super_b
-       kfree(ufs->config.lowerdir);
-       kfree(ufs->config.upperdir);
-       kfree(ufs->config.workdir);
-+      put_cred(ufs->creator_cred);
-       kfree(ufs);
- }
-@@ -1087,10 +1097,14 @@ static int ovl_fill_super(struct super_b
-       else
-               sb->s_d_op = &ovl_dentry_operations;
-+      ufs->creator_cred = prepare_creds();
-+      if (!ufs->creator_cred)
-+              goto out_put_lower_mnt;
-+
-       err = -ENOMEM;
-       oe = ovl_alloc_entry(numlower);
-       if (!oe)
--              goto out_put_lower_mnt;
-+              goto out_put_cred;
-       root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, oe));
-       if (!root_dentry)
-@@ -1123,6 +1137,8 @@ static int ovl_fill_super(struct super_b
- out_free_oe:
-       kfree(oe);
-+out_put_cred:
-+      put_cred(ufs->creator_cred);
- out_put_lower_mnt:
-       for (i = 0; i < ufs->numlower; i++)
-               mntput(ufs->lower_mnt[i]);
diff --git a/target/linux/generic/patches-4.4/051-0005-ovl-proper-cleanup-of-workdir.patch b/target/linux/generic/patches-4.4/051-0005-ovl-proper-cleanup-of-workdir.patch
deleted file mode 100644 (file)
index e7ed81d..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-From eea2fb4851e9dcbab6b991aaf47e2e024f1f55a0 Mon Sep 17 00:00:00 2001
-From: Miklos Szeredi <mszeredi@redhat.com>
-Date: Thu, 1 Sep 2016 11:11:59 +0200
-Subject: [PATCH] ovl: proper cleanup of workdir
-
-When mounting overlayfs it needs a clean "work" directory under the
-supplied workdir.
-
-Previously the mount code removed this directory if it already existed and
-created a new one.  If the removal failed (e.g. directory was not empty)
-then it fell back to a read-only mount not using the workdir.
-
-While this has never been reported, it is possible to get a non-empty
-"work" dir from a previous mount of overlayfs in case of crash in the
-middle of an operation using the work directory.
-
-In this case the left over state should be discarded and the overlay
-filesystem will be consistent, guaranteed by the atomicity of operations on
-moving to/from the workdir to the upper layer.
-
-This patch implements cleaning out any files left in workdir.  It is
-implemented using real recursion for simplicity, but the depth is limited
-to 2, because the worst case is that of a directory containing whiteouts
-under "work".
-
-Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-Cc: <stable@vger.kernel.org>
----
- fs/overlayfs/overlayfs.h |  2 ++
- fs/overlayfs/readdir.c   | 63 +++++++++++++++++++++++++++++++++++++++++++++++-
- fs/overlayfs/super.c     |  2 +-
- 3 files changed, 65 insertions(+), 2 deletions(-)
-
---- a/fs/overlayfs/overlayfs.h
-+++ b/fs/overlayfs/overlayfs.h
-@@ -165,6 +165,8 @@ int ovl_check_empty_dir(struct dentry *d
- void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list);
- void ovl_cache_free(struct list_head *list);
- int ovl_check_d_type_supported(struct path *realpath);
-+void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
-+                        struct dentry *dentry, int level);
- /* inode.c */
- int ovl_setattr(struct dentry *dentry, struct iattr *attr);
---- a/fs/overlayfs/readdir.c
-+++ b/fs/overlayfs/readdir.c
-@@ -248,7 +248,7 @@ static inline int ovl_dir_read(struct pa
-                       err = rdd->err;
-       } while (!err && rdd->count);
--      if (!err && rdd->first_maybe_whiteout)
-+      if (!err && rdd->first_maybe_whiteout && rdd->dentry)
-               err = ovl_check_whiteouts(realpath->dentry, rdd);
-       fput(realfile);
-@@ -610,3 +610,64 @@ int ovl_check_d_type_supported(struct pa
-       return rdd.d_type_supported;
- }
-+
-+static void ovl_workdir_cleanup_recurse(struct path *path, int level)
-+{
-+      int err;
-+      struct inode *dir = path->dentry->d_inode;
-+      LIST_HEAD(list);
-+      struct ovl_cache_entry *p;
-+      struct ovl_readdir_data rdd = {
-+              .ctx.actor = ovl_fill_merge,
-+              .dentry = NULL,
-+              .list = &list,
-+              .root = RB_ROOT,
-+              .is_lowest = false,
-+      };
-+
-+      err = ovl_dir_read(path, &rdd);
-+      if (err)
-+              goto out;
-+
-+      mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
-+      list_for_each_entry(p, &list, l_node) {
-+              struct dentry *dentry;
-+
-+              if (p->name[0] == '.') {
-+                      if (p->len == 1)
-+                              continue;
-+                      if (p->len == 2 && p->name[1] == '.')
-+                              continue;
-+              }
-+              dentry = lookup_one_len(p->name, path->dentry, p->len);
-+              if (IS_ERR(dentry))
-+                      continue;
-+              if (dentry->d_inode)
-+                      ovl_workdir_cleanup(dir, path->mnt, dentry, level);
-+              dput(dentry);
-+      }
-+      mutex_unlock(&dir->i_mutex);
-+out:
-+      ovl_cache_free(&list);
-+}
-+
-+void 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;
-+      }
-+
-+      err = ovl_do_rmdir(dir, dentry);
-+      if (err) {
-+              struct path path = { .mnt = mnt, .dentry = dentry };
-+
-+              mutex_unlock(&dir->i_mutex);
-+              ovl_workdir_cleanup_recurse(&path, level + 1);
-+              mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
-+              ovl_cleanup(dir, dentry);
-+      }
-+}
---- a/fs/overlayfs/super.c
-+++ b/fs/overlayfs/super.c
-@@ -784,7 +784,7 @@ retry:
-                               goto out_dput;
-                       retried = true;
--                      ovl_cleanup(dir, work);
-+                      ovl_workdir_cleanup(dir, mnt, work, 0);
-                       dput(work);
-                       goto retry;
-               }