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/