[PATCH 2.5.3] VFS fix for open(".") breakage under

From: Trond Myklebust (trond.myklebust@fys.uio.no)
Date: Fri Feb 01 2002 - 07:18:39 EST


distributed filesystems
X-Mailer: VM 6.92 under 21.1 (patch 14) "Cuyahoga Valley" XEmacs Lucid
Reply-To: trond.myklebust@fys.uio.no
From: Trond Myklebust <trond.myklebust@fys.uio.no>

The following is the fix for the open(".")/open("..") problems
that are hitting distributed file systems such as OpenGFS, and NFS.

The problem is that in the case where the final element of a path is
'.' or '..', then link_path_walk() does not actually check that the
resulting dentry is valid.

For the case of NFS, this results in 2 breakages:

  - Resulting dentry may be stale, and so the open() may succeed, but
    still results in an invalid file.

  - Attribute and data cache checking upon open(), which is normally
    done as part of the lookup process, gets circumvented, and so you
    end up with strange inconsistencies.
    Typical result is 'ls -l' returning "file 'blah' does not exist"
    errors.

Cheers,
  Trond

diff -u --recursive --new-file linux-2.5.3/fs/namei.c linux-2.5.3-cto/fs/namei.c
--- linux-2.5.3/fs/namei.c Tue Jan 15 22:53:51 2002
+++ linux-2.5.3-cto/fs/namei.c Fri Feb 1 13:00:39 2002
@@ -457,7 +457,7 @@
         while (*name=='/')
                 name++;
         if (!*name)
- goto return_base;
+ goto return_reval;
 
         inode = nd->dentry->d_inode;
         if (current->link_count)
@@ -576,7 +576,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);
@@ -627,6 +627,19 @@
                         nd->last_type = LAST_DOT;
                 else if (this.len == 2 && this.name[1] == '.')
                         nd->last_type = LAST_DOTDOT;
+return_reval:
+ /*
+ * We bypassed the ordinary revalidation routines.
+ * Check the cached dentry for staleness.
+ */
+ dentry = nd->dentry;
+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
+ err = -ESTALE;
+ if (!dentry->d_op->d_revalidate(dentry, 0)) {
+ d_invalidate(dentry);
+ break;
+ }
+ }
 return_base:
                 return 0;
 out_dput:
-
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/



This archive was generated by hypermail 2b29 : Thu Feb 07 2002 - 21:00:13 EST