[H/F][PATCH 1/1] aufs: bugfix, stop omitting path->mnt
Mauricio Faria de Oliveira
mfo at canonical.com
Fri Oct 22 15:47:14 UTC 2021
From: "J. R. Okajima" <hooanon05g at gmail.com>
BugLink: https://bugs.launchpad.net/bugs/1948470
For some cases, aufs calls vfs_getattr() with setting NULL to
path->mnt (via vfsub_update_h_iattr() and vfsub_getattr()).
This commit always sets the correct value to it.
Reported-by: Mauricio Faria de Oliveira <mfo at canonical.com>
Originally-patched-by: Mauricio Faria de Oliveira <mfo at canonical.com>
See-also: https://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg05862.html and its thread
Signed-off-by: J. R. Okajima <hooanon05g at gmail.com>
(cherry picked from commit 71dfddc730395d2bae4e1ae3c9259635a719cf69 aufs5-linux.git)
Signed-off-by: Mauricio Faria de Oliveira <mfo at canonical.com>
---
fs/aufs/cpup.c | 6 ++--
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 | 11 +++++--
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 ++++---
13 files changed, 156 insertions(+), 125 deletions(-)
diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c
index 492442339b6c..7977b3bc9b64 100644
--- a/fs/aufs/cpup.c
+++ b/fs/aufs/cpup.c
@@ -753,11 +753,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);
@@ -769,9 +771,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/dentry.c b/fs/aufs/dentry.c
index 50aaaa21d089..ab8a651ab301 100644
--- a/fs/aufs/dentry.c
+++ b/fs/aufs/dentry.c
@@ -35,6 +35,7 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
struct dentry *h_dentry;
struct inode *h_inode;
struct au_branch *br;
+ struct path h_path;
int wh_found, opq;
unsigned char wh_able;
const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
@@ -43,9 +44,11 @@ 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);
wh_able = !!au_br_whable(br->br_perm);
if (wh_able)
- wh_found = au_wh_test(h_parent, &args->whname, ignore_perm);
+ wh_found = au_wh_test(&h_path, &args->whname, ignore_perm);
h_dentry = ERR_PTR(wh_found);
if (!wh_found)
goto real_lookup;
@@ -60,9 +63,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(args->name, h_parent);
+ h_dentry = au_sio_lkup_one(args->name, &h_path);
if (IS_ERR(h_dentry)) {
if (PTR_ERR(h_dentry) == -ENAMETOOLONG
&& !allow_neg)
@@ -96,8 +99,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_dentry);
+ opq = au_diropq_test(&h_path);
inode_unlock_shared(h_inode);
if (opq > 0)
au_set_dbdiropq(dentry, bindex);
@@ -242,18 +246,18 @@ int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
return err;
}
-struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent)
+struct dentry *au_sio_lkup_one(struct qstr *name, struct path *ppath)
{
struct dentry *dentry;
int wkq_err;
- if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC))
- dentry = vfsub_lkup_one(name, parent);
+ if (!au_test_h_perm_sio(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);
@@ -270,16 +274,18 @@ struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent)
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 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);
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(&dentry->d_name, h_parent);
+ h_dentry = au_sio_lkup_one(&dentry->d_name, &h_ppath);
err = PTR_ERR(h_dentry);
if (IS_ERR(h_dentry))
goto out;
@@ -354,6 +360,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));
@@ -368,7 +375,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 c9f9c704da0a..ab45ded80f8c 100644
--- a/fs/aufs/dentry.h
+++ b/fs/aufs/dentry.h
@@ -73,7 +73,7 @@ struct au_do_lookup_args {
/* dentry.c */
extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
struct au_branch;
-struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
+struct dentry *au_sio_lkup_one(struct qstr *name, 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 354997f3e9f7..36e3fe074b48 100644
--- a/fs/aufs/dirren.c
+++ b/fs/aufs/dirren.c
@@ -263,7 +263,8 @@ 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;
@@ -297,7 +298,6 @@ static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex,
}
flags = O_WRONLY;
}
- hinopath.mnt = path->mnt;
hinofile = vfsub_dentry_open(&hinopath, flags);
if (suspend)
au_hn_inode_unlock(hdir);
@@ -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 842df6f05517..bdd5e02e7aba 100644
--- a/fs/aufs/export.c
+++ b/fs/aufs/export.c
@@ -407,7 +407,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 9beba2ba8db0..be42650637dd 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;
h_dentry = au_h_dptr(dentry, bindex);
if (d_really_is_positive(dentry)) {
@@ -131,12 +134,16 @@ int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
* let's try heavy test.
*/
err = -EACCES;
- if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)
+ sb = dentry->d_sb;
+ br = au_sbr(sb, bindex);
+ if (unlikely(!au_opt_test(au_mntflags(sb), DIRPERM1)
&& au_test_h_perm(d_inode(h_parent),
MAY_EXEC | MAY_WRITE)))
goto out;
- h_latest = au_sio_lkup_one(&dentry->d_name, h_parent);
+ h_ppath.dentry = h_parent;
+ h_ppath.mnt = au_br_mnt(br);
+ h_latest = au_sio_lkup_one(&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 435fa50811ff..d65a584170ab 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 850829b21888..5a05903d75f9 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 a5e10c5c004f..a3b3d16077f9 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 705f033ba2c3..6caa1c28c89f 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 efe0c16508db..ca8a5cd7e6d7 100644
--- a/fs/aufs/whout.c
+++ b/fs/aufs/whout.c
@@ -61,18 +61,18 @@ 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 dentry *h_parent, struct qstr *wh_name, int try_sio)
+int au_wh_test(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(wh_name, h_parent);
+ wh_dentry = au_sio_lkup_one(wh_name, h_ppath);
err = PTR_ERR(wh_dentry);
if (IS_ERR(wh_dentry)) {
if (err == -ENAMETOOLONG)
@@ -99,15 +99,15 @@ int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio)
}
/*
- * test if the @h_dentry sets opaque or not.
+ * test if the @h_path->dentry sets opaque or not.
*/
-int au_diropq_test(struct dentry *h_dentry)
+int au_diropq_test(struct path *h_path)
{
int err;
struct inode *h_dir;
- h_dir = d_inode(h_dentry);
- err = au_wh_test(h_dentry, &diropq_name,
+ h_dir = d_inode(h_path->dentry);
+ err = au_wh_test(h_path, &diropq_name,
au_test_h_perm_sio(h_dir, MAY_EXEC));
return err;
}
@@ -125,6 +125,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;
BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
@@ -148,10 +149,12 @@ 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);
qs.name = name;
for (i = 0; i < 3; i++) {
sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
- dentry = au_sio_lkup_one(&qs, h_parent);
+ dentry = au_sio_lkup_one(&qs, &h_ppath);
if (IS_ERR(dentry) || d_is_negative(dentry))
goto out_name;
dput(dentry);
@@ -245,21 +248,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);
}
@@ -699,15 +701,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;
@@ -718,11 +722,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);
}
@@ -785,11 +786,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;
@@ -824,8 +828,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;
@@ -855,7 +859,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;
@@ -874,16 +878,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);
}
/* ---------------------------------------------------------------------- */
@@ -935,7 +938,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;
@@ -943,6 +946,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);
wh_inode = d_inode(wh_dentry);
inode_lock_nested(wh_inode, AuLsc_I_CHILD);
@@ -951,15 +956,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(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);
@@ -969,10 +973,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 65459ba0e790..28da00f02369 100644
--- a/fs/aufs/whout.h
+++ b/fs/aufs/whout.h
@@ -29,8 +29,8 @@
/* whout.c */
int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
-int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio);
-int au_diropq_test(struct dentry *h_dentry);
+int au_wh_test(struct path *h_ppath, struct qstr *wh_name, int try_sio);
+int au_diropq_test(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 b3152c0ce0b5..8351e0a2c30c 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));
--
2.30.2
More information about the kernel-team
mailing list