]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE14-macos-avoid-reclaim-hang-20060124 openafs-stable-1_4_1-rc5
authorDerrick Brashear <shadow@dementia.org>
Wed, 25 Jan 2006 04:47:11 +0000 (04:47 +0000)
committerDerrick Brashear <shadow@dementia.org>
Wed, 25 Jan 2006 04:47:11 +0000 (04:47 +0000)
FIXES 25686

based on chaskiel's suggestion, implement a lookaside reclaim list

(cherry picked from commit 1649de223462f5290974b7f05d09a41f9ff29bde)

src/afs/DARWIN/osi_vnodeops.c
src/afs/afs_callback.c
src/afs/afs_daemons.c
src/afs/afs_prototypes.h
src/afs/afs_vcache.c

index db02aa528d38d995f10ee9d63d5611d3b4e65406..3f248179aa12ec016b1eaabed497e21fb132edfd 100644 (file)
@@ -1624,7 +1624,7 @@ afs_vop_reclaim(ap)
                                 * } */ *ap;
 {
     int error = 0;
-    int sl;
+    int sl, writelocked;
     register struct vnode *vp = ap->a_vp;
     struct vcache *tvc = VTOAFS(vp);
 
@@ -1632,25 +1632,40 @@ afs_vop_reclaim(ap)
     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;
index e54d8850dfcff08762fa127ed713a1db452d8ca2..3ab7a434d95f846e8c0d7d90c8a664f6f0006967 100644 (file)
@@ -59,7 +59,9 @@ static struct ltable {
     "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;
index 9f40c3a9c0f5675bf3aa89f823f7f4def1f22a85..cf64703e1098d52fb0a6eb1dbc46f72be89210e7 100644 (file)
@@ -175,6 +175,9 @@ afs_Daemon(void)
            /* 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();
index f637226d031d25b4b9c8e2050cdbaa6c5a475031..dca36e9e56bc59c9e5d4b239ab44cbb39261368a 100644 (file)
@@ -811,6 +811,7 @@ extern afs_int32 afs_data_pointer_to_int32(const void *p);
 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;
@@ -819,6 +820,7 @@ extern unsigned int afs_paniconwarn;
 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,
index 1d2e08db5fcd49e8bb03ba5b6863b0c38351016b..2cd6b53e53f5117fd649f9133f8cd65cf7a4bbb3 100644 (file)
@@ -62,9 +62,11 @@ char *makesname();
 
 /* 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 */
@@ -572,6 +574,38 @@ afs_RemoveVCB(struct VenusFid *afid)
     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
  *
@@ -603,6 +637,9 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
     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)