aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2013-02-20 11:19:05 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2013-02-26 02:46:09 -0500
commitecf3d1f1aa74da0d632b651a2e05a911f60e92c0 (patch)
tree62a2e0a46bfd993a24a1154ec1331c57bbd50482 /Documentation
parent4f4a4faddea0fe45bf508e723c3a810c5190ed62 (diff)
vfs: kill FS_REVAL_DOT by adding a d_weak_revalidate dentry op
The following set of operations on a NFS client and server will cause server# mkdir a client# cd a server# mv a a.bak client# sleep 30 # (or whatever the dir attrcache timeout is) client# stat . stat: cannot stat `.': Stale NFS file handle Obviously, we should not be getting an ESTALE error back there since the inode still exists on the server. The problem is that the lookup code will call d_revalidate on the dentry that "." refers to, because NFS has FS_REVAL_DOT set. nfs_lookup_revalidate will see that the parent directory has changed and will try to reverify the dentry by redoing a LOOKUP. That of course fails, so the lookup code returns ESTALE. The problem here is that d_revalidate is really a bad fit for this case. What we really want to know at this point is whether the inode is still good or not, but we don't really care what name it goes by or whether the dcache is still valid. Add a new d_op->d_weak_revalidate operation and have complete_walk call that instead of d_revalidate. The intent there is to allow for a "weaker" d_revalidate that just checks to see whether the inode is still good. This is also gives us an opportunity to kill off the FS_REVAL_DOT special casing. [AV: changed method name, added note in porting, fixed confusion re having it possibly called from RCU mode (it won't be)] Cc: NeilBrown <neilb@suse.de> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/filesystems/Locking2
-rw-r--r--Documentation/filesystems/porting4
-rw-r--r--Documentation/filesystems/vfs.txt24
3 files changed, 28 insertions, 2 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index f48e0c6b4c42..0706d32a61e6 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -10,6 +10,7 @@ be able to use diff(1).
10--------------------------- dentry_operations -------------------------- 10--------------------------- dentry_operations --------------------------
11prototypes: 11prototypes:
12 int (*d_revalidate)(struct dentry *, unsigned int); 12 int (*d_revalidate)(struct dentry *, unsigned int);
13 int (*d_weak_revalidate)(struct dentry *, unsigned int);
13 int (*d_hash)(const struct dentry *, const struct inode *, 14 int (*d_hash)(const struct dentry *, const struct inode *,
14 struct qstr *); 15 struct qstr *);
15 int (*d_compare)(const struct dentry *, const struct inode *, 16 int (*d_compare)(const struct dentry *, const struct inode *,
@@ -25,6 +26,7 @@ prototypes:
25locking rules: 26locking rules:
26 rename_lock ->d_lock may block rcu-walk 27 rename_lock ->d_lock may block rcu-walk
27d_revalidate: no no yes (ref-walk) maybe 28d_revalidate: no no yes (ref-walk) maybe
29d_weak_revalidate:no no yes no
28d_hash no no no maybe 30d_hash no no no maybe
29d_compare: yes no no maybe 31d_compare: yes no no maybe
30d_delete: no yes no no 32d_delete: no yes no no
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index 0472c31c163b..4db22f6491e0 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -441,3 +441,7 @@ d_make_root() drops the reference to inode if dentry allocation fails.
441two, it gets "is it an O_EXCL or equivalent?" boolean argument. Note that 441two, it gets "is it an O_EXCL or equivalent?" boolean argument. Note that
442local filesystems can ignore tha argument - they are guaranteed that the 442local filesystems can ignore tha argument - they are guaranteed that the
443object doesn't exist. It's remote/distributed ones that might care... 443object doesn't exist. It's remote/distributed ones that might care...
444--
445[mandatory]
446 FS_REVAL_DOT is gone; if you used to have it, add ->d_weak_revalidate()
447in your dentry operations instead.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index e3869098163e..bc4b06b3160a 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -900,6 +900,7 @@ defined:
900 900
901struct dentry_operations { 901struct dentry_operations {
902 int (*d_revalidate)(struct dentry *, unsigned int); 902 int (*d_revalidate)(struct dentry *, unsigned int);
903 int (*d_weak_revalidate)(struct dentry *, unsigned int);
903 int (*d_hash)(const struct dentry *, const struct inode *, 904 int (*d_hash)(const struct dentry *, const struct inode *,
904 struct qstr *); 905 struct qstr *);
905 int (*d_compare)(const struct dentry *, const struct inode *, 906 int (*d_compare)(const struct dentry *, const struct inode *,
@@ -915,8 +916,13 @@ struct dentry_operations {
915 916
916 d_revalidate: called when the VFS needs to revalidate a dentry. This 917 d_revalidate: called when the VFS needs to revalidate a dentry. This
917 is called whenever a name look-up finds a dentry in the 918 is called whenever a name look-up finds a dentry in the
918 dcache. Most filesystems leave this as NULL, because all their 919 dcache. Most local filesystems leave this as NULL, because all their
919 dentries in the dcache are valid 920 dentries in the dcache are valid. Network filesystems are different
921 since things can change on the server without the client necessarily
922 being aware of it.
923
924 This function should return a positive value if the dentry is still
925 valid, and zero or a negative error code if it isn't.
920 926
921 d_revalidate may be called in rcu-walk mode (flags & LOOKUP_RCU). 927 d_revalidate may be called in rcu-walk mode (flags & LOOKUP_RCU).
922 If in rcu-walk mode, the filesystem must revalidate the dentry without 928 If in rcu-walk mode, the filesystem must revalidate the dentry without
@@ -927,6 +933,20 @@ struct dentry_operations {
927 If a situation is encountered that rcu-walk cannot handle, return 933 If a situation is encountered that rcu-walk cannot handle, return
928 -ECHILD and it will be called again in ref-walk mode. 934 -ECHILD and it will be called again in ref-walk mode.
929 935
936 d_weak_revalidate: called when the VFS needs to revalidate a "jumped" dentry.
937 This is called when a path-walk ends at dentry that was not acquired by
938 doing a lookup in the parent directory. This includes "/", "." and "..",
939 as well as procfs-style symlinks and mountpoint traversal.
940
941 In this case, we are less concerned with whether the dentry is still
942 fully correct, but rather that the inode is still valid. As with
943 d_revalidate, most local filesystems will set this to NULL since their
944 dcache entries are always valid.
945
946 This function has the same return code semantics as d_revalidate.
947
948 d_weak_revalidate is only called after leaving rcu-walk mode.
949
930 d_hash: called when the VFS adds a dentry to the hash table. The first 950 d_hash: called when the VFS adds a dentry to the hash table. The first
931 dentry passed to d_hash is the parent directory that the name is 951 dentry passed to d_hash is the parent directory that the name is
932 to be hashed into. The inode is the dentry's inode. 952 to be hashed into. The inode is the dentry's inode.