--- src/afs/LINUX/osi_vnodeops.c.orig	2005-04-25 10:55:47.000000000 -0400
+++ src/afs/LINUX/osi_vnodeops.c	2005-05-02 21:15:24.000000000 -0400
@@ -27,6 +27,7 @@
 #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"
@@ -425,13 +426,6 @@
 extern int afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
 		      unsigned long arg);
 
-#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
-static long afs_unlocked_xioctl(struct file *fp, unsigned int com,
-                               unsigned long arg) {
-    return afs_xioctl(FILE_INODE(fp), fp, com, arg);
-
-}
-#endif
 
 /* We need to detect unmap's after close. To do that, we need our own
  * vm_operations_struct's. And we need to set them up for both the
@@ -739,14 +733,7 @@
   .read =	generic_read_dir,
 #endif
   .readdir =	afs_linux_readdir,
-#ifdef HAVE_UNLOCKED_IOCTL
-  .unlocked_ioctl = afs_unlocked_xioctl,
-#else
   .ioctl =	afs_xioctl,
-#endif
-#ifdef HAVE_COMPAT_IOCTL
-  .compat_ioctl = afs_unlocked_xioctl,
-#endif
   .open =	afs_linux_open,
   .release =	afs_linux_release,
 };
@@ -754,14 +741,7 @@
 struct file_operations afs_file_fops = {
   .read =	afs_linux_read,
   .write =	afs_linux_write,
-#ifdef HAVE_UNLOCKED_IOCTL
-  .unlocked_ioctl = afs_unlocked_xioctl,
-#else
   .ioctl =	afs_xioctl,
-#endif
-#ifdef HAVE_COMPAT_IOCTL
-  .compat_ioctl = afs_unlocked_xioctl,
-#endif
   .mmap =	afs_linux_mmap,
   .open =	afs_linux_open,
   .flush =	afs_linux_flush,
@@ -864,73 +844,84 @@
 afs_linux_dentry_revalidate(struct dentry *dp)
 #endif
 {
-    cred_t *credp = NULL;
+    char *name = NULL;
+    cred_t *credp = crref();
     struct vrequest treq;
-    int code, bad_dentry;
+    struct vcache *lookupvcp = NULL;
+    int code, bad_dentry = 1;
+    struct sysname_info sysState;
     struct vcache *vcp, *parentvcp;
 
+    sysState.allocked = 0;
+
 #ifdef AFS_LINUX24_ENV
     lock_kernel();
 #endif
     AFS_GLOCK();
 
     vcp = ITOAFS(dp->d_inode);
-    parentvcp = ITOAFS(dp->d_parent->d_inode);		/* dget_parent()? */
+    parentvcp = ITOAFS(dp->d_parent->d_inode);
 
-    /* If it's a negative dentry, it's never valid */
-    if (!vcp || !parentvcp) {
-	bad_dentry = 1;
+    /* If it's a negative dentry, then there's nothing to do. */
+    if (!vcp || !parentvcp)
 	goto done;
-    }
 
-    /* If it's @sys, perhaps it has been changed */
-    if (!afs_ENameOK(dp->d_name.name)) {
-	bad_dentry = 10;
+    /* If it is the AFS root, then there's no chance it needs 
+     * revalidating */
+    if (vcp == afs_globalVp) {
+	bad_dentry = 0;
 	goto done;
     }
 
-    /* If it's the AFS root no chance it needs revalidating */
-    if (vcp == afs_globalVp)
-	goto good_dentry;
-
-    /* Get a validated vcache entry */
-    credp = crref();
-    code = afs_InitReq(&treq, credp);
-    if (code) {
-	bad_dentry = 2;
+    if ((code = afs_InitReq(&treq, credp)))
 	goto done;
-    }
-    code = afs_VerifyVCache(vcp, &treq);
-    if (code) {
-	bad_dentry = 3;
+
+    Check_AtSys(parentvcp, dp->d_name.name, &sysState, &treq);
+    name = sysState.name;
+
+    /* 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;
 	goto done;
     }
 
-    /* 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;
-	}
+    /* 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);
 
-	vcp->last_looker = treq.uid;
-    }
+    /* Verify that the dentry does not point to an old inode */
+    if (vcp != lookupvcp)
+	goto done;
 
-  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
-    if (credp)
-	crfree(credp);
+    crfree(credp);
 
     return !bad_dentry;
 }
@@ -940,6 +931,17 @@
 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
@@ -947,6 +949,16 @@
 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? */
 
