struct vrequest treq;
struct vcache *vcp = ITOAFS(dp->d_inode);
struct vcache *rootvp = NULL;
- struct afs_fakestat_state fakestat;
AFS_GLOCK();
- afs_InitFakeStat(&fakestat);
- if (vcp->mvstat == 1) {
- afs_InitReq(&treq, credp);
- rootvp = vcp;
- code = afs_TryEvalFakeStat(&rootvp, &fakestat, &treq);
- if (code) {
- AFS_GUNLOCK();
- return -code;
- }
+ 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
if (vcp->states & CStatd) {
if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
check_bad_parent(dp); /* check and correct mvid */
- if (rootvp && rootvp != vcp)
+ if (rootvp)
vcache2fakeinode(rootvp, vcp);
else
vcache2inode(vcp);
#ifdef AFS_LINUX24_ENV
unlock_kernel();
#endif
- afs_PutFakeStat(&fakestat);
+ if (rootvp) afs_PutVCache(rootvp);
AFS_GUNLOCK();
return 0;
}
#ifdef AFS_LINUX24_ENV
unlock_kernel();
#endif
- afs_PutFakeStat(&fakestat);
AFS_GUNLOCK();
crfree(credp);
afs_int32 afs_bulkStatsDone;
static int bulkStatCounter = 0; /* counter for bulk stat seq. numbers */
-int afs_fakestat_enable = 0;
+int afs_fakestat_enable = 0; /* 1: fakestat-all, 2: fakestat-crosscell */
/* this would be faster if it did comparison as int32word, but would be
*
* The actual implementation of afs_EvalFakeStat and afs_TryEvalFakeStat,
* which is called by those wrapper functions.
+ *
+ * Only issues RPCs if canblock is non-zero.
*/
-static int afs_EvalFakeStat_int(stricr vcache **avcp,
- struct afs_fakestat_state *state, struct vrequest *areq, int canblock)
+int afs_EvalFakeStat_int(struct vcache **avcp, struct afs_fakestat_state *state,
+ struct vrequest *areq, int canblock)
{
struct vcache *tvc, *root_vp;
struct volume *tvolp = NULL;
if (tvc->mvstat != 1)
return 0;
+ /* Is the call to VerifyVCache really necessary? */
code = afs_VerifyVCache(tvc, areq);
if (code)
goto done;
-
- if (afs_fakestat_enable == 2 && !canblock) {
- ObtainSharedLock(&tvc->lock, 680);
- if (!tvc->linkData) {
- UpgradeSToWLock(&tvc->lock, 681);
- code = afs_HandleLink(tvc, areq);
- if (code) {
- ReleaseWriteLock(&tvc->lock);
- goto done;
- }
- ConvertWToRLock(&tvc->lock);
- } else {
- ConvertSToRLock(&tvc->lock);
- }
-
- if (!afs_strchr(tvc->linkData, ':'))
- canblock = 1;
- ReleaseReadLock(&tvc->lock);
- }
-
if (canblock) {
ObtainWriteLock(&tvc->lock, 599);
code = EvalMountPoint(tvc, NULL, &tvolp, areq);
} /* sub-block just to reduce stack usage */
if (tvc) {
- if (adp->states & CForeign)
+ int force_eval = afs_fakestat_enable ? 0 : 1;
+
+ if (adp->states & CForeign)
tvc->states |= CForeign;
tvc->parentVnode = adp->fid.Fid.Vnode;
tvc->parentUnique = adp->fid.Fid.Unique;
tvc->states &= ~CBulkStat;
+ if (afs_fakestat_enable == 2 && tvc->mvstat == 1) {
+ ObtainSharedLock(&tvc->lock, 680);
+ if (!tvc->linkData) {
+ UpgradeSToWLock(&tvc->lock, 681);
+ code = afs_HandleLink(tvc, &treq);
+ ConvertWToRLock(&tvc->lock);
+ } else {
+ ConvertSToRLock(&tvc->lock);
+ code = 0;
+ }
+ if (!code && !strchr(tvc->linkData, ':'))
+ force_eval = 1;
+ ReleaseReadLock(&tvc->lock);
+ }
+
#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
if (!(flags & AFS_LOOKUP_NOEVAL))
/* don't eval mount points */
#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
- if (!afs_fakestat_enable && tvc->mvstat == 1) {
+ if (tvc->mvstat == 1 && force_eval) {
/* a mt point, possibly unevaluated */
struct volume *tvolp;