]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
afs: Create afs_StaleVCache
authorAndrew Deason <adeason@sinenomine.net>
Thu, 15 May 2014 00:56:58 +0000 (19:56 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Thu, 15 Sep 2016 01:01:43 +0000 (21:01 -0400)
In numerous different places in the code, we do something like this to
mark a vcache as stale:

  ObtainWriteLock(&afs_xcbhash, somenumber);
  avc->f.states &= ~CStatd;
  afs_DequeueCallback(avc);
  ReleaseWriteLock(&afs_xcbhash);
  if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
      osi_dnlc_purgedp(avc);

There are some variations here and there, but all locations usually
involve at least some code like that. But they all do the same general
thing: invalidate a vcache so we hit the net the next time we need
that vcache.

In order to make it easier to modify what happens when we invalidate a
vcache, and just to improve the code, take all of these instances and
put the functionality in a single function, called afs_StaleVCache,
which marks the vcache as 'stale'.

To handle a few different situations that must be handled, we have
some flags that can also be passed to the new function. These are
primarily necessary to handle variations in the circumstances under
which we hit this code path; for instance, we may already have
afs_xcbhash locked, or we may be invalidating the entire osidnlc (if
we're invalidating vcaches in bulk, for example).

This should result in the same general behavior in all cases. The only
slight differences in a few cases is that we hold locks for a few more
operations than we used to; for example, we may clear an osidnlc entry
while holding the vcache lock. But these are minor and shouldn't
result in any actual differences in behavior.

So, this commit should just be code reorganization and should incur no
behavior change. However, this reorganization is complex, and should
not be considered a simple risk-free refactoring.

[kaduk@mit.edu: implement Tom Keiser's suggestion of a third argument
to afs_StaleVCacheFlags, add AFS_STALEVC_CLEARCB and
AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED]

Change-Id: I2b2f606c56d5b22826eeb98471187165260c7b91
Reviewed-on: https://gerrit.openafs.org/11790
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
19 files changed:
src/afs/VNOPS/afs_vnop_attrs.c
src/afs/VNOPS/afs_vnop_create.c
src/afs/VNOPS/afs_vnop_dirops.c
src/afs/VNOPS/afs_vnop_link.c
src/afs/VNOPS/afs_vnop_lookup.c
src/afs/VNOPS/afs_vnop_remove.c
src/afs/VNOPS/afs_vnop_rename.c
src/afs/VNOPS/afs_vnop_symlink.c
src/afs/afs_analyze.c
src/afs/afs_bypasscache.c
src/afs/afs_callback.c
src/afs/afs_cbqueue.c
src/afs/afs_dcache.c
src/afs/afs_dynroot.c
src/afs/afs_pioctl.c
src/afs/afs_prototypes.h
src/afs/afs_segments.c
src/afs/afs_vcache.c
src/afs/afs_volume.c

index 3b065fd35241059819c07968fff225d530bcaac0..26062d1b9161210df810c9b8d6a00765b533722f 100644 (file)
@@ -611,13 +611,8 @@ afs_setattr(OSI_VC_DECL(avc), struct vattr *attrs,
            ReleaseSharedLock(&avc->lock);      /* release lock */
         }
         if (code) {
-           ObtainWriteLock(&afs_xcbhash, 487);
-           afs_DequeueCallback(avc);
-           avc->f.states &= ~CStatd;
-           ReleaseWriteLock(&afs_xcbhash);
-           if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-               osi_dnlc_purgedp(avc);
            /* error?  erase any changes we made to vcache entry */
+           afs_StaleVCache(avc);
         }
     } else {
        ObtainSharedLock(&avc->lock, 712);
index a2d600d68f64055b0fd9039478d1b049b3a4af9a..2fb580cc300c8fe828d71445fa65a0083c32ce54 100644 (file)
@@ -356,11 +356,7 @@ afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
 
        if (code) {
            if (code < 0) {
-               ObtainWriteLock(&afs_xcbhash, 488);
-               afs_DequeueCallback(adp);
-               adp->f.states &= ~CStatd;
-               ReleaseWriteLock(&afs_xcbhash);
-               osi_dnlc_purgedp(adp);
+               afs_StaleVCache(adp);
            }
            ReleaseWriteLock(&adp->lock);
            if (tdc) {
@@ -451,11 +447,9 @@ afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
                    afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), volp);
                }
            } else {
-               afs_DequeueCallback(tvc);
-               tvc->f.states &= ~(CStatd | CUnique);
-               tvc->callback = 0;
-               if (tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
-                   osi_dnlc_purgedp(tvc);
+               afs_StaleVCacheFlags(tvc,
+                                    AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+                                    CUnique);
            }
            ReleaseWriteLock(&afs_xcbhash);
            if (AFS_IS_DISCON_RW) {
index d1d2ab2ef04d7fb944ea86611750f45654d5a3f8..596651324dea55a0c131781d7924f21fcc7d8c0a 100644 (file)
@@ -135,11 +135,7 @@ afs_mkdir(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
 
        if (code) {
            if (code < 0) {
-               ObtainWriteLock(&afs_xcbhash, 490);
-               afs_DequeueCallback(adp);
-               adp->f.states &= ~CStatd;
-               ReleaseWriteLock(&afs_xcbhash);
-               osi_dnlc_purgedp(adp);
+               afs_StaleVCache(adp);
            }
            ReleaseWriteLock(&adp->lock);
            if (tdc)
@@ -370,11 +366,7 @@ afs_rmdir(OSI_VC_DECL(adp), char *aname, afs_ucred_t *acred)
            }
 
            if (code < 0) {
-               ObtainWriteLock(&afs_xcbhash, 491);
-               afs_DequeueCallback(adp);
-               adp->f.states &= ~CStatd;
-               ReleaseWriteLock(&afs_xcbhash);
-               osi_dnlc_purgedp(adp);
+               afs_StaleVCache(adp);
            }
            ReleaseWriteLock(&adp->lock);
            goto done;
index 2a8844348b1315fd826a2b55d90bb35249cdabda..f57b7ad492e65ecc9d51590d23ebe44deb3accd8 100644 (file)
@@ -123,11 +123,7 @@ afs_link(struct vcache *avc, OSI_VC_DECL(adp), char *aname,
        if (tdc)
            afs_PutDCache(tdc);
        if (code < 0) {
-           ObtainWriteLock(&afs_xcbhash, 492);
-           afs_DequeueCallback(adp);
-           adp->f.states &= ~CStatd;
-           ReleaseWriteLock(&afs_xcbhash);
-           osi_dnlc_purgedp(adp);
+           afs_StaleVCache(adp);
        }
        ReleaseWriteLock(&adp->lock);
        goto done;
@@ -158,12 +154,7 @@ afs_link(struct vcache *avc, OSI_VC_DECL(adp), char *aname,
      * returned in ustat is the most recent to store in the file's
      * cache entry */
 
-    ObtainWriteLock(&afs_xcbhash, 493);
-    afs_DequeueCallback(avc);
-    avc->f.states &= ~CStatd;  /* don't really know new link count */
-    ReleaseWriteLock(&afs_xcbhash);
-    if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-       osi_dnlc_purgedp(avc);
+    afs_StaleVCache(avc); /* don't really know new link count */
     ReleaseWriteLock(&avc->lock);
     code = 0;
   done:
index ff641e0e9d4a618f7988fb70c726e5bb41f3595d..c3c3963b664a4813fb333047cf3b4c29b3fdd911 100644 (file)
@@ -1266,11 +1266,9 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
            tvcp->f.states |= CStatd;
            afs_QueueCallback(tvcp, CBHash(3600), volp);
        } else {
-           tvcp->callback = 0;
-           tvcp->f.states &= ~(CStatd | CUnique);
-           afs_DequeueCallback(tvcp);
-           if ((tvcp->f.states & CForeign) || (vType(tvcp) == VDIR))
-               osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */
+           afs_StaleVCacheFlags(tvcp,
+                                AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+                                CUnique);
        }
 #ifdef AFS_DARWIN80_ENV
        /* reclaim->FlushVCache will need xcbhash */
@@ -1280,11 +1278,9 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
            code = afs_darwin_finalizevnode(tvcp, NULL, NULL, 0, 1);
            if (code) {
                /* It's gonna get recycled - shouldn't happen */
-               tvcp->callback = 0;
-               tvcp->f.states &= ~(CStatd | CUnique);
-               afs_DequeueCallback(tvcp);
-               if ((tvcp->f.states & CForeign) || (vType(tvcp) == VDIR))
-                   osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */
+               afs_StaleVCacheFlags(tvcp,
+                                    AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+                                    CUnique);
            } else
                /* re-acquire the usecount that finalizevnode disposed of */
                vnode_ref(AFSTOV(tvcp));
@@ -1890,12 +1886,8 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
                if (tv) {
                    if (tv->states & VRO) {
                        pass = 1;       /* try this *once* */
-                       ObtainWriteLock(&afs_xcbhash, 495);
-                       afs_DequeueCallback(adp);
-                       /* re-stat to get later version */
-                       adp->f.states &= ~CStatd;
-                       ReleaseWriteLock(&afs_xcbhash);
-                       osi_dnlc_purgedp(adp);
+                       /* re-stat to get later version */
+                       afs_StaleVCache(adp);
                        afs_PutVolume(tv, READ_LOCK);
                        goto redo;
                    }
index c19c2a5e6535305650aa33567499c55bf7595bd8..f1e1fafae6f14c08b312c6a11c5cb1b11cd9fe97 100644 (file)
@@ -93,11 +93,7 @@ afsremove(struct vcache *adp, struct dcache *tdc,
            afs_PutVCache(tvc);
 
        if (code < 0) {
-           ObtainWriteLock(&afs_xcbhash, 497);
-           afs_DequeueCallback(adp);
-           adp->f.states &= ~CStatd;
-           ReleaseWriteLock(&afs_xcbhash);
-           osi_dnlc_purgedp(adp);
+           afs_StaleVCache(adp);
        }
        ReleaseWriteLock(&adp->lock);
        code = afs_CheckCode(code, treqp, 21);
index 7791784a08a1ce52b711ac922a451389fce30c5f..2d4b9c185b0cd894e337a8c33072dbf449f4bbe5 100644 (file)
@@ -320,13 +320,9 @@ afsrename(struct vcache *aodp, char *aname1, struct vcache *andp,
            /* if failed, server might have done something anyway, and 
             * assume that we know about it */
            ObtainWriteLock(&afs_xcbhash, 498);
-           afs_DequeueCallback(aodp);
-           afs_DequeueCallback(andp);
-           andp->f.states &= ~CStatd;
-           aodp->f.states &= ~CStatd;
+           afs_StaleVCacheFlags(aodp, AFS_STALEVC_CBLOCKED, 0);
+           afs_StaleVCacheFlags(andp, AFS_STALEVC_CBLOCKED, 0);
            ReleaseWriteLock(&afs_xcbhash);
-           osi_dnlc_purgedp(andp);
-           osi_dnlc_purgedp(aodp);
        }
     }
 
index f608b2be70eab5934422ae2ba423f7ea072f1ee1..1dd461125727948cc8ed35e7d300b0a7edb1c0b4 100644 (file)
@@ -200,11 +200,7 @@ afs_symlink(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
     ObtainWriteLock(&afs_xvcache, 40);
     if (code) {
        if (code < 0) {
-           ObtainWriteLock(&afs_xcbhash, 499);
-           afs_DequeueCallback(adp);
-           adp->f.states &= ~CStatd;
-           ReleaseWriteLock(&afs_xcbhash);
-           osi_dnlc_purgedp(adp);
+           afs_StaleVCache(adp);
        }
        ReleaseWriteLock(&adp->lock);
        ReleaseWriteLock(&afs_xvcache);
index c0233ef99cb4b2af5f1e8cfc961c20611453bf2c..4bb212ba66d1d78bb68d341d774de57b7b4e0e60 100644 (file)
@@ -317,7 +317,8 @@ afs_ClearStatus(struct VenusFid *afid, int op, struct volume *avp)
        ObtainReadLock(&afs_xvcache);
        if ((tvc = afs_FindVCache(afid, 0, 0))) {
            ReleaseReadLock(&afs_xvcache);
-           tvc->f.states &= ~(CStatd | CUnique);
+           afs_StaleVCacheFlags(tvc, AFS_STALEVC_NOCB | AFS_STALEVC_NODNLC,
+                                CUnique);
            afs_PutVCache(tvc);
        } else {
            ReleaseReadLock(&afs_xvcache);
index 4c6fb9a3ac781cdf689b7ecd90fd31decf086e09..76973d9c71d59b07ef670041f1e8b7430e35da30 100644 (file)
@@ -166,16 +166,11 @@ afs_TransitionToBypass(struct vcache *avc,
        }
     }
 
-#if 0
     /* also cg2v, don't dequeue the callback */
-    ObtainWriteLock(&afs_xcbhash, 956);
-    afs_DequeueCallback(avc);
-    ReleaseWriteLock(&afs_xcbhash);
-#endif
-    avc->f.states &= ~(CStatd | CDirty);      /* next reference will re-stat */
+    /* next reference will re-stat */
+    afs_StaleVCacheFlags(avc, AFS_STALEVC_NOCB, CDirty);
     /* now find the disk cache entries */
     afs_TryToSmush(avc, acred, 1);
-    osi_dnlc_purgedp(avc);
     if (avc->linkData && !(avc->f.states & CCore)) {
        afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
        avc->linkData = NULL;
@@ -226,13 +221,11 @@ afs_TransitionToCaching(struct vcache *avc,
        goto done;
 
     /* Ok, we actually do need to flush */
-    ObtainWriteLock(&afs_xcbhash, 957);
-    afs_DequeueCallback(avc);
-    avc->f.states &= ~(CStatd | CDirty);       /* next reference will re-stat cache entry */
-    ReleaseWriteLock(&afs_xcbhash);
+    /* next reference will re-stat cache entry */
+    afs_StaleVCacheFlags(avc, 0, CDirty);
+
     /* now find the disk cache entries */
     afs_TryToSmush(avc, acred, 1);
-    osi_dnlc_purgedp(avc);
     if (avc->linkData && !(avc->f.states & CCore)) {
        afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
        avc->linkData = NULL;
index c90f82f69233065856d188f038a30caf99b77260..61b2a75b7a20b3af63e2152cf58849872eaac41d 100644 (file)
@@ -473,17 +473,12 @@ loop1:
 #endif
 #endif
                        ReleaseReadLock(&afs_xvcache);
-                       ObtainWriteLock(&afs_xcbhash, 449);
-                       afs_DequeueCallback(tvc);
-                       tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
+                       afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
                        afs_allCBs++;
                        if (tvc->f.fid.Fid.Vnode & 1)
                            afs_oddCBs++;
                        else
                            afs_evenCBs++;
-                       ReleaseWriteLock(&afs_xcbhash);
-                       if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
-                           osi_dnlc_purgedp(tvc);
                        afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
                                   ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
                                   tvc->f.states, ICL_TYPE_INT32,
@@ -561,12 +556,7 @@ loop2:
 #endif
 #endif
                    ReleaseReadLock(&afs_xvcache);
-                   ObtainWriteLock(&afs_xcbhash, 450);
-                   afs_DequeueCallback(tvc);
-                   tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
-                   ReleaseWriteLock(&afs_xcbhash);
-                   if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
-                       osi_dnlc_purgedp(tvc);
+                   afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
                    afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
                               ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
                               tvc->f.states, ICL_TYPE_LONG, 0);
@@ -745,11 +735,9 @@ SRXAFSCB_InitCallBackState(struct rx_call *a_call)
            for (i = 0; i < VCSIZE; i++)
                for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
                    if (tvc->callback == ts) {
-                       ObtainWriteLock(&afs_xcbhash, 451);
-                       afs_DequeueCallback(tvc);
-                       tvc->callback = NULL;
-                       tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
-                       ReleaseWriteLock(&afs_xcbhash);
+                       afs_StaleVCacheFlags(tvc, AFS_STALEVC_NODNLC |
+                                                 AFS_STALEVC_CLEARCB,
+                                            CUnique | CBulkFetching);
                    }
                }
 
index 2f5225028f155af316e7ddbf86b28ebb744b3d75..85b3247b74efa44604e7e72c5d35f28a69b8f352 100644 (file)
@@ -216,12 +216,9 @@ afs_CheckCallbacks(unsigned int secs)
                        if (!(tvp->serverHost[i]->flags & SRVR_ISDOWN)) {
                            /* What about locking xvcache or vrefcount++ or
                             * write locking tvc? */
-                           QRemove(tq);
-                           tvc->f.states &= ~(CStatd | CMValid | CUnique);
-                            if (!(tvc->f.states & (CVInit|CVFlushed)) &&
-                                (tvc->f.fid.Fid.Vnode & 1 ||
-                                 (vType(tvc) == VDIR)))
-                               osi_dnlc_purgedp(tvc);
+                           afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED |
+                               AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED,
+                               CMValid | CUnique);
                            tvc->dchint = NULL; /*invalidate em */
                            afs_ResetVolumeInfo(tvp);
                            break;
@@ -233,11 +230,9 @@ afs_CheckCallbacks(unsigned int secs)
                /* Do I need to worry about things like execsorwriters?
                 * What about locking xvcache or vrefcount++ or write locking tvc?
                 */
-               QRemove(tq);
-               tvc->f.states &= ~(CStatd | CMValid | CUnique);
-                if (!(tvc->f.states & (CVInit|CVFlushed)) &&
-                    (tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
-                   osi_dnlc_purgedp(tvc);
+               afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED |
+                                    AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED,
+                                    CMValid | CUnique);
            }
        }
 
@@ -303,14 +298,10 @@ afs_FlushCBs(void)
 
     for (i = 0; i < VCSIZE; i++)       /* reset all the vnodes */
        for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
-           tvc->callback = 0;
+           afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED |
+                                AFS_STALEVC_CLEARCB |
+                                AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED, 0);
            tvc->dchint = NULL; /* invalidate hints */
-           tvc->f.states &= ~(CStatd);
-           if (QPrev(&(tvc->callsort)))
-               QRemove(&(tvc->callsort));
-           if (!(tvc->f.states & (CVInit|CVFlushed)) &&
-                ((tvc->f.fid.Fid.Vnode & 1) || (vType(tvc) == VDIR)))
-               osi_dnlc_purgedp(tvc);
        }
 
     afs_InitCBQueue(0);
@@ -334,14 +325,10 @@ afs_FlushServerCBs(struct server *srvp)
     for (i = 0; i < VCSIZE; i++) {     /* reset all the vnodes */
        for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
            if (tvc->callback == srvp) {
-               tvc->callback = 0;
+               afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED |
+                                    AFS_STALEVC_CLEARCB |
+                                    AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED, 0);
                tvc->dchint = NULL;     /* invalidate hints */
-               tvc->f.states &= ~(CStatd);
-               if (!(tvc->f.states & (CVInit|CVFlushed)) &&
-                    ((tvc->f.fid.Fid.Vnode & 1) || (vType(tvc) == VDIR))) {
-                   osi_dnlc_purgedp(tvc);
-               }
-               afs_DequeueCallback(tvc);
            }
        }
     }
index dc14762b4f7917efaec5984a9d2681bd8cb3a6ad..60d2a3106ea2b01d48e8c19bbd46815bce2800c3 100644 (file)
@@ -2423,13 +2423,7 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
                    afs_CFileTruncate(file, size);      /* prune it */
                } else {
                    if (!setLocks || slowPass) {
-                       ObtainWriteLock(&afs_xcbhash, 453);
-                       afs_DequeueCallback(avc);
-                       avc->f.states &= ~(CStatd | CUnique);
-                       avc->callback = NULL;
-                       ReleaseWriteLock(&afs_xcbhash);
-                       if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-                           osi_dnlc_purgedp(avc);
+                       afs_StaleVCacheFlags(avc, AFS_STALEVC_CLEARCB, CUnique);
                    } else {
                        /* Something lost.  Forget about performance, and go
                         * back with a vcache write lock.
@@ -2504,12 +2498,7 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
            ReleaseWriteLock(&tdc->lock);
            afs_PutDCache(tdc);
            if (!afs_IsDynroot(avc)) {
-               ObtainWriteLock(&afs_xcbhash, 454);
-               afs_DequeueCallback(avc);
-               avc->f.states &= ~(CStatd | CUnique);
-               ReleaseWriteLock(&afs_xcbhash);
-               if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-                   osi_dnlc_purgedp(avc);
+               afs_StaleVCacheFlags(avc, 0, CUnique);
                /*
                 * Locks held:
                 * avc->lock(W); assert(!setLocks || slowPass)
index 83dc1aab0418aadaa80db62e6a7b27f056a188ce..a18602f8156812e0065c923fdb54ef08bbb97248 100644 (file)
@@ -306,8 +306,7 @@ afs_DynrootInvalidate(void)
        ReleaseReadLock(&afs_xvcache);
     } while (retry);
     if (tvc) {
-       tvc->f.states &= ~(CStatd | CUnique);
-       osi_dnlc_purgedp(tvc);
+       afs_StaleVCacheFlags(tvc, AFS_STALEVC_NOCB, CUnique);
        afs_PutVCache(tvc);
     }
 }
index bc6b3e6261018323578a7659ea67ad0f8e304174..6d5b7ccec42a0c045be1bc44012ec7971d2174e1 100644 (file)
@@ -1478,15 +1478,10 @@ DECL_PIOCTL(PSetAcl)
              SHARED_LOCK, NULL));
 
     /* now we've forgotten all of the access info */
-    ObtainWriteLock(&afs_xcbhash, 455);
-    avc->callback = 0;
-    afs_DequeueCallback(avc);
-    avc->f.states &= ~(CStatd | CUnique);
-    ReleaseWriteLock(&afs_xcbhash);
-    if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-       osi_dnlc_purgedp(avc);
+    afs_StaleVCacheFlags(avc, AFS_STALEVC_CLEARCB, CUnique);
 
     /* SXW - Should we flush metadata here? */
+
     return code;
 }
 
@@ -3022,13 +3017,7 @@ DECL_PIOCTL(PRemoveCallBack)
                 (tc, rxconn, code, &avc->f.fid, areq,
                  AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS, SHARED_LOCK, NULL));
 
-       ObtainWriteLock(&afs_xcbhash, 457);
-       afs_DequeueCallback(avc);
-       avc->callback = 0;
-       avc->f.states &= ~(CStatd | CUnique);
-       ReleaseWriteLock(&afs_xcbhash);
-       if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-           osi_dnlc_purgedp(avc);
+       afs_StaleVCacheFlags(avc, AFS_STALEVC_CLEARCB, CUnique);
     }
     ReleaseWriteLock(&avc->lock);
     return 0;
@@ -4859,13 +4848,10 @@ DECL_PIOCTL(PFlushMount)
        goto out;
     }
     ObtainWriteLock(&tvc->lock, 649);
-    ObtainWriteLock(&afs_xcbhash, 650);
-    afs_DequeueCallback(tvc);
-    tvc->f.states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
-    ReleaseWriteLock(&afs_xcbhash);
+    /* next reference will re-stat cache entry */
+    afs_StaleVCacheFlags(tvc, 0, CDirty);
     /* now find the disk cache entries */
     afs_TryToSmush(tvc, *acred, 1);
-    osi_dnlc_purgedp(tvc);
     if (tvc->linkData && !(tvc->f.states & CCore)) {
        afs_osi_Free(tvc->linkData, strlen(tvc->linkData) + 1);
        tvc->linkData = NULL;
index 945954e77bc46f8c25fd85d2e0ff73d2af00e0b4..d6b7cf64a798e9dd0514fec92c7e9c21017f56eb 100644 (file)
@@ -1109,6 +1109,38 @@ extern struct vcache *afs_GetVCache(struct VenusFid *afid,
                                    struct vcache *avc);
 extern void afs_PutVCache(struct vcache *avc);
 extern int afs_RefVCache(struct vcache *avc);
+
+/* Flags for afs_StaleVCacheFlags */
+
+/* afs_xcbhash is already locked by the caller */
+#define AFS_STALEVC_CBLOCKED (0x01)
+
+/* Normally we assume we only need to invalidate cached
+ * name -> vcache mappings for entries where the given
+ * vcache is the parent dir. This flag says to also clear
+ * entries for the vcache itself. */
+#define AFS_STALEVC_FILENAME (0x02)
+
+/* Do not touch the DNLC; the caller will deal with it. */
+#define AFS_STALEVC_NODNLC   (0x04)
+
+/* Do not run afs_DequeueCallback; the caller will take
+ * care of callback management. */
+#define AFS_STALEVC_NOCB     (0x08)
+
+/* NULL-out the callback field of the vcache, to save code at the callsite. */
+#define AFS_STALEVC_CLEARCB    (0x10)
+
+/* Skip the DNLC purge if CVInit or CVFlushed is set, for efficiency.
+ * A transitional flag used to reduce the logic change during refactoring
+ * that is expected to be removed and the purge behavior standardized. */
+#define AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED (0x20)
+typedef unsigned int afs_stalevc_flags_t;
+
+#define afs_StaleVCache(avc) afs_StaleVCacheFlags(avc, 0, 0)
+extern void afs_StaleVCacheFlags(struct vcache *avc, afs_stalevc_flags_t flags,
+                                afs_uint32 cflags);
+
 extern void afs_ProcessFS(struct vcache *avc,
                          struct AFSFetchStatus *astat,
                          struct vrequest *areq);
index 69f7445f9edcf76e16412792c3ddf02cb15e8bc1..9992a84a5f756f38e4d40310fa56f808b2deaf12 100644 (file)
@@ -526,12 +526,7 @@ afs_InvalidateAllSegments(struct vcache *avc)
     hash = DVHash(&avc->f.fid);
     avc->f.truncPos = AFS_NOTRUNC;     /* don't truncate later */
     avc->f.states &= ~CExtendedFile;   /* not any more */
-    ObtainWriteLock(&afs_xcbhash, 459);
-    afs_DequeueCallback(avc);
-    avc->f.states &= ~(CStatd | CDirty);       /* mark status information as bad, too */
-    ReleaseWriteLock(&afs_xcbhash);
-    if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-       osi_dnlc_purgedp(avc);
+    afs_StaleVCacheFlags(avc, 0, CDirty);
     /* Blow away pages; for now, only for Solaris */
 #if    (defined(AFS_SUN5_ENV))
     if (WriteLocked(&avc->lock))
index 14032541e8a9c4c0dd9ecc2ecadf6a8e909c588b..18fb79ae7e2be1eb590a142234ddf7957eb25a31 100644 (file)
@@ -248,14 +248,7 @@ afs_FlushVCache(struct vcache *avc, int *slept)
     vn_reinit(AFSTOV(avc));
 #endif
     afs_FreeAllAxs(&(avc->Access));
-    ObtainWriteLock(&afs_xcbhash, 460);
-    afs_DequeueCallback(avc);  /* remove it from queued callbacks list */
-    avc->f.states &= ~(CStatd | CUnique);
-    ReleaseWriteLock(&afs_xcbhash);
-    if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
-       osi_dnlc_purgedp(avc);  /* if it (could be) a directory */
-    else
-       osi_dnlc_purgevp(avc);
+    afs_StaleVCacheFlags(avc, AFS_STALEVC_FILENAME, CUnique);
 
     /* By this point, the vcache has been removed from all global structures
      * via which someone could try to use the vcache. It is okay to drop
@@ -1240,22 +1233,10 @@ afs_VerifyVCache2(struct vcache *avc, struct vrequest *areq)
        ReleaseWriteLock(&avc->lock);
        return 0;
     }
-    ObtainWriteLock(&afs_xcbhash, 461);
-    avc->f.states &= ~(CStatd | CUnique);
-    avc->callback = NULL;
-    afs_DequeueCallback(avc);
-    ReleaseWriteLock(&afs_xcbhash);
+    afs_StaleVCacheFlags(avc, AFS_STALEVC_FILENAME | AFS_STALEVC_CLEARCB,
+                        CUnique);
     ReleaseWriteLock(&avc->lock);
 
-    /* since we've been called back, or the callback has expired,
-     * it's possible that the contents of this directory, or this
-     * file's name have changed, thus invalidating the dnlc contents.
-     */
-    if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
-       osi_dnlc_purgedp(avc);
-    else
-       osi_dnlc_purgevp(avc);
-
     /* fetch the status info */
     tvc = afs_GetVCache(&avc->f.fid, areq, NULL, avc);
     if (!tvc)
@@ -1411,12 +1392,7 @@ afs_WriteVCache(struct vcache *avc,
        avc->f.m.Date = OutStatus.ClientModTime;
     } else {
        /* failure, set up to check with server next time */
-       ObtainWriteLock(&afs_xcbhash, 462);
-       afs_DequeueCallback(avc);
-       avc->f.states &= ~(CStatd | CUnique);   /* turn off stat valid flag */
-       ReleaseWriteLock(&afs_xcbhash);
-       if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
-           osi_dnlc_purgedp(avc);      /* if it (could be) a directory */
+       afs_StaleVCacheFlags(avc, 0, CUnique);
     }
     ConvertWToSLock(&avc->lock);
     return code;
@@ -1829,11 +1805,8 @@ afs_GetVCache(struct VenusFid *afid, struct vrequest *areq,
 #endif
 #endif
 
-    ObtainWriteLock(&afs_xcbhash, 464);
-    tvc->f.states &= ~CUnique;
-    tvc->callback = 0;
-    afs_DequeueCallback(tvc);
-    ReleaseWriteLock(&afs_xcbhash);
+    afs_StaleVCacheFlags(tvc, AFS_STALEVC_NODNLC | AFS_STALEVC_CLEARCB,
+                        CUnique);
 
     /* It is always appropriate to throw away all the access rights? */
     afs_FreeAllAxs(&(tvc->Access));
@@ -2048,12 +2021,7 @@ afs_LookupVCache(struct VenusFid *afid, struct vrequest *areq,
     }
 
     if (code) {
-       ObtainWriteLock(&afs_xcbhash, 465);
-       afs_DequeueCallback(tvc);
-       tvc->f.states &= ~(CStatd | CUnique);
-       ReleaseWriteLock(&afs_xcbhash);
-       if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
-           osi_dnlc_purgedp(tvc);      /* if it (could be) a directory */
+       afs_StaleVCacheFlags(tvc, 0, CUnique);
        if (tvp)
            afs_PutVolume(tvp, READ_LOCK);
        ReleaseWriteLock(&tvc->lock);
@@ -2076,19 +2044,14 @@ afs_LookupVCache(struct VenusFid *afid, struct vrequest *areq,
            tvc->f.states &= ~CBulkFetching;
            afs_QueueCallback(tvc, CBHash(3600), tvp);
        } else {
-           tvc->callback = NULL;
-           afs_DequeueCallback(tvc);
-           tvc->f.states &= ~(CStatd | CUnique);
-           if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
-               osi_dnlc_purgedp(tvc);  /* if it (could be) a directory */
+           afs_StaleVCacheFlags(tvc,
+                                AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+                                CUnique);
        }
     } else {
-       afs_DequeueCallback(tvc);
-       tvc->f.states &= ~CStatd;
-       tvc->f.states &= ~CUnique;
-       tvc->callback = NULL;
-       if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
-           osi_dnlc_purgedp(tvc);      /* if it (could be) a directory */
+       afs_StaleVCacheFlags(tvc,
+                            AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+                            CUnique);
     }
     ReleaseWriteLock(&afs_xcbhash);
     if (tvp)
@@ -2286,13 +2249,7 @@ afs_GetRootVCache(struct VenusFid *afid, struct vrequest *areq,
     }
 
     if (code) {
-       ObtainWriteLock(&afs_xcbhash, 467);
-       afs_DequeueCallback(tvc);
-       tvc->callback = NULL;
-       tvc->f.states &= ~(CStatd | CUnique);
-       ReleaseWriteLock(&afs_xcbhash);
-       if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
-           osi_dnlc_purgedp(tvc);      /* if it (could be) a directory */
+       afs_StaleVCacheFlags(tvc, AFS_STALEVC_CLEARCB, CUnique);
        ReleaseWriteLock(&tvc->lock);
        afs_PutVCache(tvc);
        return NULL;
@@ -2315,11 +2272,8 @@ afs_GetRootVCache(struct VenusFid *afid, struct vrequest *areq,
            afs_QueueCallback(tvc, CBHash(3600), tvolp);
        }
     } else {
-       afs_DequeueCallback(tvc);
-       tvc->callback = NULL;
-       tvc->f.states &= ~(CStatd | CUnique);
-       if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
-           osi_dnlc_purgedp(tvc);      /* if it (could be) a directory */
+       afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+                            CUnique);
     }
     ReleaseWriteLock(&afs_xcbhash);
     afs_ProcessFS(tvc, &OutStatus, areq);
@@ -2369,18 +2323,13 @@ afs_UpdateStatus(struct vcache *avc, struct VenusFid *afid,
            avc->f.states &= ~CBulkFetching;
            afs_QueueCallback(avc, CBHash(3600), volp);
        } else {
-           afs_DequeueCallback(avc);
-           avc->callback = NULL;
-           avc->f.states &= ~(CStatd | CUnique);
-           if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
-               osi_dnlc_purgedp(avc);  /* if it (could be) a directory */
+           afs_StaleVCacheFlags(avc,
+                                AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+                                CUnique);
        }
     } else {
-       afs_DequeueCallback(avc);
-       avc->callback = NULL;
-       avc->f.states &= ~(CStatd | CUnique);
-       if ((avc->f.states & CForeign) || (avc->f.fid.Fid.Vnode & 1))
-           osi_dnlc_purgedp(avc);      /* if it (could be) a directory */
+       afs_StaleVCacheFlags(avc, AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+                            CUnique);
     }
     ReleaseWriteLock(&afs_xcbhash);
     if (volp)
@@ -2554,9 +2503,7 @@ afs_StuffVcache(struct VenusFid *afid,
     ReleaseSharedLock(&afs_xvcache);
     ObtainWriteLock(&tvc->lock, 58);
 
-    tvc->f.states &= ~CStatd;
-    if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
-       osi_dnlc_purgedp(tvc);  /* if it (could be) a directory */
+    afs_StaleVCacheFlags(tvc, AFS_STALEVC_NOCB, 0);
 
     /* Is it always appropriate to throw away all the access rights? */
     afs_FreeAllAxs(&(tvc->Access));
@@ -2608,11 +2555,8 @@ afs_StuffVcache(struct VenusFid *afid,
        tvc->f.states &= ~CBulkFetching;
        afs_QueueCallback(tvc, CBHash(3600), tvp);
     } else {
-       afs_DequeueCallback(tvc);
-       tvc->callback = NULL;
-       tvc->f.states &= ~(CStatd | CUnique);
-       if ((tvc->f.states & CForeign) || (tvc->f.fid.Fid.Vnode & 1))
-           osi_dnlc_purgedp(tvc);      /* if it (could be) a directory */
+       afs_StaleVCacheFlags(tvc, AFS_STALEVC_CBLOCKED | AFS_STALEVC_CLEARCB,
+                            CUnique);
     }
     ReleaseWriteLock(&afs_xcbhash);
     if (tvp)
@@ -2675,15 +2619,14 @@ afs_PutVCache(struct vcache *avc)
 void
 afs_ResetVCache(struct vcache *avc, afs_ucred_t *acred, afs_int32 skipdnlc)
 {
-    ObtainWriteLock(&afs_xcbhash, 456);
-    afs_DequeueCallback(avc);
-    avc->f.states &= ~(CStatd | CDirty);    /* next reference will re-stat */
-    ReleaseWriteLock(&afs_xcbhash);
+    afs_stalevc_flags_t flags = 0;
+    if (skipdnlc) {
+       flags |= AFS_STALEVC_NODNLC;
+    }
+
+    afs_StaleVCacheFlags(avc, flags, CDirty); /* next reference will re-stat */
     /* now find the disk cache entries */
     afs_TryToSmush(avc, acred, 1);
-    if (!skipdnlc) {
-       osi_dnlc_purgedp(avc);
-    }
     if (avc->linkData && !(avc->f.states & CCore)) {
        afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
        avc->linkData = NULL;
@@ -3244,8 +3187,74 @@ afs_ClearAllStatdFlag(void)
 
     for (i = 0; i < VCSIZE; i++) {
        for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
-           tvc->f.states &= ~(CStatd|CUnique);
+           afs_StaleVCacheFlags(tvc, AFS_STALEVC_NODNLC | AFS_STALEVC_NOCB,
+                                CUnique);
        }
     }
     ReleaseWriteLock(&afs_xvcache);
 }
+
+/**
+ * Mark a vcache as stale; our metadata for the relevant file may be out of
+ * date.
+ *
+ * @post Any subsequent access to this vcache will cause us to fetch the
+ *       metadata for this vcache again.
+ */
+void
+afs_StaleVCacheFlags(struct vcache *avc, afs_stalevc_flags_t flags,
+                    afs_uint32 cflags)
+{
+    int do_dnlc = 1;
+    int do_filename = 0;
+    int do_dequeue = 1;
+    int lock_cbhash = 1;
+
+    if ((flags & AFS_STALEVC_NODNLC)) {
+       do_dnlc = 0;
+    }
+    if ((flags & AFS_STALEVC_FILENAME)) {
+       do_filename = 1;
+    }
+    if ((flags & AFS_STALEVC_CBLOCKED)) {
+       lock_cbhash = 0;
+    }
+    if ((flags & AFS_STALEVC_NOCB)) {
+       do_dequeue = 0;
+       lock_cbhash = 0;
+    }
+
+    if (lock_cbhash) {
+       ObtainWriteLock(&afs_xcbhash, 486);
+    }
+    if (do_dequeue) {
+       afs_DequeueCallback(avc);
+    }
+
+    cflags |= CStatd;
+    avc->f.states &= ~cflags;
+
+    if (lock_cbhash) {
+       ReleaseWriteLock(&afs_xcbhash);
+    }
+
+    if ((flags & AFS_STALEVC_SKIP_DNLC_FOR_INIT_FLUSHED) &&
+       (avc->f.states & (CVInit | CVFlushed))) {
+       do_dnlc = 0;
+    }
+
+    if (flags & AFS_STALEVC_CLEARCB) {
+       avc->callback = NULL;
+    }
+
+    if (do_dnlc) {
+       if ((avc->f.fid.Fid.Vnode & 1) || vType(avc) == VDIR ||
+           (avc->f.states & CForeign)) {
+           /* This vcache is (or could be) a directory. */
+           osi_dnlc_purgedp(avc);
+
+       } else if (do_filename) {
+           osi_dnlc_purgevp(avc);
+       }
+    }
+}
index 0dcab6b5934b5e68e637282cc5ae876511280a4c..b731a598c1c655976f5961f33ef0d26577458cda 100644 (file)
@@ -537,13 +537,8 @@ loop:
 #endif
                    ReleaseReadLock(&afs_xvcache);
 
-                   ObtainWriteLock(&afs_xcbhash, 485);
                    /* LOCKXXX: We aren't holding tvc write lock? */
-                   afs_DequeueCallback(tvc);
-                   tvc->f.states &= ~CStatd;
-                   ReleaseWriteLock(&afs_xcbhash);
-                   if (tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
-                       osi_dnlc_purgedp(tvc);
+                   afs_StaleVCache(tvc);
 
 #ifdef AFS_DARWIN80_ENV
                    vnode_put(AFSTOV(tvc));