For most filesystems this is OK, but it the case of the stateless
NFS, this means that it circumvents path staleness detection, and the
attribute+data cache revalidation code on such common commands as
opendir(".").
The following patch provides a way to do such revalidation for NFS
without impacting other filesystems.
Note: the failure to revalidate the path here does not result in a
call to d_invalidate() unlike (all?) other calls to d_revalidate(). It
only results in an ESTALE error being returned to the caller.
Cheers,
Trond
diff -u --recursive --new-file linux-2.5.75/fs/namei.c linux-2.5.75-10-reval/fs/namei.c
--- linux-2.5.75/fs/namei.c 2003-07-11 07:23:45.000000000 +0200
+++ linux-2.5.75-10-reval/fs/namei.c 2003-07-11 19:33:47.000000000 +0200
@@ -572,7 +572,7 @@
while (*name=='/')
name++;
if (!*name)
- goto return_base;
+ goto return_reval;
inode = nd->dentry->d_inode;
if (current->link_count)
@@ -693,7 +693,7 @@
inode = nd->dentry->d_inode;
/* fallthrough */
case 1:
- goto return_base;
+ goto return_reval;
}
if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
err = nd->dentry->d_op->d_hash(nd->dentry, &this);
@@ -737,6 +737,20 @@
nd->last_type = LAST_DOT;
else if (this.len == 2 && this.name[1] == '.')
nd->last_type = LAST_DOTDOT;
+ else
+ goto return_base;
+return_reval:
+ /*
+ * We bypassed the ordinary revalidation routines.
+ * We may need to check the cached dentry for staleness.
+ */
+ if (nd->dentry && nd->dentry->d_sb &&
+ (nd->dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) {
+ err = -ESTALE;
+ /* Note: we do not d_invalidate() */
+ if (!nd->dentry->d_op->d_revalidate(nd->dentry, nd))
+ break;
+ }
return_base:
return 0;
out_dput:
diff -u --recursive --new-file linux-2.5.75/fs/nfs/inode.c linux-2.5.75-10-reval/fs/nfs/inode.c
--- linux-2.5.75/fs/nfs/inode.c 2003-07-11 07:22:59.000000000 +0200
+++ linux-2.5.75-10-reval/fs/nfs/inode.c 2003-07-11 19:32:02.000000000 +0200
@@ -1275,7 +1275,7 @@
.name = "nfs",
.get_sb = nfs_get_sb,
.kill_sb = nfs_kill_super,
- .fs_flags = FS_ODD_RENAME,
+ .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT,
};
#ifdef CONFIG_NFS_V4
@@ -1507,7 +1507,7 @@
.name = "nfs4",
.get_sb = nfs4_get_sb,
.kill_sb = nfs_kill_super,
- .fs_flags = FS_ODD_RENAME,
+ .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT,
};
#define nfs4_zero_state(nfsi) \
diff -u --recursive --new-file linux-2.5.75/include/linux/fs.h linux-2.5.75-10-reval/include/linux/fs.h
--- linux-2.5.75/include/linux/fs.h 2003-07-11 07:22:59.000000000 +0200
+++ linux-2.5.75-10-reval/include/linux/fs.h 2003-07-11 19:32:02.000000000 +0200
@@ -89,6 +89,7 @@
/* public flags for file_system_type */
#define FS_REQUIRES_DEV 1
+#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */
#define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
* as nfs_rename() will be cleaned up
*/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/