To incorporate the following encapsulated changes:

05607e3cb465 5.14 20211018
9e5e47e46da7 aufs: tiny, fix an editing failure
ee28de7d4b6c aufs: support FUSE branch a little more
71dfddc73039 aufs: bugfix, stop omitting path->mnt
03a3ee3199ae 5.14 20210906

from https://github.com/sfjro/aufs5-standalone.git

Signed-off-by: Paul Gortmaker <paul.gortma...@windriver.com>
---
 fs/aufs/cpup.c                 |  6 ++-
 fs/aufs/debug.c                |  5 ++-
 fs/aufs/dentry.c               | 35 +++++++++------
 fs/aufs/dentry.h               |  2 +-
 fs/aufs/dirren.c               |  9 ++--
 fs/aufs/export.c               |  2 +-
 fs/aufs/i_op_del.c             | 13 ++++--
 fs/aufs/i_op_ren.c             | 14 ++++--
 fs/aufs/plink.c                | 62 ++++++++++++-------------
 fs/aufs/vfsub.c                | 33 ++++++++------
 fs/aufs/vfsub.h                | 10 ++---
 fs/aufs/whout.c                | 82 +++++++++++++++++-----------------
 fs/aufs/whout.h                |  4 +-
 fs/aufs/xino.c                 | 11 ++---
 include/uapi/linux/aufs_type.h |  2 +-
 15 files changed, 162 insertions(+), 128 deletions(-)

diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c
index dbaa01a55904..5b8b6b25200e 100644
--- a/fs/aufs/cpup.c
+++ b/fs/aufs/cpup.c
@@ -745,11 +745,13 @@ static int au_do_ren_after_cpup(struct au_cp_generic 
*cpg, struct path *h_path)
 {
        int err;
        struct dentry *dentry, *h_dentry, *h_parent, *parent;
+       struct path h_ppath;
        struct inode *h_dir;
        aufs_bindex_t bdst;
 
        dentry = cpg->dentry;
        bdst = cpg->bdst;
+       h_ppath.mnt = au_sbr_mnt(dentry->d_sb, bdst);
        h_dentry = au_h_dptr(dentry, bdst);
        if (!au_ftest_cpup(cpg->flags, OVERWRITE)) {
                dget(h_dentry);
@@ -761,9 +763,9 @@ static int au_do_ren_after_cpup(struct au_cp_generic *cpg, 
struct path *h_path)
        } else {
                err = 0;
                parent = dget_parent(dentry);
-               h_parent = au_h_dptr(parent, bdst);
+               h_ppath.dentry = au_h_dptr(parent, bdst);
                dput(parent);
-               h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
+               h_path->dentry = vfsub_lkup_one(&dentry->d_name, &h_ppath);
                if (IS_ERR(h_path->dentry))
                        err = PTR_ERR(h_path->dentry);
        }
diff --git a/fs/aufs/debug.c b/fs/aufs/debug.c
index f7fa23c1a9bc..3394083eadd7 100644
--- a/fs/aufs/debug.c
+++ b/fs/aufs/debug.c
@@ -383,7 +383,10 @@ void __au_dbg_verify_dinode(struct dentry *dentry, const 
char *func, int line)
                        AuDbgDentry(dentry);
                        AuDbgInode(inode);
                        au_debug_off();
-                       BUG();
+                       if (au_test_fuse(h_inode->i_sb))
+                               WARN_ON_ONCE(1);
+                       else
+                               BUG();
                }
        }
 }
diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c
index 4b63daab7220..1bae481ab105 100644
--- a/fs/aufs/dentry.c
+++ b/fs/aufs/dentry.c
@@ -36,6 +36,7 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
        struct inode *h_inode;
        struct au_branch *br;
        struct user_namespace *h_userns;
+       struct path h_path;
        int wh_found, opq;
        unsigned char wh_able;
        const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
@@ -44,10 +45,12 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
 
        wh_found = 0;
        br = au_sbr(dentry->d_sb, bindex);
+       h_path.dentry = h_parent;
+       h_path.mnt = au_br_mnt(br);
        h_userns = au_br_userns(br);
        wh_able = !!au_br_whable(br->br_perm);
        if (wh_able)
-               wh_found = au_wh_test(h_userns, h_parent, &args->whname,
+               wh_found = au_wh_test(h_userns, &h_path, &args->whname,
                                      ignore_perm);
        h_dentry = ERR_PTR(wh_found);
        if (!wh_found)
@@ -63,9 +66,9 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
 
 real_lookup:
        if (!ignore_perm)
-               h_dentry = vfsub_lkup_one(args->name, h_parent);
+               h_dentry = vfsub_lkup_one(args->name, &h_path);
        else
-               h_dentry = au_sio_lkup_one(h_userns, args->name, h_parent);
+               h_dentry = au_sio_lkup_one(h_userns, args->name, &h_path);
        if (IS_ERR(h_dentry)) {
                if (PTR_ERR(h_dentry) == -ENAMETOOLONG
                    && !allow_neg)
@@ -99,8 +102,9 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
            || (d_really_is_positive(dentry) && !d_is_dir(dentry)))
                goto out; /* success */
 
+       h_path.dentry = h_dentry;
        inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
-       opq = au_diropq_test(h_userns, h_dentry);
+       opq = au_diropq_test(h_userns, &h_path);
        inode_unlock_shared(h_inode);
        if (opq > 0)
                au_set_dbdiropq(dentry, bindex);
@@ -246,18 +250,18 @@ int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t 
btop,
 }
 
 struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr 
*name,
-                              struct dentry *parent)
+                              struct path *ppath)
 {
        struct dentry *dentry;
        int wkq_err;
 
-       if (!au_test_h_perm_sio(userns, d_inode(parent), MAY_EXEC))
-               dentry = vfsub_lkup_one(name, parent);
+       if (!au_test_h_perm_sio(userns, d_inode(ppath->dentry), MAY_EXEC))
+               dentry = vfsub_lkup_one(name, ppath);
        else {
                struct vfsub_lkup_one_args args = {
                        .errp   = &dentry,
                        .name   = name,
-                       .parent = parent
+                       .ppath  = ppath
                };
 
                wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
@@ -274,18 +278,20 @@ struct dentry *au_sio_lkup_one(struct user_namespace 
*userns, struct qstr *name,
 int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh)
 {
        int err;
-       struct dentry *parent, *h_parent, *h_dentry;
+       struct dentry *parent, *h_dentry;
        struct au_branch *br;
        struct user_namespace *h_userns;
+       struct path h_ppath;
 
        parent = dget_parent(dentry);
-       h_parent = au_h_dptr(parent, bindex);
        br = au_sbr(dentry->d_sb, bindex);
+       h_ppath.dentry = au_h_dptr(parent, bindex);
+       h_ppath.mnt = au_br_mnt(br);
        h_userns = au_br_userns(br);
        if (wh)
-               h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
+               h_dentry = au_whtmp_lkup(h_ppath.dentry, br, &dentry->d_name);
        else
-               h_dentry = au_sio_lkup_one(h_userns, &dentry->d_name, h_parent);
+               h_dentry = au_sio_lkup_one(h_userns, &dentry->d_name, &h_ppath);
        err = PTR_ERR(h_dentry);
        if (IS_ERR(h_dentry))
                goto out;
@@ -360,6 +366,7 @@ static int au_h_verify_dentry(struct dentry *h_dentry, 
struct dentry *h_parent,
        struct inode *h_inode;
        struct dentry *h_d;
        struct super_block *h_sb;
+       struct path h_ppath;
 
        err = 0;
        memset(&ia, -1, sizeof(ia));
@@ -374,7 +381,9 @@ static int au_h_verify_dentry(struct dentry *h_dentry, 
struct dentry *h_parent,
                goto out;
 
        /* main purpose is namei.c:cached_lookup() and d_revalidate */
-       h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
+       h_ppath.dentry = h_parent;
+       h_ppath.mnt = au_br_mnt(br);
+       h_d = vfsub_lkup_one(&h_dentry->d_name, &h_ppath);
        err = PTR_ERR(h_d);
        if (IS_ERR(h_d))
                goto out;
diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h
index a1df828fd132..26d1332d269b 100644
--- a/fs/aufs/dentry.h
+++ b/fs/aufs/dentry.h
@@ -74,7 +74,7 @@ struct au_do_lookup_args {
 extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
 struct au_branch;
 struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr 
*name,
-                              struct dentry *parent);
+                              struct path *ppath);
 int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode 
*h_dir,
                struct dentry *h_parent, struct au_branch *br);
 
diff --git a/fs/aufs/dirren.c b/fs/aufs/dirren.c
index 42f590603c91..341b706f5e13 100644
--- a/fs/aufs/dirren.c
+++ b/fs/aufs/dirren.c
@@ -263,11 +263,11 @@ static int au_dr_hino(struct super_block *sb, 
aufs_bindex_t bindex,
                dir = d_inode(path->dentry);
                inode_lock_nested(dir, AuLsc_I_CHILD);
        }
-       hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry);
+       hinopath.mnt = path->mnt;
+       hinopath.dentry = vfsub_lkup_one(&hinoname, (struct path *)path);
        err = PTR_ERR(hinopath.dentry);
        if (IS_ERR(hinopath.dentry))
                goto out_unlock;
-       hinopath.mnt = path->mnt;
 
        err = 0;
        flags = O_RDONLY;
@@ -619,7 +619,7 @@ static int au_drinfo_do_store(struct au_drinfo_store *w,
        AuDebugOn(elm
                  && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm)));
 
-       infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry,
+       infopath.dentry = vfsub_lookup_one_len(w->whname, &w->h_ppath,
                                               w->whnamelen);
        AuTraceErrPtr(infopath.dentry);
        if (IS_ERR(infopath.dentry)) {
@@ -1003,8 +1003,7 @@ static struct au_drinfo *au_drinfo_do_load(struct path 
*h_ppath,
        unlocked = 0;
        h_dir = d_inode(h_ppath->dentry);
        inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
-       infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry,
-                                              whnamelen);
+       infopath.dentry = vfsub_lookup_one_len(whname, h_ppath, whnamelen);
        if (IS_ERR(infopath.dentry)) {
                drinfo = (void *)infopath.dentry;
                goto out;
diff --git a/fs/aufs/export.c b/fs/aufs/export.c
index abd0897101bf..0aa20ceddd1a 100644
--- a/fs/aufs/export.c
+++ b/fs/aufs/export.c
@@ -406,7 +406,7 @@ static struct dentry *au_lkup_by_ino(struct path *path, 
ino_t ino,
 
        /* do not call vfsub_lkup_one() */
        dir = d_inode(parent);
-       dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen);
+       dentry = vfsub_lookup_one_len_unlocked(arg.name, path, arg.namelen);
        AuTraceErrPtr(dentry);
        if (IS_ERR(dentry))
                goto out_name;
diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
index a11987581548..b7b5a4f69e98 100644
--- a/fs/aufs/i_op_del.c
+++ b/fs/aufs/i_op_del.c
@@ -94,6 +94,9 @@ int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
        umode_t h_mode;
        struct dentry *h_dentry, *h_latest;
        struct inode *h_inode;
+       struct path h_ppath;
+       struct super_block *sb;
+       struct au_branch *br;
        struct user_namespace *h_userns;
 
        h_dentry = au_h_dptr(dentry, bindex);
@@ -132,13 +135,17 @@ int au_may_del(struct dentry *dentry, aufs_bindex_t 
bindex,
         * let's try heavy test.
         */
        err = -EACCES;
-       h_userns = au_sbr_userns(dentry->d_sb, bindex);
-       if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)
+       sb = dentry->d_sb;
+       br = au_sbr(sb, bindex);
+       h_userns = au_br_userns(br);
+       if (unlikely(!au_opt_test(au_mntflags(sb), DIRPERM1)
                     && au_test_h_perm(h_userns, d_inode(h_parent),
                                       MAY_EXEC | MAY_WRITE)))
                goto out;
 
-       h_latest = au_sio_lkup_one(h_userns, &dentry->d_name, h_parent);
+       h_ppath.dentry = h_parent;
+       h_ppath.mnt = au_br_mnt(br);
+       h_latest = au_sio_lkup_one(h_userns, &dentry->d_name, &h_ppath);
        err = -EIO;
        if (IS_ERR(h_latest))
                goto out;
diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c
index 022b6e8cef11..b8cf8c5dd020 100644
--- a/fs/aufs/i_op_ren.c
+++ b/fs/aufs/i_op_ren.c
@@ -150,9 +150,12 @@ static void au_ren_rev_rename(int err, struct au_ren_args 
*a)
 {
        int rerr;
        struct inode *delegated;
+       struct path h_ppath = {
+               .dentry = a->src_h_parent,
+               .mnt    = a->h_path.mnt
+       };
 
-       a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name,
-                                         a->src_h_parent);
+       a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, &h_ppath);
        rerr = PTR_ERR(a->h_path.dentry);
        if (IS_ERR(a->h_path.dentry)) {
                RevertFailure("lkup one %pd", a->src_dentry);
@@ -179,9 +182,12 @@ static void au_ren_rev_whtmp(int err, struct au_ren_args 
*a)
 {
        int rerr;
        struct inode *delegated;
+       struct path h_ppath = {
+               .dentry = a->dst_h_parent,
+               .mnt    = a->h_path.mnt
+       };
 
-       a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name,
-                                         a->dst_h_parent);
+       a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, &h_ppath);
        rerr = PTR_ERR(a->h_path.dentry);
        if (IS_ERR(a->h_path.dentry)) {
                RevertFailure("lkup one %pd", a->dst_dentry);
diff --git a/fs/aufs/plink.c b/fs/aufs/plink.c
index 518350041aa2..82e51a50191c 100644
--- a/fs/aufs/plink.c
+++ b/fs/aufs/plink.c
@@ -206,35 +206,35 @@ static int plink_name(char *name, int len, struct inode 
*inode,
 struct au_do_plink_lkup_args {
        struct dentry **errp;
        struct qstr *tgtname;
-       struct dentry *h_parent;
-       struct au_branch *br;
+       struct path *h_ppath;
 };
 
 static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
-                                      struct dentry *h_parent,
-                                      struct au_branch *br)
+                                      struct path *h_ppath)
 {
        struct dentry *h_dentry;
        struct inode *h_inode;
 
-       h_inode = d_inode(h_parent);
+       h_inode = d_inode(h_ppath->dentry);
        inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2);
-       h_dentry = vfsub_lkup_one(tgtname, h_parent);
+       h_dentry = vfsub_lkup_one(tgtname, h_ppath);
        inode_unlock_shared(h_inode);
+
        return h_dentry;
 }
 
 static void au_call_do_plink_lkup(void *args)
 {
        struct au_do_plink_lkup_args *a = args;
-       *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
+       *a->errp = au_do_plink_lkup(a->tgtname, a->h_ppath);
 }
 
 /* lookup the plink-ed @inode under the branch at @bindex */
 struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
 {
-       struct dentry *h_dentry, *h_parent;
+       struct dentry *h_dentry;
        struct au_branch *br;
+       struct path h_ppath;
        int wkq_err;
        char a[PLINK_NAME_LEN];
        struct qstr tgtname = QSTR_INIT(a, 0);
@@ -242,40 +242,39 @@ struct dentry *au_plink_lkup(struct inode *inode, 
aufs_bindex_t bindex)
        AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
 
        br = au_sbr(inode->i_sb, bindex);
-       h_parent = br->br_wbr->wbr_plink;
+       h_ppath.dentry = br->br_wbr->wbr_plink;
+       h_ppath.mnt = au_br_mnt(br);
        tgtname.len = plink_name(a, sizeof(a), inode, bindex);
 
        if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
                struct au_do_plink_lkup_args args = {
                        .errp           = &h_dentry,
                        .tgtname        = &tgtname,
-                       .h_parent       = h_parent,
-                       .br             = br
+                       .h_ppath        = &h_ppath
                };
 
                wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
                if (unlikely(wkq_err))
                        h_dentry = ERR_PTR(wkq_err);
        } else
-               h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
+               h_dentry = au_do_plink_lkup(&tgtname, &h_ppath);
 
        return h_dentry;
 }
 
 /* create a pseudo-link */
-static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
-                     struct dentry *h_dentry, struct au_branch *br)
+static int do_whplink(struct qstr *tgt, struct path *h_ppath,
+                     struct dentry *h_dentry)
 {
        int err;
-       struct path h_path = {
-               .mnt = au_br_mnt(br)
-       };
+       struct path h_path;
        struct inode *h_dir, *delegated;
 
-       h_dir = d_inode(h_parent);
+       h_dir = d_inode(h_ppath->dentry);
        inode_lock_nested(h_dir, AuLsc_I_CHILD2);
+       h_path.mnt = h_ppath->mnt;
 again:
-       h_path.dentry = vfsub_lkup_one(tgt, h_parent);
+       h_path.dentry = vfsub_lkup_one(tgt, h_ppath);
        err = PTR_ERR(h_path.dentry);
        if (IS_ERR(h_path.dentry))
                goto out;
@@ -316,28 +315,30 @@ static int do_whplink(struct qstr *tgt, struct dentry 
*h_parent,
 struct do_whplink_args {
        int *errp;
        struct qstr *tgt;
-       struct dentry *h_parent;
+       struct path *h_ppath;
        struct dentry *h_dentry;
-       struct au_branch *br;
 };
 
 static void call_do_whplink(void *args)
 {
        struct do_whplink_args *a = args;
-       *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
+       *a->errp = do_whplink(a->tgt, a->h_ppath, a->h_dentry);
 }
 
 static int whplink(struct dentry *h_dentry, struct inode *inode,
-                  aufs_bindex_t bindex, struct au_branch *br)
+                  aufs_bindex_t bindex)
 {
        int err, wkq_err;
+       struct au_branch *br;
        struct au_wbr *wbr;
-       struct dentry *h_parent;
+       struct path h_ppath;
        char a[PLINK_NAME_LEN];
        struct qstr tgtname = QSTR_INIT(a, 0);
 
-       wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
-       h_parent = wbr->wbr_plink;
+       br = au_sbr(inode->i_sb, bindex);
+       wbr = br->br_wbr;
+       h_ppath.dentry = wbr->wbr_plink;
+       h_ppath.mnt = au_br_mnt(br);
        tgtname.len = plink_name(a, sizeof(a), inode, bindex);
 
        /* always superio. */
@@ -345,15 +346,14 @@ static int whplink(struct dentry *h_dentry, struct inode 
*inode,
                struct do_whplink_args args = {
                        .errp           = &err,
                        .tgt            = &tgtname,
-                       .h_parent       = h_parent,
-                       .h_dentry       = h_dentry,
-                       .br             = br
+                       .h_ppath        = &h_ppath,
+                       .h_dentry       = h_dentry
                };
                wkq_err = au_wkq_wait(call_do_whplink, &args);
                if (unlikely(wkq_err))
                        err = wkq_err;
        } else
-               err = do_whplink(&tgtname, h_parent, h_dentry, br);
+               err = do_whplink(&tgtname, &h_ppath, h_dentry);
 
        return err;
 }
@@ -403,7 +403,7 @@ void au_plink_append(struct inode *inode, aufs_bindex_t 
bindex,
                if (cnt > AUFS_PLINK_WARN)
                        AuWarn1(msg ", %d\n", cnt);
 #undef msg
-               err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
+               err = whplink(h_dentry, inode, bindex);
                if (unlikely(err)) {
                        pr_warn("err %d, damaged pseudo link.\n", err);
                        au_hbl_del(&icntnr->plink, hbl);
diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c
index f905aa22ac3b..e91b65a54a23 100644
--- a/fs/aufs/vfsub.c
+++ b/fs/aufs/vfsub.c
@@ -58,6 +58,11 @@ int vfsub_update_h_iattr(struct path *h_path, int *did)
        struct kstat st;
        struct super_block *h_sb;
 
+       /*
+        * Always needs h_path->mnt for LSM or FUSE branch.
+        */
+       AuDebugOn(!h_path->mnt);
+
        /* for remote fs, leave work for its getattr or d_revalidate */
        /* for bad i_attr fs, handle them in aufs_getattr() */
        /* still some fs may acquire i_mutex. we need to skip them */
@@ -166,38 +171,38 @@ int vfsub_kern_path(const char *name, unsigned int flags, 
struct path *path)
 }
 
 struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
-                                            struct dentry *parent, int len)
+                                            struct path *ppath, int len)
 {
-       struct path path = {
-               .mnt = NULL
-       };
+       struct path path;
 
-       path.dentry = lookup_one_len_unlocked(name, parent, len);
+       path.dentry = lookup_one_len_unlocked(name, ppath->dentry, len);
        if (IS_ERR(path.dentry))
                goto out;
-       if (d_is_positive(path.dentry))
+       if (d_is_positive(path.dentry)) {
+               path.mnt = ppath->mnt;
                vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
+       }
 
 out:
        AuTraceErrPtr(path.dentry);
        return path.dentry;
 }
 
-struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
+struct dentry *vfsub_lookup_one_len(const char *name, struct path *ppath,
                                    int len)
 {
-       struct path path = {
-               .mnt = NULL
-       };
+       struct path path;
 
        /* VFS checks it too, but by WARN_ON_ONCE() */
-       IMustLock(d_inode(parent));
+       IMustLock(d_inode(ppath->dentry));
 
-       path.dentry = lookup_one_len(name, parent, len);
+       path.dentry = lookup_one_len(name, ppath->dentry, len);
        if (IS_ERR(path.dentry))
                goto out;
-       if (d_is_positive(path.dentry))
+       if (d_is_positive(path.dentry)) {
+               path.mnt = ppath->mnt;
                vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
+       }
 
 out:
        AuTraceErrPtr(path.dentry);
@@ -207,7 +212,7 @@ struct dentry *vfsub_lookup_one_len(const char *name, 
struct dentry *parent,
 void vfsub_call_lkup_one(void *args)
 {
        struct vfsub_lkup_one_args *a = args;
-       *a->errp = vfsub_lkup_one(a->name, a->parent);
+       *a->errp = vfsub_lkup_one(a->name, a->ppath);
 }
 
 /* ---------------------------------------------------------------------- */
diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
index 9441fda85f35..0c76f421b95f 100644
--- a/fs/aufs/vfsub.h
+++ b/fs/aufs/vfsub.h
@@ -103,20 +103,20 @@ int vfsub_atomic_open(struct inode *dir, struct dentry 
*dentry,
 int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
 
 struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
-                                            struct dentry *parent, int len);
-struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
+                                            struct path *ppath, int len);
+struct dentry *vfsub_lookup_one_len(const char *name, struct path *ppath,
                                    int len);
 
 struct vfsub_lkup_one_args {
        struct dentry **errp;
        struct qstr *name;
-       struct dentry *parent;
+       struct path *ppath;
 };
 
 static inline struct dentry *vfsub_lkup_one(struct qstr *name,
-                                           struct dentry *parent)
+                                           struct path *ppath)
 {
-       return vfsub_lookup_one_len(name->name, parent, name->len);
+       return vfsub_lookup_one_len(name->name, ppath, name->len);
 }
 
 void vfsub_call_lkup_one(void *args);
diff --git a/fs/aufs/whout.c b/fs/aufs/whout.c
index 8849e6239dd1..a6d30f64b0c0 100644
--- a/fs/aufs/whout.c
+++ b/fs/aufs/whout.c
@@ -61,19 +61,19 @@ int au_wh_name_alloc(struct qstr *wh, const struct qstr 
*name)
 /* ---------------------------------------------------------------------- */
 
 /*
- * test if the @wh_name exists under @h_parent.
+ * test if the @wh_name exists under @h_ppath.
  * @try_sio specifies the necessary of super-io.
  */
-int au_wh_test(struct user_namespace *h_userns, struct dentry *h_parent,
+int au_wh_test(struct user_namespace *h_userns, struct path *h_ppath,
               struct qstr *wh_name, int try_sio)
 {
        int err;
        struct dentry *wh_dentry;
 
        if (!try_sio)
-               wh_dentry = vfsub_lkup_one(wh_name, h_parent);
+               wh_dentry = vfsub_lkup_one(wh_name, h_ppath);
        else
-               wh_dentry = au_sio_lkup_one(h_userns, wh_name, h_parent);
+               wh_dentry = au_sio_lkup_one(h_userns, wh_name, h_ppath);
        err = PTR_ERR(wh_dentry);
        if (IS_ERR(wh_dentry)) {
                if (err == -ENAMETOOLONG)
@@ -100,15 +100,15 @@ int au_wh_test(struct user_namespace *h_userns, struct 
dentry *h_parent,
 }
 
 /*
- * test if the @h_dentry sets opaque or not.
+ * test if the @h_path->dentry sets opaque or not.
  */
-int au_diropq_test(struct user_namespace *h_userns, struct dentry *h_dentry)
+int au_diropq_test(struct user_namespace *h_userns, struct path *h_path)
 {
        int err;
        struct inode *h_dir;
 
-       h_dir = d_inode(h_dentry);
-       err = au_wh_test(h_userns, h_dentry, &diropq_name,
+       h_dir = d_inode(h_path->dentry);
+       err = au_wh_test(h_userns, h_path, &diropq_name,
                         au_test_h_perm_sio(h_userns, h_dir, MAY_EXEC));
        return err;
 }
@@ -126,6 +126,7 @@ struct dentry *au_whtmp_lkup(struct dentry *h_parent, 
struct au_branch *br,
        /* strict atomic_t is unnecessary here */
        static unsigned short cnt;
        struct qstr qs;
+       struct path h_ppath;
        struct user_namespace *h_userns;
 
        BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
@@ -150,11 +151,13 @@ struct dentry *au_whtmp_lkup(struct dentry *h_parent, 
struct au_branch *br,
        *p++ = '.';
        AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
 
+       h_ppath.dentry = h_parent;
+       h_ppath.mnt = au_br_mnt(br);
        h_userns = au_br_userns(br);
        qs.name = name;
        for (i = 0; i < 3; i++) {
                sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
-               dentry = au_sio_lkup_one(h_userns, &qs, h_parent);
+               dentry = au_sio_lkup_one(h_userns, &qs, &h_ppath);
                if (IS_ERR(dentry) || d_is_negative(dentry))
                        goto out_name;
                dput(dentry);
@@ -248,21 +251,20 @@ int au_wh_unlink_dentry(struct inode *h_dir, struct path 
*h_path,
        return err;
 }
 
-static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
-                         struct au_branch *br)
+static int unlink_wh_name(struct path *h_ppath, struct qstr *wh)
 {
        int err;
-       struct path h_path = {
-               .mnt = au_br_mnt(br)
-       };
+       struct path h_path;
 
        err = 0;
-       h_path.dentry = vfsub_lkup_one(wh, h_parent);
+       h_path.dentry = vfsub_lkup_one(wh, h_ppath);
        if (IS_ERR(h_path.dentry))
                err = PTR_ERR(h_path.dentry);
        else {
-               if (d_is_reg(h_path.dentry))
-                       err = do_unlink_wh(d_inode(h_parent), &h_path);
+               if (d_is_reg(h_path.dentry)) {
+                       h_path.mnt = h_ppath->mnt;
+                       err = do_unlink_wh(d_inode(h_ppath->dentry), &h_path);
+               }
                dput(h_path.dentry);
        }
 
@@ -702,15 +704,17 @@ static int link_or_create_wh(struct super_block *sb, 
aufs_bindex_t bindex,
 static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
                                unsigned int flags)
 {
-       struct dentry *opq_dentry, *h_dentry;
+       struct dentry *opq_dentry;
        struct super_block *sb;
        struct au_branch *br;
+       struct path h_path;
        int err;
 
        sb = dentry->d_sb;
        br = au_sbr(sb, bindex);
-       h_dentry = au_h_dptr(dentry, bindex);
-       opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
+       h_path.dentry = au_h_dptr(dentry, bindex);
+       h_path.mnt = au_br_mnt(br);
+       opq_dentry = vfsub_lkup_one(&diropq_name, &h_path);
        if (IS_ERR(opq_dentry))
                goto out;
 
@@ -721,11 +725,8 @@ static struct dentry *do_diropq(struct dentry *dentry, 
aufs_bindex_t bindex,
                        goto out; /* success */
                }
        } else {
-               struct path tmp = {
-                       .dentry = opq_dentry,
-                       .mnt    = au_br_mnt(br)
-               };
-               err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp);
+               h_path.dentry = opq_dentry;
+               err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &h_path);
                if (!err)
                        au_set_dbdiropq(dentry, -1);
        }
@@ -791,11 +792,14 @@ struct dentry *au_wh_lkup(struct dentry *h_parent, struct 
qstr *base_name,
        int err;
        struct qstr wh_name;
        struct dentry *wh_dentry;
+       struct path h_path;
 
        err = au_wh_name_alloc(&wh_name, base_name);
        wh_dentry = ERR_PTR(err);
        if (!err) {
-               wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
+               h_path.dentry = h_parent;
+               h_path.mnt = au_br_mnt(br);
+               wh_dentry = vfsub_lkup_one(&wh_name, &h_path);
                au_kfree_try_rcu(wh_name.name);
        }
        return wh_dentry;
@@ -830,8 +834,8 @@ struct dentry *au_wh_create(struct dentry *dentry, 
aufs_bindex_t bindex,
 /* ---------------------------------------------------------------------- */
 
 /* Delete all whiteouts in this directory on branch bindex. */
-static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
-                          aufs_bindex_t bindex, struct au_branch *br)
+static int del_wh_children(struct path *h_path, struct au_nhash *whlist,
+                          aufs_bindex_t bindex)
 {
        int err;
        unsigned long ul, n;
@@ -861,7 +865,7 @@ static int del_wh_children(struct dentry *h_dentry, struct 
au_nhash *whlist,
                        if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
                                memcpy(p, str->name, str->len);
                                wh_name.len = AUFS_WH_PFX_LEN + str->len;
-                               err = unlink_wh_name(h_dentry, &wh_name, br);
+                               err = unlink_wh_name(h_path, &wh_name);
                                if (!err)
                                        continue;
                                break;
@@ -880,16 +884,15 @@ static int del_wh_children(struct dentry *h_dentry, 
struct au_nhash *whlist,
 
 struct del_wh_children_args {
        int *errp;
-       struct dentry *h_dentry;
+       struct path *h_path;
        struct au_nhash *whlist;
        aufs_bindex_t bindex;
-       struct au_branch *br;
 };
 
 static void call_del_wh_children(void *args)
 {
        struct del_wh_children_args *a = args;
-       *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
+       *a->errp = del_wh_children(a->h_path, a->whlist, a->bindex);
 }
 
 /* ---------------------------------------------------------------------- */
@@ -941,7 +944,7 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
 {
        int err;
        unsigned int h_nlink;
-       struct path h_tmp;
+       struct path wh_path;
        struct inode *wh_inode, *h_dir;
        struct au_branch *br;
        struct user_namespace *h_userns;
@@ -950,6 +953,8 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
        IMustLock(h_dir);
 
        br = au_sbr(dir->i_sb, bindex);
+       wh_path.dentry = wh_dentry;
+       wh_path.mnt = au_br_mnt(br);
        h_userns = au_br_userns(br);
        wh_inode = d_inode(wh_dentry);
        inode_lock_nested(wh_inode, AuLsc_I_CHILD);
@@ -959,15 +964,14 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t 
bindex,
         * it means this whlist may have an obsoleted entry.
         */
        if (!au_test_h_perm_sio(h_userns, wh_inode, MAY_EXEC | MAY_WRITE))
-               err = del_wh_children(wh_dentry, whlist, bindex, br);
+               err = del_wh_children(&wh_path, whlist, bindex);
        else {
                int wkq_err;
                struct del_wh_children_args args = {
                        .errp           = &err,
-                       .h_dentry       = wh_dentry,
+                       .h_path         = &wh_path,
                        .whlist         = whlist,
-                       .bindex         = bindex,
-                       .br             = br
+                       .bindex         = bindex
                };
 
                wkq_err = au_wkq_wait(call_del_wh_children, &args);
@@ -977,10 +981,8 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
        inode_unlock(wh_inode);
 
        if (!err) {
-               h_tmp.dentry = wh_dentry;
-               h_tmp.mnt = au_br_mnt(br);
                h_nlink = h_dir->i_nlink;
-               err = vfsub_rmdir(h_dir, &h_tmp);
+               err = vfsub_rmdir(h_dir, &wh_path);
                /* some fs doesn't change the parent nlink in some cases */
                h_nlink -= h_dir->i_nlink;
        }
diff --git a/fs/aufs/whout.h b/fs/aufs/whout.h
index 08bce298f8a3..d55c4f9a9659 100644
--- a/fs/aufs/whout.h
+++ b/fs/aufs/whout.h
@@ -29,9 +29,9 @@
 
 /* whout.c */
 int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
-int au_wh_test(struct user_namespace *h_userns, struct dentry *h_parent,
+int au_wh_test(struct user_namespace *h_userns, struct path *h_ppath,
               struct qstr *wh_name, int try_sio);
-int au_diropq_test(struct user_namespace *h_userns, struct dentry *h_dentry);
+int au_diropq_test(struct user_namespace *h_userns, struct path *h_path);
 struct au_branch;
 struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
                             struct qstr *prefix);
diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c
index b126b34206f3..e6683663885b 100644
--- a/fs/aufs/xino.c
+++ b/fs/aufs/xino.c
@@ -235,22 +235,23 @@ struct file *au_xino_create2(struct super_block *sb, 
struct path *base,
                             struct file *copy_src)
 {
        struct file *file;
-       struct dentry *dentry, *parent;
+       struct dentry *dentry;
        struct inode *dir, *delegated;
        struct qstr *name;
-       struct path path;
+       struct path ppath, path;
        int err, do_unlock;
        struct au_xino_lock_dir ldir;
 
        do_unlock = 1;
        au_xino_lock_dir(sb, base, &ldir);
        dentry = base->dentry;
-       parent = dentry->d_parent; /* dir inode is locked */
-       dir = d_inode(parent);
+       ppath.dentry = dentry->d_parent; /* dir inode is locked */
+       ppath.mnt = base->mnt;
+       dir = d_inode(ppath.dentry);
        IMustLock(dir);
 
        name = &dentry->d_name;
-       path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
+       path.dentry = vfsub_lookup_one_len(name->name, &ppath, name->len);
        if (IS_ERR(path.dentry)) {
                file = (void *)path.dentry;
                pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry));
diff --git a/include/uapi/linux/aufs_type.h b/include/uapi/linux/aufs_type.h
index 8993ca8ef927..1d62ed357532 100644
--- a/include/uapi/linux/aufs_type.h
+++ b/include/uapi/linux/aufs_type.h
@@ -40,7 +40,7 @@
 #include <limits.h>
 #endif /* __KERNEL__ */
 
-#define AUFS_VERSION   "5.14-20210906"
+#define AUFS_VERSION   "5.14-20211018"
 
 /* todo? move this to linux-2.6.19/include/magic.h */
 #define AUFS_SUPER_MAGIC       ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
-- 
2.17.1

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#11061): 
https://lists.yoctoproject.org/g/linux-yocto/message/11061
Mute This Topic: https://lists.yoctoproject.org/mt/90000689/21656
Group Owner: linux-yocto+ow...@lists.yoctoproject.org
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to