summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/aufs/debug.c11
-rw-r--r--fs/aufs/dentry.c22
-rw-r--r--fs/aufs/dentry.h14
-rw-r--r--fs/aufs/i_op.c14
-rw-r--r--fs/aufs/i_op_del.c3
-rw-r--r--fs/aufs/mvdown.c3
-rw-r--r--fs/aufs/vfsub.h2
-rw-r--r--fs/inode.c3
8 files changed, 41 insertions, 31 deletions
diff --git a/fs/aufs/debug.c b/fs/aufs/debug.c
index 4fdc9d422..44bdb5ff8 100644
--- a/fs/aufs/debug.c
+++ b/fs/aufs/debug.c
@@ -163,9 +163,9 @@ static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
{
struct dentry *wh = NULL;
int hn;
+ struct inode *inode;
struct au_iinfo *iinfo;
struct au_hinode *hi;
- struct inode *inode;
if (!dentry || IS_ERR(dentry)) {
dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
@@ -180,11 +180,12 @@ static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
d_unhashed(dentry) ? "un" : "");
hn = -1;
inode = NULL;
- if (bindex >= 0
- && d_is_positive(dentry)
- && au_test_aufs(dentry->d_sb))
+ if (d_is_positive(dentry))
inode = d_inode(dentry);
- if (inode && !au_is_bad_inode(inode)) {
+ if (inode
+ && au_test_aufs(dentry->d_sb)
+ && bindex >= 0
+ && !au_is_bad_inode(inode)) {
iinfo = au_ii(inode);
hi = au_hinode(iinfo, bindex);
hn = !!au_hn(hi);
diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c
index 080fac9c8..4bb153086 100644
--- a/fs/aufs/dentry.c
+++ b/fs/aufs/dentry.c
@@ -9,14 +9,6 @@
#include <linux/namei.h>
#include "aufs.h"
-#define AuLkup_ALLOW_NEG 1
-#define AuLkup_IGNORE_PERM (1 << 1)
-#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
-#define au_fset_lkup(flags, name) \
- do { (flags) |= AuLkup_##name; } while (0)
-#define au_fclr_lkup(flags, name) \
- do { (flags) &= ~AuLkup_##name; } while (0)
-
struct au_do_lookup_args {
unsigned int flags;
mode_t type;
@@ -119,15 +111,15 @@ static int au_test_shwh(struct super_block *sb, const struct qstr *name)
* otherwise an error.
* can be called at unlinking with @type is zero.
*/
-int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, mode_t type)
+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
+ unsigned int flags)
{
int npositive, err;
aufs_bindex_t bindex, btail, bdiropq;
unsigned char isdir, dirperm1;
struct qstr whname;
struct au_do_lookup_args args = {
- .flags = 0,
- .type = type
+ .flags = flags
};
const struct qstr *name = &dentry->d_name;
struct dentry *parent;
@@ -143,8 +135,6 @@ int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, mode_t type)
goto out;
isdir = !!d_is_dir(dentry);
- if (!type)
- au_fset_lkup(args.flags, ALLOW_NEG);
dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1);
npositive = 0;
@@ -158,9 +148,7 @@ int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, mode_t type)
if (h_dentry) {
if (d_is_positive(h_dentry))
npositive++;
- if (type != S_IFDIR)
- break;
- continue;
+ break;
}
h_parent = au_h_dptr(parent, bindex);
if (!h_parent || !d_is_dir(h_parent))
@@ -761,7 +749,7 @@ int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
* if current working dir is removed, it returns an error.
* but the dentry is legal.
*/
- err = au_lkup_dentry(dentry, /*btop*/0, /*type*/0);
+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
AuDbgDentry(dentry);
au_di_swap(tmp, dinfo);
if (err == -ENOENT)
diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h
index c52fe583f..bdc1af622 100644
--- a/fs/aufs/dentry.h
+++ b/fs/aufs/dentry.h
@@ -30,6 +30,17 @@ struct au_dinfo {
/* ---------------------------------------------------------------------- */
+/* flags for au_lkup_dentry() */
+#define AuLkup_ALLOW_NEG 1
+#define AuLkup_IGNORE_PERM (1 << 1)
+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
+#define au_fset_lkup(flags, name) \
+ do { (flags) |= AuLkup_##name; } while (0)
+#define au_fclr_lkup(flags, name) \
+ do { (flags) &= ~AuLkup_##name; } while (0)
+
+/* ---------------------------------------------------------------------- */
+
/* dentry.c */
extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
struct au_branch;
@@ -37,7 +48,8 @@ struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
struct dentry *h_parent, struct au_branch *br);
-int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, mode_t type);
+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
+ unsigned int flags);
int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c
index ac3bf9437..c274958dd 100644
--- a/fs/aufs/i_op.c
+++ b/fs/aufs/i_op.c
@@ -184,8 +184,9 @@ static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
if (!err)
err = au_digen_test(parent, au_sigen(sb));
if (!err) {
+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */
npositive = au_lkup_dentry(dentry, au_dbtop(parent),
- /*type*/0);
+ AuLkup_ALLOW_NEG);
err = npositive;
}
di_read_unlock(parent, AuLock_IR);
@@ -266,6 +267,7 @@ static int aufs_atomic_open(struct inode *dir, struct dentry *dentry,
umode_t create_mode, int *opened)
{
int err, h_opened = *opened;
+ unsigned int lkup_flags;
struct dentry *parent;
struct dentry *d;
struct au_sphlhead *aopen;
@@ -279,14 +281,18 @@ static int aufs_atomic_open(struct inode *dir, struct dentry *dentry,
};
IMustLock(dir);
- AuDbg("open_flag 0x%x\n", open_flag);
+ AuDbg("open_flag 0%o\n", open_flag);
AuDbgDentry(dentry);
err = 0;
if (!au_di(dentry)) {
- d = aufs_lookup(dir, dentry, /*flags*/0);
+ lkup_flags = LOOKUP_OPEN;
+ if (open_flag & O_CREAT)
+ lkup_flags |= LOOKUP_CREATE;
+ d = aufs_lookup(dir, dentry, lkup_flags);
if (IS_ERR(d)) {
err = PTR_ERR(d);
+ AuTraceErr(err);
goto out;
} else if (d) {
/*
@@ -312,7 +318,7 @@ static int aufs_atomic_open(struct inode *dir, struct dentry *dentry,
parent = dentry->d_parent; /* dir is locked */
di_write_lock_parent(parent);
- err = au_lkup_dentry(dentry, /*btop*/0, /*type*/0);
+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
if (unlikely(err))
goto out_unlock;
diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
index bda70b008..35b923ccc 100644
--- a/fs/aufs/i_op_del.c
+++ b/fs/aufs/i_op_del.c
@@ -54,7 +54,8 @@ int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
au_di_cp(tmp, dinfo);
au_di_swap(tmp, dinfo);
/* returns the number of positive dentries */
- need_wh = au_lkup_dentry(dentry, btop + 1, /*type*/0);
+ need_wh = au_lkup_dentry(dentry, btop + 1,
+ /* AuLkup_IGNORE_PERM */ 0);
au_di_swap(tmp, dinfo);
au_rw_write_unlock(&tmp->di_rwsem);
au_di_free(tmp);
diff --git a/fs/aufs/mvdown.c b/fs/aufs/mvdown.c
index 334f25c13..a48aa1c50 100644
--- a/fs/aufs/mvdown.c
+++ b/fs/aufs/mvdown.c
@@ -451,7 +451,8 @@ static int au_mvd_args_intermediate(const unsigned char dmsg,
au_di_swap(tmp, dinfo);
/* returns the number of positive dentries */
- err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1, /*type*/0);
+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1,
+ /* AuLkup_IGNORE_PERM */ 0);
if (!err)
a->bwh = au_dbwh(a->dentry);
else if (err > 0)
diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
index 4e08d33c2..291bfae7a 100644
--- a/fs/aufs/vfsub.h
+++ b/fs/aufs/vfsub.h
@@ -207,7 +207,7 @@ static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
static inline int vfsub_update_time(struct inode *h_inode, struct timespec *ts,
int flags)
{
- return generic_update_time(h_inode, ts, flags);
+ return update_time(h_inode, ts, flags);
/* no vfsub_update_h_iattr() since we don't have struct path */
}
diff --git a/fs/inode.c b/fs/inode.c
index 69b8b526c..a41481e3d 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1590,7 +1590,7 @@ EXPORT_SYMBOL(generic_update_time);
* This does the actual work of updating an inodes time or version. Must have
* had called mnt_want_write() before calling this.
*/
-static int update_time(struct inode *inode, struct timespec *time, int flags)
+int update_time(struct inode *inode, struct timespec *time, int flags)
{
int (*update_time)(struct inode *, struct timespec *, int);
@@ -1599,6 +1599,7 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
return update_time(inode, time, flags);
}
+EXPORT_SYMBOL_GPL(update_time);
/**
* touch_atime - update the access time