linux-d-reval-rewrite-mtpts-when-fakestat-enabled-20081007
authorDerrick Brashear <shadow@dementia.org>
Tue, 7 Oct 2008 20:00:31 +0000 (20:00 +0000)
committerDerrick Brashear <shadow@dementia.org>
Tue, 7 Oct 2008 20:00:31 +0000 (20:00 +0000)
LICENSE IPL10
FIXES 113558

avoid case where revalidate saw a mountpoint which hadn't been rewritten yet
and failed to handle it, exposing ENOENT where the entry existed.

src/afs/LINUX/osi_vnodeops.c

index eb57bb9..60b11ca 100644 (file)
@@ -876,11 +876,13 @@ afs_linux_dentry_revalidate(struct dentry *dp)
     cred_t *credp = NULL;
     struct vcache *vcp, *pvcp, *tvc = NULL;
     int valid;
+    struct afs_fakestat_state fakestate;
 
 #ifdef AFS_LINUX24_ENV
     maybe_lock_kernel();
 #endif
     AFS_GLOCK();
+    afs_InitFakeStat(&fakestate);
 
     if (dp->d_inode) {
 
@@ -892,8 +894,28 @@ afs_linux_dentry_revalidate(struct dentry *dp)
 
        if (vcp->mvstat == 1) {         /* mount point */
            if (vcp->mvid && (vcp->states & CMValid)) {
-               /* a mount point, not yet replaced by its directory */
-               goto bad_dentry;
+               int tryEvalOnly = 0;
+               int code = 0;
+               struct vrequest treq;
+
+               credp = crref();
+               code = afs_InitReq(&treq, credp);
+               if (
+#ifdef AFS_DARWIN_ENV
+                   (strcmp(dp->d_name.name, ".DS_Store") == 0) ||
+                   (strcmp(dp->d_name.name, "Contents") == 0) ||
+#endif
+                   (strcmp(dp->d_name.name, ".directory") == 0)) {
+                   tryEvalOnly = 1;
+               }
+               if (tryEvalOnly)
+                   code = afs_TryEvalFakeStat(&vcp, &fakestate, &treq);
+               else
+                   code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
+               if ((tryEvalOnly && vcp->mvstat == 1) || code) {
+                   /* a mount point, not yet replaced by its directory */
+                   goto bad_dentry;
+               }
            }
        } else
            if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
@@ -957,6 +979,7 @@ afs_linux_dentry_revalidate(struct dentry *dp)
     /* Clean up */
     if (tvc)
        afs_PutVCache(tvc);
+    afs_PutFakeStat(&fakestate);
     AFS_GUNLOCK();
     if (credp)
        crfree(credp);
@@ -971,7 +994,10 @@ afs_linux_dentry_revalidate(struct dentry *dp)
     return valid;
 
   bad_dentry:
-    valid = 0;
+    if (have_submounts(dp))
+       valid = 1;
+    else 
+       valid = 0;
     goto done;
 }