d-reval-fin-20050529
[openafs.git] / src / afs / LINUX / osi_vnodeops.c
index 2da933c..943137f 100644 (file)
@@ -27,7 +27,6 @@ RCSID
 #include "afs/sysincludes.h"
 #include "afsincludes.h"
 #include "afs/afs_stats.h"
-#include "afs/afs_osidnlc.h"
 #include "h/mm.h"
 #ifdef HAVE_MM_INLINE_H
 #include "h/mm_inline.h"
@@ -865,15 +864,10 @@ static int
 afs_linux_dentry_revalidate(struct dentry *dp)
 #endif
 {
-    char *name = NULL;
-    cred_t *credp = crref();
+    cred_t *credp = NULL;
     struct vrequest treq;
-    struct vcache *lookupvcp = NULL;
-    int code, bad_dentry = 1;
-    struct sysname_info sysState;
-    struct vcache *vcp, *parentvcp;
-
-    sysState.allocked = 0;
+    int code, bad_dentry;
+    struct vcache *vcp, *pvcp;
 
 #ifdef AFS_LINUX24_ENV
     lock_kernel();
@@ -881,68 +875,61 @@ afs_linux_dentry_revalidate(struct dentry *dp)
     AFS_GLOCK();
 
     vcp = ITOAFS(dp->d_inode);
-    parentvcp = ITOAFS(dp->d_parent->d_inode);
-
-    /* If it's a negative dentry, then there's nothing to do. */
-    if (!vcp || !parentvcp)
-       goto done;
+    pvcp = ITOAFS(dp->d_parent->d_inode);              /* dget_parent()? */
 
-    /* If it is the AFS root, then there's no chance it needs 
-     * revalidating */
-    if (vcp == afs_globalVp) {
-       bad_dentry = 0;
+    /* If it's a negative dentry, it's never valid */
+    if (!vcp || !pvcp) {
+       bad_dentry = 1;
        goto done;
     }
 
-    if ((code = afs_InitReq(&treq, credp)))
-       goto done;
+    /* If it's the AFS root no chance it needs revalidating */
+    if (vcp == afs_globalVp)
+       goto good_dentry;
 
-    Check_AtSys(parentvcp, dp->d_name.name, &sysState, &treq);
-    name = sysState.name;
+    /* parent's DataVersion changed? */
+    if (hgetlo(pvcp->m.DataVersion) > dp->d_time) {
+       vcp->states &= ~CStatd; /* force afs_VerifyVCache() to go to the server */
+    }
 
-    /* First try looking up the DNLC */
-    if ((lookupvcp = osi_dnlc_lookup(parentvcp, name, WRITE_LOCK))) {
-       /* Verify that the dentry does not point to an old inode */
-       if (vcp != lookupvcp)
-           goto done;
-       /* Check and correct mvid */
-       if (*name != '/' && vcp->mvstat == 2)
-           check_bad_parent(dp);
-       vcache2inode(vcp);
-       bad_dentry = 0;
+    /* Get a validated vcache entry */
+    credp = crref();
+    code = afs_InitReq(&treq, credp);
+    if (code) {
+       bad_dentry = 2;
+       goto done;
+    }
+    code = afs_VerifyVCache(vcp, &treq);
+    if (code) {
+       bad_dentry = 3;
        goto done;
     }
 
-    /* A DNLC lookup failure cannot be trusted. Try a real lookup. 
-       Make sure to try the real name and not the @sys expansion; 
-       afs_lookup will expand @sys itself. */
-  
-    code = afs_lookup(parentvcp, dp->d_name.name, &lookupvcp, credp);
+    /* If we aren't the last looker, verify access */
+    if (vcp->last_looker != treq.uid) {
+       if (!afs_AccessOK(vcp, (vType(vcp) == VREG) ? PRSFS_READ : PRSFS_LOOKUP, &treq, CHECK_MODE_BITS)) {
+           bad_dentry = 5;
+           goto done;
+       }
 
-    /* Verify that the dentry does not point to an old inode */
-    if (vcp != lookupvcp)
-       goto done;
+       vcp->last_looker = treq.uid;
+    }
 
+  good_dentry:
     bad_dentry = 0;
 
   done:
     /* Clean up */
-    if (lookupvcp)
-       afs_PutVCache(lookupvcp);
-    if (sysState.allocked)
-       osi_FreeLargeSpace(name);
-
     AFS_GUNLOCK();
-
     if (bad_dentry) {
        shrink_dcache_parent(dp);
        d_drop(dp);
     }
-
 #ifdef AFS_LINUX24_ENV
     unlock_kernel();
 #endif
-    crfree(credp);
+    if (credp)
+       crfree(credp);
 
     return !bad_dentry;
 }
@@ -952,17 +939,6 @@ afs_linux_dentry_revalidate(struct dentry *dp)
 static void
 afs_dentry_iput(struct dentry *dp, struct inode *ip)
 {
-    int isglock;
-
-    if (ICL_SETACTIVE(afs_iclSetp)) {
-       isglock = ISAFS_GLOCK();
-       if (!isglock) AFS_GLOCK();
-       afs_Trace3(afs_iclSetp, CM_TRACE_DENTRYIPUT, ICL_TYPE_POINTER, ip,
-                  ICL_TYPE_STRING, dp->d_parent->d_name.name,
-                  ICL_TYPE_STRING, dp->d_name.name);
-       if (!isglock) AFS_GUNLOCK();
-    }
-
     osi_iput(ip);
 }
 #endif
@@ -970,16 +946,6 @@ afs_dentry_iput(struct dentry *dp, struct inode *ip)
 static int
 afs_dentry_delete(struct dentry *dp)
 {
-    int isglock;
-    if (ICL_SETACTIVE(afs_iclSetp)) {
-       isglock = ISAFS_GLOCK();
-       if (!isglock) AFS_GLOCK();
-       afs_Trace3(afs_iclSetp, CM_TRACE_DENTRYDELETE, ICL_TYPE_POINTER,
-                  dp->d_inode, ICL_TYPE_STRING, dp->d_parent->d_name.name,
-                  ICL_TYPE_STRING, dp->d_name.name);
-       if (!isglock) AFS_GUNLOCK();
-    }
-
     if (dp->d_inode && (ITOAFS(dp->d_inode)->states & CUnlinked))
        return 1;               /* bad inode? */
 
@@ -1057,6 +1023,7 @@ afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
 #endif
 
        dp->d_op = &afs_dentry_operations;
+       dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
        d_instantiate(dp, ip);
     }
 
@@ -1128,6 +1095,7 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
 #endif
     }
     dp->d_op = &afs_dentry_operations;
+    dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
     d_add(dp, AFSTOI(vcp));
 
 #if defined(AFS_LINUX26_ENV)
@@ -1218,8 +1186,10 @@ afs_linux_unlink(struct inode *dip, struct dentry *dp)
        }
        AFS_GUNLOCK();
 
-       if (!code)
+       if (!code) {
+           __dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
            d_move(dp, __dp);
+       }
        dput(__dp);
 
        goto out;
@@ -1285,6 +1255,7 @@ afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
        tvcp->v.v_fop = &afs_dir_fops;
 #endif
        dp->d_op = &afs_dentry_operations;
+       dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
        d_instantiate(dp, AFSTOI(tvcp));
     }