Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 359184
b: refs/heads/master
c: ecf3d1f
h: refs/heads/master
v: v3
  • Loading branch information
Jeff Layton authored and Al Viro committed Feb 26, 2013
1 parent 913d73f commit ff3b07b
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 17 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4f4a4faddea0fe45bf508e723c3a810c5190ed62
refs/heads/master: ecf3d1f1aa74da0d632b651a2e05a911f60e92c0
2 changes: 2 additions & 0 deletions trunk/Documentation/filesystems/Locking
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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 *, const struct inode *,
struct qstr *);
int (*d_compare)(const struct dentry *, const struct inode *,
Expand All @@ -25,6 +26,7 @@ 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
Expand Down
4 changes: 4 additions & 0 deletions trunk/Documentation/filesystems/porting
Original file line number Diff line number Diff line change
Expand Up @@ -441,3 +441,7 @@ d_make_root() drops the reference to inode if dentry allocation fails.
two, it gets "is it an O_EXCL or equivalent?" boolean argument. Note that
local filesystems can ignore tha argument - they are guaranteed that the
object doesn't exist. It's remote/distributed ones that might care...
--
[mandatory]
FS_REVAL_DOT is gone; if you used to have it, add ->d_weak_revalidate()
in your dentry operations instead.
24 changes: 22 additions & 2 deletions trunk/Documentation/filesystems/vfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,7 @@ 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 *, const struct inode *,
struct qstr *);
int (*d_compare)(const struct dentry *, const struct inode *,
Expand All @@ -915,8 +916,13 @@ struct dentry_operations {

d_revalidate: called when the VFS needs to revalidate a dentry. This
is called whenever a name look-up finds a dentry in the
dcache. Most filesystems leave this as NULL, because all their
dentries in the dcache are valid
dcache. Most local filesystems leave this as NULL, because all their
dentries in the dcache are valid. Network filesystems are different
since things can change on the server without the client necessarily
being aware of it.

This function should return a positive value if the dentry is still
valid, and zero or a negative error code if it isn't.

d_revalidate may be called in rcu-walk mode (flags & LOOKUP_RCU).
If in rcu-walk mode, the filesystem must revalidate the dentry without
Expand All @@ -927,6 +933,20 @@ 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.

In this case, we are less concerned with whether the dentry is still
fully correct, but rather that the inode is still valid. As with
d_revalidate, most local filesystems will set this to NULL since their
dcache entries are always valid.

This function has the same return code semantics as d_revalidate.

d_weak_revalidate is only called after leaving rcu-walk mode.

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
to be hashed into. The inode is the dentry's inode.
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/9p/vfs_dentry.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)

const struct dentry_operations v9fs_cached_dentry_operations = {
.d_revalidate = v9fs_lookup_revalidate,
.d_weak_revalidate = v9fs_lookup_revalidate,
.d_delete = v9fs_cached_dentry_delete,
.d_release = v9fs_dentry_release,
};
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/9p/vfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,5 +363,5 @@ struct file_system_type v9fs_fs_type = {
.mount = v9fs_mount,
.kill_sb = v9fs_kill_super,
.owner = THIS_MODULE,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT,
.fs_flags = FS_RENAME_DOES_D_MOVE,
};
3 changes: 3 additions & 0 deletions trunk/fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,7 @@ 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 ));
dentry->d_op = op;
if (!op)
Expand All @@ -1368,6 +1369,8 @@ 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)
Expand Down
8 changes: 2 additions & 6 deletions trunk/fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,14 +600,10 @@ static int complete_walk(struct nameidata *nd)
if (likely(!(nd->flags & LOOKUP_JUMPED)))
return 0;

if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE)))
if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE)))
return 0;

if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)))
return 0;

/* Note: we do not d_invalidate() */
status = d_revalidate(dentry, nd->flags);
status = dentry->d_op->d_weak_revalidate(dentry, nd->flags);
if (status > 0)
return 0;

Expand Down
40 changes: 40 additions & 0 deletions trunk/fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,45 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
return error;
}

/*
* A weaker form of d_revalidate for revalidating just the dentry->d_inode
* when we don't really care about the dentry name. This is called when a
* pathwalk ends on a dentry that was not found via a normal lookup in the
* parent dir (e.g.: ".", "..", procfs symlinks or mountpoint traversals).
*
* In this situation, we just want to verify that the inode itself is OK
* since the dentry might have changed on the server.
*/
static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags)
{
int error;
struct inode *inode = dentry->d_inode;

/*
* I believe we can only get a negative dentry here in the case of a
* procfs-style symlink. Just assume it's correct for now, but we may
* eventually need to do something more here.
*/
if (!inode) {
dfprintk(LOOKUPCACHE, "%s: %s/%s has negative inode\n",
__func__, dentry->d_parent->d_name.name,
dentry->d_name.name);
return 1;
}

if (is_bad_inode(inode)) {
dfprintk(LOOKUPCACHE, "%s: %s/%s has dud inode\n",
__func__, dentry->d_parent->d_name.name,
dentry->d_name.name);
return 0;
}

error = nfs_revalidate_inode(NFS_SERVER(inode), inode);
dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n",
__func__, inode->i_ino, error ? "invalid" : "valid");
return !error;
}

/*
* This is called from dput() when d_count is going to 0.
*/
Expand Down Expand Up @@ -1202,6 +1241,7 @@ static void nfs_d_release(struct dentry *dentry)

const struct dentry_operations nfs_dentry_operations = {
.d_revalidate = nfs_lookup_revalidate,
.d_weak_revalidate = nfs_weak_revalidate,
.d_delete = nfs_dentry_delete,
.d_iput = nfs_dentry_iput,
.d_automount = nfs_d_automount,
Expand Down
6 changes: 3 additions & 3 deletions trunk/fs/nfs/nfs4super.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,23 @@ static struct file_system_type nfs4_remote_fs_type = {
.name = "nfs4",
.mount = nfs4_remote_mount,
.kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
};

static struct file_system_type nfs4_remote_referral_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs4_remote_referral_mount,
.kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
};

struct file_system_type nfs4_referral_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs4_referral_mount,
.kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
};

static const struct super_operations nfs4_sops = {
Expand Down
6 changes: 3 additions & 3 deletions trunk/fs/nfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ struct file_system_type nfs_fs_type = {
.name = "nfs",
.mount = nfs_fs_mount,
.kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
};
EXPORT_SYMBOL_GPL(nfs_fs_type);

Expand All @@ -301,7 +301,7 @@ struct file_system_type nfs_xdev_fs_type = {
.name = "nfs",
.mount = nfs_xdev_mount,
.kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
};

const struct super_operations nfs_sops = {
Expand Down Expand Up @@ -331,7 +331,7 @@ struct file_system_type nfs4_fs_type = {
.name = "nfs4",
.mount = nfs_fs_mount,
.kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
};
EXPORT_SYMBOL_GPL(nfs4_fs_type);

Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/dcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ 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 *, const struct inode *,
struct qstr *);
int (*d_compare)(const struct dentry *, const struct inode *,
Expand Down Expand Up @@ -192,6 +193,8 @@ struct dentry_operations {
#define DCACHE_GENOCIDE 0x0200
#define DCACHE_SHRINK_LIST 0x0400

#define DCACHE_OP_WEAK_REVALIDATE 0x0800

#define DCACHE_NFSFS_RENAMED 0x1000
/* this dentry has been "silly renamed" and has to be deleted on the last
* dput() */
Expand Down
1 change: 0 additions & 1 deletion trunk/include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1807,7 +1807,6 @@ struct file_system_type {
#define FS_HAS_SUBTYPE 4
#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
#define FS_USERNS_DEV_MOUNT 16 /* A userns mount does not imply MNT_NODEV */
#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *);
Expand Down

0 comments on commit ff3b07b

Please sign in to comment.