diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c index e9d68992ce..fd200623e1 100644 --- a/src/afs/LINUX/osi_vfsops.c +++ b/src/afs/LINUX/osi_vfsops.c @@ -463,3 +463,13 @@ void vcache2inode(struct vcache *avc) VATTR_NULL(&vattr); afs_CopyOutAttrs(avc, &vattr); /* calls vattr2inode */ } + +/* Yet another one for fakestat'ed mountpoints */ +void vcache2fakeinode(struct vcache *rootvp, struct vcache *mpvp) +{ + struct vattr vattr; + + VATTR_NULL(&vattr); + afs_CopyOutAttrs(rootvp, &vattr); + vattr2inode(AFSTOV(mpvp), &vattr); +} diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 2bb449f9f8..9bd392f401 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -42,6 +42,7 @@ RCSID("$Header$"); #endif extern struct vcache *afs_globalVp; +extern afs_rwlock_t afs_xvcache; extern struct dentry_operations *afs_dops; #if defined(AFS_LINUX24_ENV) @@ -763,20 +764,33 @@ static int afs_linux_revalidate(struct dentry *dp) cred_t *credp; struct vrequest treq; struct vcache *vcp = ITOAFS(dp->d_inode); + struct vcache *rootvp = NULL; AFS_GLOCK(); + + if (afs_fakestat_enable && vcp->mvstat == 1 && vcp->mvid && + (vcp->states & CMValid) && (vcp->states & CStatd)) { + ObtainSharedLock(&afs_xvcache, 680); + rootvp = afs_FindVCache(vcp->mvid, 0, 0, 0, 0); + ReleaseSharedLock(&afs_xvcache); + } + #ifdef AFS_LINUX24_ENV lock_kernel(); #endif /* Make this a fast path (no crref), since it's called so often. */ if (vcp->states & CStatd) { - if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */ + if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */ check_bad_parent(dp); /* check and correct mvid */ - vcache2inode(vcp); + if (rootvp) + vcache2fakeinode(rootvp, vcp); + else + vcache2inode(vcp); #ifdef AFS_LINUX24_ENV unlock_kernel(); #endif + if (rootvp) afs_PutVCache(rootvp); AFS_GUNLOCK(); return 0; } @@ -893,7 +907,7 @@ static int afs_linux_dentry_revalidate(struct dentry *dp) unsigned long timeout = 3*HZ; /* 3 seconds */ -if (!ip) + if (!ip) printk("negative dentry: %s\n", dp->d_name.name); if (!(flags & LOOKUP_CONTINUE)) {