struct afs_q vlruq; /* lru q next and prev */
struct vcache *nextfree; /* next on free list (if free) */
struct vcache *hnext; /* Hash next */
+ struct vcache *vhnext; /* vol hash next */
struct VenusFid fid;
struct mstat {
afs_size_t Length;
/* don't hash on the cell, our callback-breaking code sometimes fails to compute
the cell correctly, and only scans one hash bucket */
#define VCHash(fid) (((fid)->Fid.Volume + (fid)->Fid.Vnode) & (VCSIZE-1))
+/* Hash only on volume to speed up volume callbacks. */
+#define VCHashV(fid) ((fid)->Fid.Volume & (VCSIZE-1))
extern struct dcache **afs_indexTable; /*Pointers to in-memory dcache entries */
extern afs_int32 *afs_indexUnique; /*dcache entry Fid.Unique */
extern afs_int32 afs_cacheBlocks; /*1K blocks in cache */
extern afs_int32 afs_cacheStats; /*Stat entries in cache */
extern struct vcache *afs_vhashT[VCSIZE]; /*Stat cache hash table */
+extern struct vcache *afs_vhashTV[VCSIZE]; /* cache hash table on volume */
extern afs_int32 afs_initState; /*Initialization state */
extern afs_int32 afs_termState; /* Termination state */
extern struct VenusFid afs_rootFid; /*Root for whole file system */
* Clear callback for the whole volume. Zip through the
* hash chain, nullifying entries whose volume ID matches.
*/
- for (i = 0; i < VCSIZE; i++)
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
+ i = VCHashV(&localFid);
+ for (tvc = afs_vhashTV[i]; tvc; tvc = tvc->vhnext) {
if (tvc->fid.Fid.Volume == a_fid->Volume) {
tvc->callback = NULL;
tvc->quick.stamp = 0;
* the vcaches associated with the volume.
*/
ObtainReadLock(&afs_xvcache);
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
+ i = VCHashV(&avc->fid);
+ for (tvc = afs_vhashT[i]; tvc; tvc = tvc->vhnext) {
if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
#if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
VN_HOLD(AFSTOV(tvc));
AFS_FAST_RELE(tvc);
}
}
- }
ReleaseReadLock(&afs_xvcache);
afs_int32 vcachegen = 0;
unsigned int afs_paniconwarn = 0;
struct vcache *afs_vhashT[VCSIZE];
+struct vcache *afs_vhashTV[VCSIZE];
static struct afs_cbr *afs_cbrHashT[CBRSIZE];
afs_int32 afs_bulkStatsLost;
int afs_norefpanic = 0;
afs_FlushVCache(struct vcache *avc, int *slept)
{ /*afs_FlushVCache */
- register afs_int32 i, code;
- register struct vcache **uvc, *wvc;
+ afs_int32 i, code, j;
+ struct vcache **uvc, *wvc, **uvc2, *wvc2;
*slept = 0;
AFS_STATCNT(afs_FlushVCache);
break;
}
}
- if (!wvc)
+
+ /* remove entry from the volume hash table */
+ j = VCHashV(&avc->fid);
+ uvc2 = &afs_vhashTV[j];
+ for (wvc2 = *uvc2; wvc2; uvc2 = &wvc2->vhnext, wvc2 = *uvc2) {
+ if (avc == wvc2) {
+ *uvc2 = avc->vhnext;
+ avc->vhnext = (struct vcache *)NULL;
+ break;
+ }
+ }
+ if (!wvc || !wvc2)
osi_Panic("flushvcache"); /* not in correct hash bucket */
if (avc->mvid)
osi_FreeSmallSpace(avc->mvid);
afs_NewVCache(struct VenusFid *afid, struct server *serverp)
{
struct vcache *tvc;
- afs_int32 i;
+ afs_int32 i, j;
afs_int32 anumber = VCACHE_FREE;
#ifdef AFS_AIX_ENV
struct gnode *gnodepnt;
memset((char *)&(tvc->callsort), 0, sizeof(struct afs_q));
tvc->slocks = NULL;
i = VCHash(afid);
+ j = VCHashV(afid);
tvc->hnext = afs_vhashT[i];
- afs_vhashT[i] = tvc;
+ tvc->vhnext = afs_vhashTV[j];
+ afs_vhashT[i] = afs_vhashTV[j] = tvc;
+
if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) {
refpanic("NewVCache VLRU inconsistent");
}
afs_FreeAllAxs(&(tvc->Access));
}
- afs_vhashT[i] = 0;
+ afs_vhashT[i] = afs_vhashTV[i] = 0;
}
}
/*