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] -=-=-=-=-=-=-=-=-=-=-=-