ReleaseSharedLock(&avc->lock); /* release lock */
}
if (code) {
- ObtainWriteLock(&afs_xcbhash, 487);
- afs_DequeueCallback(avc);
- avc->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
/* error? erase any changes we made to vcache entry */
+ afs_StaleVCache(avc);
}
} else {
ObtainSharedLock(&avc->lock, 712);
if (code) {
if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 488);
- afs_DequeueCallback(adp);
- adp->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ afs_StaleVCache(adp);
}
ReleaseWriteLock(&adp->lock);
if (tdc) {
afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), volp);
}
} else {
- afs_DequeueCallback(tvc);
- tvc->f.states &= ~(CStatd | CUnique);
- tvc->callback = 0;
- if (tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
+ afs_StaleVCacheFlags(tvc,
+ AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+ CUnique);
}
ReleaseWriteLock(&afs_xcbhash);
if (AFS_IS_DISCON_RW) {
if (code) {
if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 490);
- afs_DequeueCallback(adp);
- adp->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ afs_StaleVCache(adp);
}
ReleaseWriteLock(&adp->lock);
if (tdc)
}
if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 491);
- afs_DequeueCallback(adp);
- adp->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ afs_StaleVCache(adp);
}
ReleaseWriteLock(&adp->lock);
goto done;
if (tdc)
afs_PutDCache(tdc);
if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 492);
- afs_DequeueCallback(adp);
- adp->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ afs_StaleVCache(adp);
}
ReleaseWriteLock(&adp->lock);
goto done;
* returned in ustat is the most recent to store in the file's
* cache entry */
- ObtainWriteLock(&afs_xcbhash, 493);
- afs_DequeueCallback(avc);
- avc->f.states &= ~CStatd; /* don't really know new link count */
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
+ afs_StaleVCache(avc); /* don't really know new link count */
ReleaseWriteLock(&avc->lock);
code = 0;
done:
tvcp->f.states |= CStatd;
afs_QueueCallback(tvcp, CBHash(3600), volp);
} else {
- tvcp->callback = 0;
- tvcp->f.states &= ~(CStatd | CUnique);
- afs_DequeueCallback(tvcp);
- if ((tvcp->f.states & CForeign) || (vType(tvcp) == VDIR))
- osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(tvcp,
+ AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+ CUnique);
}
#ifdef AFS_DARWIN80_ENV
/* reclaim->FlushVCache will need xcbhash */
code = afs_darwin_finalizevnode(tvcp, NULL, NULL, 0, 1);
if (code) {
/* It's gonna get recycled - shouldn't happen */
- tvcp->callback = 0;
- tvcp->f.states &= ~(CStatd | CUnique);
- afs_DequeueCallback(tvcp);
- if ((tvcp->f.states & CForeign) || (vType(tvcp) == VDIR))
- osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(tvcp,
+ AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+ CUnique);
} else
/* re-acquire the usecount that finalizevnode disposed of */
vnode_ref(AFSTOV(tvcp));
if (tv) {
if (tv->states & VRO) {
pass = 1; /* try this *once* */
- ObtainWriteLock(&afs_xcbhash, 495);
- afs_DequeueCallback(adp);
- /* re-stat to get later version */
- adp->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ /* re-stat to get later version */
+ afs_StaleVCache(adp);
afs_PutVolume(tv, READ_LOCK);
goto redo;
}
afs_PutVCache(tvc);
if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 497);
- afs_DequeueCallback(adp);
- adp->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ afs_StaleVCache(adp);
}
ReleaseWriteLock(&adp->lock);
code = afs_CheckCode(code, treqp, 21);
/* if failed, server might have done something anyway, and
* assume that we know about it */
ObtainWriteLock(&afs_xcbhash, 498);
- afs_DequeueCallback(aodp);
- afs_DequeueCallback(andp);
- andp->f.states &= ~CStatd;
- aodp->f.states &= ~CStatd;
+ afs_StaleVCacheFlags(aodp, AFS_STALEVC_CBLOCKED, 0);
+ afs_StaleVCacheFlags(andp, AFS_STALEVC_CBLOCKED, 0);
ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(andp);
- osi_dnlc_purgedp(aodp);
}
}
ObtainWriteLock(&afs_xvcache, 40);
if (code) {
if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 499);
- afs_DequeueCallback(adp);
- adp->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ afs_StaleVCache(adp);
}
ReleaseWriteLock(&adp->lock);
ReleaseWriteLock(&afs_xvcache);
ObtainReadLock(&afs_xvcache);
if ((tvc = afs_FindVCache(afid, 0, 0))) {
ReleaseReadLock(&afs_xvcache);
- tvc->f.states &= ~(CStatd | CUnique);
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_NOCB | AFS_STALEVC_NODNLC,
+ CUnique);
afs_PutVCache(tvc);
} else {
ReleaseReadLock(&afs_xvcache);
}
}
-#if 0
/* also cg2v, don't dequeue the callback */
- ObtainWriteLock(&afs_xcbhash, 956);
- afs_DequeueCallback(avc);
- ReleaseWriteLock(&afs_xcbhash);
-#endif
- avc->f.states &= ~(CStatd | CDirty); /* next reference will re-stat */
+ /* next reference will re-stat */
+ afs_StaleVCacheFlags(avc, AFS_STALEVC_NOCB, CDirty);
/* now find the disk cache entries */
afs_TryToSmush(avc, acred, 1);
- osi_dnlc_purgedp(avc);
if (avc->linkData && !(avc->f.states & CCore)) {
afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
avc->linkData = NULL;
goto done;
/* Ok, we actually do need to flush */
- ObtainWriteLock(&afs_xcbhash, 957);
- afs_DequeueCallback(avc);
- avc->f.states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
- ReleaseWriteLock(&afs_xcbhash);
+ /* next reference will re-stat cache entry */
+ afs_StaleVCacheFlags(avc, 0, CDirty);
+
/* now find the disk cache entries */
afs_TryToSmush(avc, acred, 1);
- osi_dnlc_purgedp(avc);
if (avc->linkData && !(avc->f.states & CCore)) {
afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
avc->linkData = NULL;
#endif
#endif
ReleaseReadLock(&afs_xvcache);
- ObtainWriteLock(&afs_xcbhash, 449);
- afs_DequeueCallback(tvc);
- tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
+ afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
afs_allCBs++;
if (tvc->f.fid.Fid.Vnode & 1)
afs_oddCBs++;
else
afs_evenCBs++;
- ReleaseWriteLock(&afs_xcbhash);
- if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
- osi_dnlc_purgedp(tvc);
afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
tvc->f.states, ICL_TYPE_INT32,
#endif
#endif
ReleaseReadLock(&afs_xvcache);
- ObtainWriteLock(&afs_xcbhash, 450);
- afs_DequeueCallback(tvc);
- tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
- ReleaseWriteLock(&afs_xcbhash);
- if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
- osi_dnlc_purgedp(tvc);
+ afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
tvc->f.states, ICL_TYPE_LONG, 0);
for (i = 0; i < VCSIZE; i++)
for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
if (tvc->callback == ts) {
- ObtainWriteLock(&afs_xcbhash, 451);
- afs_DequeueCallback(tvc);
- tvc->callback = NULL;
- tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
- ReleaseWriteLock(&afs_xcbhash);
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_NODNLC |
+ AFS_STALEVC_CLEARCB,
+ CUnique | CBulkFetching);
}
}
if (!(tvp->serverHost[i]->flags & SRVR_ISDOWN)) {
/* What about locking xvcache or vrefcount++ or
* write locking tvc? */
- QRemove(tq);
- tvc->f.states &= ~(CStatd | CMValid | CUnique);
- if (!(tvc->f.states & (CVInit|CVFlushed)) &&
- (tvc->f.fid.Fid.Vnode & 1 ||
- (vType(tvc) == VDIR)))
- osi_dnlc_purgedp(tvc);
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED |
+ AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED,
+ CMValid | CUnique);
tvc->dchint = NULL; /*invalidate em */
afs_ResetVolumeInfo(tvp);
break;
/* Do I need to worry about things like execsorwriters?
* What about locking xvcache or vrefcount++ or write locking tvc?
*/
- QRemove(tq);
- tvc->f.states &= ~(CStatd | CMValid | CUnique);
- if (!(tvc->f.states & (CVInit|CVFlushed)) &&
- (tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
- osi_dnlc_purgedp(tvc);
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED |
+ AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED,
+ CMValid | CUnique);
}
}
for (i = 0; i < VCSIZE; i++) /* reset all the vnodes */
for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- tvc->callback = 0;
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED |
+ AFS_STALEVC_CLEARCB |
+ AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED, 0);
tvc->dchint = NULL; /* invalidate hints */
- tvc->f.states &= ~(CStatd);
- if (QPrev(&(tvc->callsort)))
- QRemove(&(tvc->callsort));
- if (!(tvc->f.states & (CVInit|CVFlushed)) &&
- ((tvc->f.fid.Fid.Vnode & 1) || (vType(tvc) == VDIR)))
- osi_dnlc_purgedp(tvc);
}
afs_InitCBQueue(0);
for (i = 0; i < VCSIZE; i++) { /* reset all the vnodes */
for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
if (tvc->callback == srvp) {
- tvc->callback = 0;
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED |
+ AFS_STALEVC_CLEARCB |
+ AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED, 0);
tvc->dchint = NULL; /* invalidate hints */
- tvc->f.states &= ~(CStatd);
- if (!(tvc->f.states & (CVInit|CVFlushed)) &&
- ((tvc->f.fid.Fid.Vnode & 1) || (vType(tvc) == VDIR))) {
- osi_dnlc_purgedp(tvc);
- }
- afs_DequeueCallback(tvc);
}
}
}
afs_CFileTruncate(file, size); /* prune it */
} else {
if (!setLocks || slowPass) {
- ObtainWriteLock(&afs_xcbhash, 453);
- afs_DequeueCallback(avc);
- avc->f.states &= ~(CStatd | CUnique);
- avc->callback = NULL;
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
+ afs_StaleVCacheFlags(avc, AFS_STALEVC_CLEARCB, CUnique);
} else {
/* Something lost. Forget about performance, and go
* back with a vcache write lock.
ReleaseWriteLock(&tdc->lock);
afs_PutDCache(tdc);
if (!afs_IsDynroot(avc)) {
- ObtainWriteLock(&afs_xcbhash, 454);
- afs_DequeueCallback(avc);
- avc->f.states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
+ afs_StaleVCacheFlags(avc, 0, CUnique);
/*
* Locks held:
* avc->lock(W); assert(!setLocks || slowPass)
ReleaseReadLock(&afs_xvcache);
} while (retry);
if (tvc) {
- tvc->f.states &= ~(CStatd | CUnique);
- osi_dnlc_purgedp(tvc);
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_NOCB, CUnique);
afs_PutVCache(tvc);
}
}
SHARED_LOCK, NULL));
/* now we've forgotten all of the access info */
- ObtainWriteLock(&afs_xcbhash, 455);
- avc->callback = 0;
- afs_DequeueCallback(avc);
- avc->f.states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
+ afs_StaleVCacheFlags(avc, AFS_STALEVC_CLEARCB, CUnique);
/* SXW - Should we flush metadata here? */
+
return code;
}
(tc, rxconn, code, &avc->f.fid, areq,
AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS, SHARED_LOCK, NULL));
- ObtainWriteLock(&afs_xcbhash, 457);
- afs_DequeueCallback(avc);
- avc->callback = 0;
- avc->f.states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
+ afs_StaleVCacheFlags(avc, AFS_STALEVC_CLEARCB, CUnique);
}
ReleaseWriteLock(&avc->lock);
return 0;
goto out;
}
ObtainWriteLock(&tvc->lock, 649);
- ObtainWriteLock(&afs_xcbhash, 650);
- afs_DequeueCallback(tvc);
- tvc->f.states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
- ReleaseWriteLock(&afs_xcbhash);
+ /* next reference will re-stat cache entry */
+ afs_StaleVCacheFlags(tvc, 0, CDirty);
/* now find the disk cache entries */
afs_TryToSmush(tvc, *acred, 1);
- osi_dnlc_purgedp(tvc);
if (tvc->linkData && !(tvc->f.states & CCore)) {
afs_osi_Free(tvc->linkData, strlen(tvc->linkData) + 1);
tvc->linkData = NULL;
struct vcache *avc);
extern void afs_PutVCache(struct vcache *avc);
extern int afs_RefVCache(struct vcache *avc);
+
+/* Flags for afs_StaleVCacheFlags */
+
+/* afs_xcbhash is already locked by the caller */
+#define AFS_STALEVC_CBLOCKED (0x01)
+
+/* Normally we assume we only need to invalidate cached
+ * name -> vcache mappings for entries where the given
+ * vcache is the parent dir. This flag says to also clear
+ * entries for the vcache itself. */
+#define AFS_STALEVC_FILENAME (0x02)
+
+/* Do not touch the DNLC; the caller will deal with it. */
+#define AFS_STALEVC_NODNLC (0x04)
+
+/* Do not run afs_DequeueCallback; the caller will take
+ * care of callback management. */
+#define AFS_STALEVC_NOCB (0x08)
+
+/* NULL-out the callback field of the vcache, to save code at the callsite. */
+#define AFS_STALEVC_CLEARCB (0x10)
+
+/* Skip the DNLC purge if CVInit or CVFlushed is set, for efficiency.
+ * A transitional flag used to reduce the logic change during refactoring
+ * that is expected to be removed and the purge behavior standardized. */
+#define AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED (0x20)
+typedef unsigned int afs_stalevc_flags_t;
+
+#define afs_StaleVCache(avc) afs_StaleVCacheFlags(avc, 0, 0)
+extern void afs_StaleVCacheFlags(struct vcache *avc, afs_stalevc_flags_t flags,
+ afs_uint32 cflags);
+
extern void afs_ProcessFS(struct vcache *avc,
struct AFSFetchStatus *astat,
struct vrequest *areq);
hash = DVHash(&avc->f.fid);
avc->f.truncPos = AFS_NOTRUNC; /* don't truncate later */
avc->f.states &= ~CExtendedFile; /* not any more */
- ObtainWriteLock(&afs_xcbhash, 459);
- afs_DequeueCallback(avc);
- avc->f.states &= ~(CStatd | CDirty); /* mark status information as bad, too */
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
+ afs_StaleVCacheFlags(avc, 0, CDirty);
/* Blow away pages; for now, only for Solaris */
#if (defined(AFS_SUN5_ENV))
if (WriteLocked(&avc->lock))
vn_reinit(AFSTOV(avc));
#endif
afs_FreeAllAxs(&(avc->Access));
- ObtainWriteLock(&afs_xcbhash, 460);
- afs_DequeueCallback(avc); /* remove it from queued callbacks list */
- avc->f.states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc); /* if it (could be) a directory */
- else
- osi_dnlc_purgevp(avc);
+ afs_StaleVCacheFlags(avc, AFS_STALEVC_FILENAME, CUnique);
/* By this point, the vcache has been removed from all global structures
* via which someone could try to use the vcache. It is okay to drop
ReleaseWriteLock(&avc->lock);
return 0;
}
- ObtainWriteLock(&afs_xcbhash, 461);
- avc->f.states &= ~(CStatd | CUnique);
- avc->callback = NULL;
- afs_DequeueCallback(avc);
- ReleaseWriteLock(&afs_xcbhash);
+ afs_StaleVCacheFlags(avc, AFS_STALEVC_FILENAME | AFS_STALEVC_CLEARCB,
+ CUnique);
ReleaseWriteLock(&avc->lock);
- /* since we've been called back, or the callback has expired,
- * it's possible that the contents of this directory, or this
- * file's name have changed, thus invalidating the dnlc contents.
- */
- if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc);
- else
- osi_dnlc_purgevp(avc);
-
/* fetch the status info */
tvc = afs_GetVCache(&avc->f.fid, areq, NULL, avc);
if (!tvc)
avc->f.m.Date = OutStatus.ClientModTime;
} else {
/* failure, set up to check with server next time */
- ObtainWriteLock(&afs_xcbhash, 462);
- afs_DequeueCallback(avc);
- avc->f.states &= ~(CStatd | CUnique); /* turn off stat valid flag */
- ReleaseWriteLock(&afs_xcbhash);
- if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(avc, 0, CUnique);
}
ConvertWToSLock(&avc->lock);
return code;
#endif
#endif
- ObtainWriteLock(&afs_xcbhash, 464);
- tvc->f.states &= ~CUnique;
- tvc->callback = 0;
- afs_DequeueCallback(tvc);
- ReleaseWriteLock(&afs_xcbhash);
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_NODNLC | AFS_STALEVC_CLEARCB,
+ CUnique);
/* It is always appropriate to throw away all the access rights? */
afs_FreeAllAxs(&(tvc->Access));
}
if (code) {
- ObtainWriteLock(&afs_xcbhash, 465);
- afs_DequeueCallback(tvc);
- tvc->f.states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(tvc, 0, CUnique);
if (tvp)
afs_PutVolume(tvp, READ_LOCK);
ReleaseWriteLock(&tvc->lock);
tvc->f.states &= ~CBulkFetching;
afs_QueueCallback(tvc, CBHash(3600), tvp);
} else {
- tvc->callback = NULL;
- afs_DequeueCallback(tvc);
- tvc->f.states &= ~(CStatd | CUnique);
- if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(tvc,
+ AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+ CUnique);
}
} else {
- afs_DequeueCallback(tvc);
- tvc->f.states &= ~CStatd;
- tvc->f.states &= ~CUnique;
- tvc->callback = NULL;
- if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(tvc,
+ AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+ CUnique);
}
ReleaseWriteLock(&afs_xcbhash);
if (tvp)
}
if (code) {
- ObtainWriteLock(&afs_xcbhash, 467);
- afs_DequeueCallback(tvc);
- tvc->callback = NULL;
- tvc->f.states &= ~(CStatd | CUnique);
- ReleaseWriteLock(&afs_xcbhash);
- if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_CLEARCB, CUnique);
ReleaseWriteLock(&tvc->lock);
afs_PutVCache(tvc);
return NULL;
afs_QueueCallback(tvc, CBHash(3600), tvolp);
}
} else {
- afs_DequeueCallback(tvc);
- tvc->callback = NULL;
- tvc->f.states &= ~(CStatd | CUnique);
- if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+ CUnique);
}
ReleaseWriteLock(&afs_xcbhash);
afs_ProcessFS(tvc, &OutStatus, areq);
avc->f.states &= ~CBulkFetching;
afs_QueueCallback(avc, CBHash(3600), volp);
} else {
- afs_DequeueCallback(avc);
- avc->callback = NULL;
- avc->f.states &= ~(CStatd | CUnique);
- if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(avc,
+ AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+ CUnique);
}
} else {
- afs_DequeueCallback(avc);
- avc->callback = NULL;
- avc->f.states &= ~(CStatd | CUnique);
- if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(avc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(avc, AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+ CUnique);
}
ReleaseWriteLock(&afs_xcbhash);
if (volp)
ReleaseSharedLock(&afs_xvcache);
ObtainWriteLock(&tvc->lock, 58);
- tvc->f.states &= ~CStatd;
- if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_NOCB, 0);
/* Is it always appropriate to throw away all the access rights? */
afs_FreeAllAxs(&(tvc->Access));
tvc->f.states &= ~CBulkFetching;
afs_QueueCallback(tvc, CBHash(3600), tvp);
} else {
- afs_DequeueCallback(tvc);
- tvc->callback = NULL;
- tvc->f.states &= ~(CStatd | CUnique);
- if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
- osi_dnlc_purgedp(tvc); /* if it (could be) a directory */
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+ CUnique);
}
ReleaseWriteLock(&afs_xcbhash);
if (tvp)
void
afs_ResetVCache(struct vcache *avc, afs_ucred_t *acred, afs_int32 skipdnlc)
{
- ObtainWriteLock(&afs_xcbhash, 456);
- afs_DequeueCallback(avc);
- avc->f.states &= ~(CStatd | CDirty); /* next reference will re-stat */
- ReleaseWriteLock(&afs_xcbhash);
+ afs_stalevc_flags_t flags = 0;
+ if (skipdnlc) {
+ flags |= AFS_STALEVC_NODNLC;
+ }
+
+ afs_StaleVCacheFlags(avc, flags, CDirty); /* next reference will re-stat */
/* now find the disk cache entries */
afs_TryToSmush(avc, acred, 1);
- if (!skipdnlc) {
- osi_dnlc_purgedp(avc);
- }
if (avc->linkData && !(avc->f.states & CCore)) {
afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
avc->linkData = NULL;
for (i = 0; i < VCSIZE; i++) {
for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
- tvc->f.states &= ~(CStatd|CUnique);
+ afs_StaleVCacheFlags(tvc, AFS_STALEVC_NODNLC | AFS_STALEVC_NOCB,
+ CUnique);
}
}
ReleaseWriteLock(&afs_xvcache);
}
+
+/**
+ * Mark a vcache as stale; our metadata for the relevant file may be out of
+ * date.
+ *
+ * @post Any subsequent access to this vcache will cause us to fetch the
+ * metadata for this vcache again.
+ */
+void
+afs_StaleVCacheFlags(struct vcache *avc, afs_stalevc_flags_t flags,
+ afs_uint32 cflags)
+{
+ int do_dnlc = 1;
+ int do_filename = 0;
+ int do_dequeue = 1;
+ int lock_cbhash = 1;
+
+ if ((flags & AFS_STALEVC_NODNLC)) {
+ do_dnlc = 0;
+ }
+ if ((flags & AFS_STALEVC_FILENAME)) {
+ do_filename = 1;
+ }
+ if ((flags & AFS_STALEVC_CBLOCKED)) {
+ lock_cbhash = 0;
+ }
+ if ((flags & AFS_STALEVC_NOCB)) {
+ do_dequeue = 0;
+ lock_cbhash = 0;
+ }
+
+ if (lock_cbhash) {
+ ObtainWriteLock(&afs_xcbhash, 486);
+ }
+ if (do_dequeue) {
+ afs_DequeueCallback(avc);
+ }
+
+ cflags |= CStatd;
+ avc->f.states &= ~cflags;
+
+ if (lock_cbhash) {
+ ReleaseWriteLock(&afs_xcbhash);
+ }
+
+ if ((flags & AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED) &&
+ (avc->f.states & (CVInit | CVFlushed))) {
+ do_dnlc = 0;
+ }
+
+ if (flags & AFS_STALEVC_CLEARCB) {
+ avc->callback = NULL;
+ }
+
+ if (do_dnlc) {
+ if ((avc->f.fid.Fid.Vnode & 1) || vType(avc) == VDIR ||
+ (avc->f.states & CForeign)) {
+ /* This vcache is (or could be) a directory. */
+ osi_dnlc_purgedp(avc);
+
+ } else if (do_filename) {
+ osi_dnlc_purgevp(avc);
+ }
+ }
+}
#endif
ReleaseReadLock(&afs_xvcache);
- ObtainWriteLock(&afs_xcbhash, 485);
/* LOCKXXX: We aren't holding tvc write lock? */
- afs_DequeueCallback(tvc);
- tvc->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- if (tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
+ afs_StaleVCache(tvc);
#ifdef AFS_DARWIN80_ENV
vnode_put(AFSTOV(tvc));