MacOS: allow cdead vcaches to be found in FindVCache if requested
[openafs.git] / src / afs / afs_vcache.c
index 4ad9855..dc6a799 100644 (file)
@@ -360,6 +360,39 @@ afs_FreeCBR(struct afs_cbr *asp)
     return 0;
 }
 
+static void
+FlushAllVCBs(struct rx_connection **rxconns, int nconns, int nservers,
+            struct afs_conn **conns, struct srvAddr **addrs)
+{
+    afs_int32 *results;
+    afs_int32 i;
+
+    results = afs_osi_Alloc(nservers * sizeof (afs_int32));
+    osi_Assert(results != NULL);
+
+    AFS_GUNLOCK();
+    multi_Rx(rxconns,nconns)
+    {
+        multi_RXAFS_GiveUpAllCallBacks();
+        results[multi_i] = multi_error;
+    } multi_End;
+    AFS_GLOCK();
+
+    /*
+     * Freeing the CBR will unlink it from the server's CBR list
+     * do it here, not in the loop, because a dynamic CBR will call
+     * into the memory management routines.
+     */
+    for ( i = 0 ; i < nconns ; i++ ) {
+       if (results[i] == 0) {
+           /* Unchain all of them */
+           while (addrs[i]->server->cbrs)
+               afs_FreeCBR(addrs[i]->server->cbrs);
+       }
+    }
+    afs_osi_Free(results, nservers * sizeof(afs_int32));
+}
+
 /*!
  *   Flush all queued callbacks to all servers.
  *
@@ -384,6 +417,10 @@ afs_FlushVCBs(afs_int32 lockit)
     struct afs_conn *tc;
     int safety1, safety2, safety3;
     XSTATS_DECLS;
+
+    if (AFS_IS_DISCONNECTED)
+       return ENETDOWN;
+
     if ((code = afs_InitReq(&treq, afs_osi_credp)))
        return code;
     treq.flags |= O_NONBLOCK;
@@ -392,6 +429,15 @@ afs_FlushVCBs(afs_int32 lockit)
 
     if (lockit)
        ObtainWriteLock(&afs_xvcb, 273);
+    /*
+     * Shutting down.
+     * First, attempt a multi across everything, all addresses
+     * for all servers we know of.
+     */
+
+    if (lockit == 2)
+       afs_LoopServers(2, NULL, 0, FlushAllVCBs, NULL);
+
     ObtainReadLock(&afs_xserver);
     for (i = 0; i < NSERVERS; i++) {
        for (safety1 = 0, tsp = afs_servers[i];
@@ -652,7 +698,7 @@ afs_ShakeLooseVCaches(afs_int32 anumber)
     afs_int32 i, loop;
     struct vcache *tvc;
     struct afs_q *tq, *uq;
-    int fv_slept;
+    int fv_slept, defersleep = 0;
     afs_int32 target = anumber;
 
     i = 0;
@@ -672,7 +718,7 @@ afs_ShakeLooseVCaches(afs_int32 anumber)
        }
 
        fv_slept = 0;
-       if (osi_TryEvictVCache(tvc, &fv_slept))
+       if (osi_TryEvictVCache(tvc, &fv_slept, defersleep))
            anumber--;
 
        if (fv_slept) {
@@ -682,8 +728,14 @@ afs_ShakeLooseVCaches(afs_int32 anumber)
            i = 0;
            continue;   /* start over - may have raced. */
        }
-       if (tq == uq)
+       if (tq == uq) {
+           if (anumber && !defersleep) {
+               defersleep = 1;
+               tq = VLRU.prev;
+               continue;
+           }
            break;
+       }
     }
     if (!afsd_dynamic_vcaches && anumber == target) {
        afs_warn("afs_ShakeLooseVCaches: warning none freed, using %d of %d\n",
@@ -798,7 +850,7 @@ afs_NewVCache_int(struct VenusFid *afid, struct server *serverp, int seq)
     afs_FlushReclaimedVcaches();
 
 #if defined(AFS_LINUX22_ENV)
-    if(!afsd_dynamic_vcaches) {
+    if(!afsd_dynamic_vcaches && afs_vcount >= afs_maxvcount) {
        afs_ShakeLooseVCaches(anumber);
        if (afs_vcount >= afs_maxvcount) {
            afs_warn("afs_NewVCache - none freed\n");
@@ -1646,7 +1698,9 @@ afs_GetVCache(struct VenusFid *afid, struct vrequest *areq,
        iheldthelock = VOP_ISLOCKED(vp, curthread);
        if (!iheldthelock)
            vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+       AFS_GUNLOCK();
        vinvalbuf(vp, V_SAVE, curthread, PINOD, 0);
+       AFS_GLOCK();
        if (!iheldthelock)
            VOP_UNLOCK(vp, LK_EXCLUSIVE, curthread);
 #elif defined(AFS_FBSD_ENV)
@@ -2593,6 +2647,7 @@ afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag)
     struct vcache *tvc;
     afs_int32 i;
 #ifdef AFS_DARWIN80_ENV
+    struct vcache *deadvc = NULL, *livevc = NULL;
     vnode_t tvp;
 #endif
 
@@ -2602,47 +2657,78 @@ afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag)
     i = VCHash(afid);
     for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
        if (FidMatches(afid, tvc)) {
+#ifdef  AFS_DARWIN80_ENV
+           if (flag & FIND_CDEAD) {
+               if (tvc->f.states & (CDeadVnode|CBulkFetching)) {
+                   deadvc = tvc;
+                   continue;
+               }
+           } else {
+               if (tvc->f.states & CDeadVnode)
+                   if ((tvc->f.states & CBulkFetching) &&
+                       !(flag & FIND_BULKDEAD))
+                       continue;
+           }
+#endif
             if (tvc->f.states & CVInit) {
                findvc_sleep(tvc, flag);
                goto findloop;
-            }
-#ifdef  AFS_DARWIN80_ENV
-           if (tvc->f.states & CDeadVnode) {
-               if (!(flag & FIND_CDEAD)) {
-                   findvc_sleep(tvc, flag);
-                   goto findloop;
-               }
            }
-           tvp = AFSTOV(tvc);
-           if (vnode_get(tvp))
-               continue;
-           if (vnode_ref(tvp)) {
-               AFS_GUNLOCK();
-               /* AFSTOV(tvc) may be NULL */
-               vnode_put(tvp);
-               AFS_GLOCK();
+#ifdef  AFS_DARWIN80_ENV
+            if (tvc->f.states & CDeadVnode) {
+               findvc_sleep(tvc, flag);
+               goto findloop;
+            }
+           if (flag & FIND_CDEAD) {
+               livevc = tvc;
                continue;
            }
-           if (tvc->f.states & (CBulkFetching|CDeadVnode)) {
-               AFS_GUNLOCK();
-               vnode_recycle(AFSTOV(tvc));
-               AFS_GLOCK();
-           }
 #endif
            break;
        }
     }
+#ifdef  AFS_DARWIN80_ENV
+       if (flag & FIND_CDEAD) {
+           if (livevc && deadvc) {
+               /* discard deadvc */
+               AFS_GUNLOCK();
+               vnode_recycle(AFSTOV(deadvc));
+               vnode_put(AFSTOV(deadvc));
+               vnode_rele(AFSTOV(deadvc));
+               AFS_GLOCK();
+               deadvc = NULL;
+           }
+
+           /* return what's left */
+           tvc = livevc ? livevc : deadvc;
+       }
+#endif
 
     /* should I have a read lock on the vnode here? */
     if (tvc) {
        if (retry)
            *retry = 0;
-#if !defined(AFS_DARWIN80_ENV)
-       osi_vnhold(tvc, retry); /* already held, above */
-       if (retry && *retry)
-           return 0;
-#endif
-#if defined(AFS_DARWIN_ENV) && !defined(AFS_DARWIN80_ENV)
+#if defined(AFS_DARWIN80_ENV)
+       tvp = AFSTOV(tvc);
+       if (vnode_get(tvp))
+           tvp = NULL;
+       if (tvp && vnode_ref(tvp)) {
+           AFS_GUNLOCK();
+           /* AFSTOV(tvc) may be NULL */
+           vnode_put(tvp);
+           AFS_GLOCK();
+           tvp = NULL;
+       }
+       if (tvp && (tvc->f.states & (CBulkFetching|CDeadVnode))) {
+           AFS_GUNLOCK();
+           vnode_recycle(AFSTOV(tvc));
+           AFS_GLOCK();
+       }
+       if (!tvp) {
+           tvc = NULL;
+           return tvc;
+       }
+#elif defined(AFS_DARWIN_ENV)
        tvc->f.states |= CUBCinit;
        AFS_GUNLOCK();
        if (UBCINFOMISSING(AFSTOV(tvc)) ||
@@ -2651,6 +2737,10 @@ afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag)
        }
        AFS_GLOCK();
        tvc->f.states &= ~CUBCinit;
+#else
+       osi_vnhold(tvc, retry); /* already held, above */
+       if (retry && *retry)
+           return 0;
 #endif
        /*
         * only move to front of vlru if we have proper vcache locking)
@@ -2790,6 +2880,7 @@ afs_NFSFindVCache(struct vcache **avcp, struct VenusFid *afid)
     tvc = found_tvc;
     /* should I have a read lock on the vnode here? */
     if (tvc) {
+#ifndef AFS_DARWIN80_ENV
 #if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
        afs_int32 retry = 0;
        osi_vnhold(tvc, &retry);
@@ -2803,6 +2894,7 @@ afs_NFSFindVCache(struct vcache **avcp, struct VenusFid *afid)
 #else
        osi_vnhold(tvc, (int *)0);      /* already held, above */
 #endif
+#endif
        /*
         * We obtained the xvcache lock above.
         */
@@ -3036,7 +3128,7 @@ afs_DisconGiveUpCallbacks(void)
 
     ReleaseWriteLock(&afs_xvcache);
 
-    afs_FlushVCBs(1);
+    afs_FlushVCBs(2);
 }
 
 /*!