make-clearcallback-faster-20050524
authorKlas Lindfors <klas@it.su.se>
Wed, 25 May 2005 00:06:43 +0000 (00:06 +0000)
committerDerrick Brashear <shadow@dementia.org>
Wed, 25 May 2005 00:06:43 +0000 (00:06 +0000)
FIXES 4413

hash callbacks twice so we can discard them more quickly.

src/afs/afs.h
src/afs/afs_callback.c
src/afs/afs_pioctl.c
src/afs/afs_vcache.c

index 0205b75..25a49ad 100644 (file)
@@ -620,6 +620,7 @@ struct vcache {
     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;
@@ -1065,6 +1066,8 @@ struct memCacheEntry {
 /* 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 */
@@ -1074,6 +1077,7 @@ extern afs_int32 afs_cacheFiles;  /*Size of afs_indexTable */
 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 */
index bc044c2..05885e5 100644 (file)
@@ -388,8 +388,8 @@ ClearCallBack(register struct rx_connection *a_conn,
             * 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;
index 18e02d5..c298e8e 100644 (file)
@@ -2543,8 +2543,8 @@ DECL_PIOCTL(PFlushVolumeData)
      * 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));
@@ -2577,7 +2577,6 @@ DECL_PIOCTL(PFlushVolumeData)
                AFS_FAST_RELE(tvc);
            }
        }
-    }
     ReleaseReadLock(&afs_xvcache);
 
 
index 820de02..3dc65f4 100644 (file)
@@ -69,6 +69,7 @@ struct afs_q VLRU;            /*vcache LRU */
 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;
@@ -129,8 +130,8 @@ int
 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);
@@ -174,7 +175,18 @@ afs_FlushVCache(struct vcache *avc, int *slept)
            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);
@@ -576,7 +588,7 @@ struct vcache *
 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;
@@ -1074,9 +1086,12 @@ restart:
     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");
     }
@@ -2861,7 +2876,7 @@ shutdown_vcache(void)
 
                afs_FreeAllAxs(&(tvc->Access));
            }
-           afs_vhashT[i] = 0;
+           afs_vhashT[i] = afs_vhashTV[i] = 0;
        }
     }
     /*