* } */ *ap;
{
int error = 0;
- int sl;
+ int sl, writelocked;
register struct vnode *vp = ap->a_vp;
struct vcache *tvc = VTOAFS(vp);
cache_purge(vp); /* just in case... */
if (tvc) {
AFS_GLOCK();
- ObtainWriteLock(&afs_xvcache, 335);
- error = afs_FlushVCache(tvc, &sl); /* toss our stuff from vnode */
- if (tvc->states & (CVInit
+ writelocked = (0 == NBObtainWriteLock(&afs_xvcache, 335));
+ if (!writelocked) {
+ ObtainWriteLock(&afs_xvreclaim, 176);
#ifdef AFS_DARWIN80_ENV
- | CDeadVnode
-#endif
- )) {
- tvc->states &= ~(CVInit
+ vnode_clearfsnode(AFSTOV(tvc));
+ vnode_removefsref(AFSTOV(tvc));
+#else
+ tvc->v->v_data = NULL; /* remove from vnode */
+#endif
+ AFSTOV(tvc) = NULL; /* also drop the ptr to vnode */
+ tvc->states |= CVInit; /* also CDeadVnode? */
+ tvc->nextfree = ReclaimedVCList;
+ ReclaimedVCList = tvc;
+ ReleaseWriteLock(&afs_xvreclaim);
+ } else {
+ error = afs_FlushVCache(tvc, &sl); /* toss our stuff from vnode */
+ if (tvc->states & (CVInit
#ifdef AFS_DARWIN80_ENV
- | CDeadVnode
+ | CDeadVnode
#endif
- );
- afs_osi_Wakeup(&tvc->states);
+ )) {
+ tvc->states &= ~(CVInit
+#ifdef AFS_DARWIN80_ENV
+ | CDeadVnode
+#endif
+ );
+ afs_osi_Wakeup(&tvc->states);
+ }
+ if (!error && vnode_fsnode(vp))
+ panic("afs_reclaim: vnode not cleaned");
+ if (!error && (tvc->v != NULL))
+ panic("afs_reclaim: vcache not cleaned");
+ ReleaseWriteLock(&afs_xvcache);
}
- if (!error && vnode_fsnode(vp))
- panic("afs_reclaim: vnode not cleaned");
- if (!error && (tvc->v != NULL))
- panic("afs_reclaim: vcache not cleaned");
- ReleaseWriteLock(&afs_xvcache);
AFS_GUNLOCK();
}
return error;
"afs_xosi", (char *)&afs_xosi},
#endif
{
- "afs_xsrvAddr", (char *)&afs_xsrvAddr}
+ "afs_xsrvAddr", (char *)&afs_xsrvAddr},
+ {
+ "afs_xvreclaim", (char *)&afs_xvreclaim}
};
unsigned long lastCallBack_vnode;
unsigned int lastCallBack_dv;
/* things to do every minute */
DFlush(); /* write out dir buffers */
afs_WriteThroughDSlots(); /* write through cacheinfo entries */
+ ObtainWriteLock(&afs_xvcache, 736);
+ afs_FlushReclaimedVcaches();
+ ReleaseWriteLock(&afs_xvcache);
afs_FlushActiveVcaches(1); /* keep flocks held & flush nfs writes */
#ifdef AFS_DISCON_ENV
afs_StoreDirtyVcaches();
extern afs_int32 afs_maxvcount;
extern afs_int32 afs_vcount;
extern int afsvnumbers;
+extern afs_rwlock_t afs_xvreclaim;
extern afs_rwlock_t afs_xvcache;
extern afs_lock_t afs_xvcb;
extern struct afs_q VLRU;
extern struct afs_q afs_vhashTV[VCSIZE];
extern afs_int32 afs_bulkStatsLost;
extern int afs_norefpanic;
+extern struct vcache *ReclaimedVCList;
void afs_vcacheInit(int astatSize);
extern struct vcache *afs_FindVCache(struct VenusFid *afid, afs_int32 * retry,
/* Exported variables */
afs_rwlock_t afs_xvcache; /*Lock: alloc new stat cache entries */
+afs_rwlock_t afs_xvreclaim; /*Lock: entries reclaimed, not on free list */
afs_lock_t afs_xvcb; /*Lock: fids on which there are callbacks */
#if !defined(AFS_LINUX22_ENV)
static struct vcache *freeVCList; /*Free list for stat cache entries */
+struct vcache *ReclaimedVCList; /*Reclaimed list for stat entries */
static struct vcache *Initial_freeVCList; /*Initial list for above */
#endif
struct afs_q VLRU; /*vcache LRU */
MReleaseWriteLock(&afs_xvcb);
}
+void
+afs_FlushReclaimedVcaches(void)
+{
+#if !defined(AFS_LINUX22_ENV)
+ struct vcache *tvc;
+ int code, fv_slept;
+ struct vcache *tmpReclaimedVCList = NULL;
+
+ ObtainWriteLock(&afs_xvreclaim, 76);
+ while (ReclaimedVCList) {
+ tvc = ReclaimedVCList; /* take from free list */
+ ReclaimedVCList = tvc->nextfree;
+ tvc->nextfree = NULL;
+ code = afs_FlushVCache(tvc, &fv_slept);
+ if (code) {
+ /* Ok, so, if we got code != 0, uh, wtf do we do? */
+ /* Probably, build a temporary list and then put all back when we
+ get to the end of the list */
+ /* This is actually really crappy, but we need to not leak these.
+ We probably need a way to be smarter about this. */
+ tvc->nextfree = tmpReclaimedVCList;
+ tmpReclaimedVCList = tvc;
+ printf("Reclaim list flush %x failed: %d\n", tvc, code);
+ }
+ }
+ if (tmpReclaimedVCList)
+ ReclaimedVCList = tmpReclaimedVCList;
+
+ ReleaseWriteLock(&afs_xvreclaim);
+#endif
+}
+
/*
* afs_NewVCache
*
int code, fv_slept;
AFS_STATCNT(afs_NewVCache);
+
+ afs_FlushReclaimedVcaches();
+
#if defined(AFS_OSF_ENV) || defined(AFS_LINUX22_ENV)
#if defined(AFS_OSF30_ENV) || defined(AFS_LINUX22_ENV)
if (afs_vcount >= afs_maxvcount)