@@ -10,7 +10,6 @@ be able to use diff(1).
--------------------------- dentry_operations --------------------------
prototypes:
int (*d_revalidate)(struct dentry *, unsigned int);
- int (*d_weak_revalidate)(struct dentry *, unsigned int);
int (*d_hash)(const struct dentry *, struct qstr *);
int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
@@ -27,7 +26,6 @@ prototypes:
locking rules:
rename_lock ->d_lock may block rcu-walk
d_revalidate: no no yes (ref-walk) maybe
-d_weak_revalidate:no no yes no
d_hash no no no maybe
d_compare: yes no no maybe
d_delete: no yes no no
@@ -611,3 +611,9 @@ in your dentry operations instead.
->d_weak_revalidate should perform the same handling of LOOKUP_OPEN as
->d_revalidate. If LOOKUP_OPEN is not set, d_weak_revalidate need not
do anything.
+--
+[mandatory]
+ ->d_weak_revalidate() is gone. ->d_revalidate must check for
+ LOOKUP_JUMPED and skip revalidate of the name in that case.
+ If LOOKUP_JUMPED is set and LOOKUP_OPEN is not set, ->d_revalidate
+ need not do anything.
@@ -976,7 +976,6 @@ defined:
struct dentry_operations {
int (*d_revalidate)(struct dentry *, unsigned int);
- int (*d_weak_revalidate)(struct dentry *, unsigned int);
int (*d_hash)(const struct dentry *, struct qstr *);
int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
@@ -1010,20 +1009,11 @@ struct dentry_operations {
If a situation is encountered that rcu-walk cannot handle, return
-ECHILD and it will be called again in ref-walk mode.
- d_weak_revalidate: called when the VFS needs to revalidate a "jumped" dentry.
- This is called when a path-walk ends at dentry that was not acquired by
- doing a lookup in the parent directory. This includes "/", "." and "..",
- as well as procfs-style symlinks and mountpoint traversal.
-
- Filesystems only need this if they handle LOOKUP_OPEN in
- d_revalidate, in which case the same handling should be applied
- in d_weak_revalidate. When LOOKUP_OPEN is not set,
- d_weak_revalidate can safely be a no-op.
-
- This function has the same return code semantics as d_revalidate.
-
- d_weak_revalidate is only called after leaving rcu-walk mode,
- so LOOKUP_RCU is never set.
+ If LOOKUP_JUMPED is set in flags, the name does not need to be
+ revalidated and in many cases d_revalidate can safely do
+ nothing. If the filesystem handles LOOKUP_OPEN in
+ d_revalidate, that same handling should still be performed
+ when LOOKUP_JUMPED is set.
d_hash: called when the VFS adds a dentry to the hash table. The first
dentry passed to d_hash is the parent directory that the name is
@@ -240,7 +240,7 @@ static int ll_revalidate_dentry(struct dentry *dentry,
* to this dentry, then its lock has not been revoked and the
* path component is valid.
*/
- if (lookup_flags & LOOKUP_PARENT)
+ if (lookup_flags & (LOOKUP_PARENT | LOOKUP_JUMPED))
return 1;
/* Symlink - always valid as long as the dentry was found */
@@ -83,6 +83,9 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
inode = d_inode(dentry);
if (!inode)
goto out_valid;
@@ -588,6 +588,9 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
vnode = AFS_FS_I(d_inode(dentry));
if (d_really_is_positive(dentry))
@@ -1217,6 +1217,9 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
struct dentry *parent;
struct inode *dir;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
if (flags & LOOKUP_RCU) {
parent = READ_ONCE(dentry->d_parent);
dir = d_inode_rcu(parent);
@@ -843,6 +843,9 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
if (d_really_is_positive(direntry)) {
if (cifs_revalidate_dentry(direntry))
return 0;
@@ -461,6 +461,9 @@ static int coda_dentry_revalidate(struct dentry *de, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
inode = d_inode(de);
if (!inode || is_root_inode(inode))
goto out;
@@ -339,6 +339,9 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
dir = dget_parent(dentry);
if (!d_inode(dir)->i_sb->s_cop->is_encrypted(d_inode(dir))) {
dput(dir);
@@ -1755,7 +1755,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH |
DCACHE_OP_COMPARE |
DCACHE_OP_REVALIDATE |
- DCACHE_OP_WEAK_REVALIDATE |
DCACHE_OP_DELETE |
DCACHE_OP_REAL));
dentry->d_op = op;
@@ -1767,8 +1766,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
dentry->d_flags |= DCACHE_OP_COMPARE;
if (op->d_revalidate)
dentry->d_flags |= DCACHE_OP_REVALIDATE;
- if (op->d_weak_revalidate)
- dentry->d_flags |= DCACHE_OP_WEAK_REVALIDATE;
if (op->d_delete)
dentry->d_flags |= DCACHE_OP_DELETE;
if (op->d_prune)
@@ -50,6 +50,9 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
if (lower_dentry->d_flags & DCACHE_OP_REVALIDATE)
rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
@@ -45,6 +45,7 @@ static inline void vfat_d_version_set(struct dentry *dentry,
static int vfat_revalidate_shortname(struct dentry *dentry)
{
int ret = 1;
+
spin_lock(&dentry->d_lock);
if (vfat_d_version(dentry) != d_inode(dentry->d_parent)->i_version)
ret = 0;
@@ -68,6 +69,9 @@ static int vfat_revalidate_ci(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
/*
* This is not negative dentry. Always valid.
*
@@ -186,6 +186,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
struct fuse_inode *fi;
int ret;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
inode = d_inode_rcu(entry);
if (inode && is_bad_inode(inode))
goto invalid;
@@ -47,6 +47,9 @@ static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
parent = dget_parent(dentry);
sdp = GFS2_SB(d_inode(parent));
dip = GFS2_I(d_inode(parent));
@@ -562,6 +562,9 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
/* Always perform fresh lookup for negatives */
if (d_really_is_negative(dentry))
goto out_bad_unlocked;
@@ -809,10 +809,10 @@ static int complete_walk(struct nameidata *nd)
if (likely(!(nd->flags & LOOKUP_JUMPED)))
return 0;
- if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE)))
+ if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE)))
return 0;
- status = dentry->d_op->d_weak_revalidate(dentry, nd->flags);
+ status = dentry->d_op->d_revalidate(dentry, nd->flags);
if (status > 0)
return 0;
@@ -323,6 +323,9 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
parent = dget_parent(dentry);
dir = d_inode(parent);
@@ -1273,7 +1273,6 @@ static void nfs_d_release(struct dentry *dentry)
const struct dentry_operations nfs_dentry_operations = {
.d_revalidate = nfs_lookup_revalidate,
- .d_weak_revalidate = nfs_lookup_revalidate,
.d_delete = nfs_dentry_delete,
.d_iput = nfs_dentry_iput,
.d_automount = nfs_d_automount,
@@ -1352,7 +1351,6 @@ static int nfs4_lookup_revalidate(struct dentry *, unsigned int);
const struct dentry_operations nfs4_dentry_operations = {
.d_revalidate = nfs4_lookup_revalidate,
- .d_weak_revalidate = nfs4_lookup_revalidate,
.d_delete = nfs_dentry_delete,
.d_iput = nfs_dentry_iput,
.d_automount = nfs_d_automount,
@@ -57,6 +57,9 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
inode = d_inode(dentry);
osb = OCFS2_SB(dentry->d_sb);
@@ -103,6 +103,9 @@ static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: called on dentry %p.\n",
__func__, dentry);
@@ -138,24 +138,6 @@ static int ovl_dentry_revalidate(struct dentry *dentry, unsigned int flags)
return 1;
}
-static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
-{
- struct ovl_entry *oe = dentry->d_fsdata;
- unsigned int i;
- int ret = 1;
-
- for (i = 0; i < oe->numlower; i++) {
- struct dentry *d = oe->lowerstack[i].dentry;
-
- if (d->d_flags & DCACHE_OP_WEAK_REVALIDATE) {
- ret = d->d_op->d_weak_revalidate(d, flags);
- if (ret <= 0)
- break;
- }
- }
- return ret;
-}
-
static const struct dentry_operations ovl_dentry_operations = {
.d_release = ovl_dentry_release,
.d_real = ovl_d_real,
@@ -165,7 +147,6 @@ static const struct dentry_operations ovl_reval_dentry_operations = {
.d_release = ovl_dentry_release,
.d_real = ovl_d_real,
.d_revalidate = ovl_dentry_revalidate,
- .d_weak_revalidate = ovl_dentry_weak_revalidate,
};
static struct kmem_cache *ovl_inode_cachep;
@@ -78,8 +78,7 @@ struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
bool ovl_dentry_remote(struct dentry *dentry)
{
return dentry->d_flags &
- (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE |
- DCACHE_OP_REAL);
+ (DCACHE_OP_REVALIDATE | DCACHE_OP_REAL);
}
bool ovl_dentry_weird(struct dentry *dentry)
@@ -1926,6 +1926,9 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
inode = d_inode(dentry);
task = get_proc_task(inode);
if (!task)
@@ -91,6 +91,9 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ if (flags & LOOKUP_JUMPED)
+ return 1;
+
inode = d_inode(dentry);
task = get_proc_task(inode);
fd = proc_fd(inode);
@@ -135,7 +135,6 @@ enum dentry_d_lock_class
struct dentry_operations {
int (*d_revalidate)(struct dentry *, unsigned int);
- int (*d_weak_revalidate)(struct dentry *, unsigned int);
int (*d_hash)(const struct dentry *, struct qstr *);
int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
@@ -184,8 +183,6 @@ struct dentry_operations {
#define DCACHE_GENOCIDE 0x00000200
#define DCACHE_SHRINK_LIST 0x00000400
-#define DCACHE_OP_WEAK_REVALIDATE 0x00000800
-
#define DCACHE_NFSFS_RENAMED 0x00001000
/* this dentry has been "silly renamed" and has to be deleted on the last
* dput() */