windows-buf-consistency-20080217
authorJeffrey Altman <jaltman@secure-endpoints.com>
Sun, 17 Feb 2008 05:26:51 +0000 (05:26 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sun, 17 Feb 2008 05:26:51 +0000 (05:26 +0000)
LICENSE MIT

All calls to buf_Get() must be protected by a read lock on the
cm_scache_t bufCreateLock

When a MergeStatus results in the invalidation of buffers, do
not remove buffers from the hash tables that have active references.

src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_vnodeops.c

index 6865daf..8fe7dbe 100644 (file)
@@ -694,7 +694,10 @@ cm_BkgPrefetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, af
             lock_ReleaseMutex(&scp->mx);
             mxheld = 0;
         }
+
+        lock_ObtainRead(&scp->bufCreateLock);
         code = buf_Get(scp, &offset, &bp);
+        lock_ReleaseRead(&scp->bufCreateLock);
         if (code)
             break;
 
@@ -1087,7 +1090,9 @@ long cm_SetupFetchBIOD(cm_scache_t *scp, osi_hyper_t *offsetp,
         if (LargeIntegerGreaterThanOrEqualTo(pageBase, fileSize)) 
             break;
 
+        lock_ObtainRead(&scp->bufCreateLock);
         code = buf_Get(scp, &pageBase, &tbp);
+        lock_ReleaseRead(&scp->bufCreateLock);
         if (code) {
             //lock_ReleaseMutex(&cm_bufGetMutex);
             lock_ObtainMutex(&scp->mx);
index bd3b902..1a4d394 100644 (file)
@@ -1657,31 +1657,41 @@ void cm_MergeStatus(cm_scache_t *dscp,
                for (bp = cm_data.buf_fileHashTablepp[i]; bp; bp=nextBp)
        {
             nextBp = bp->fileHashp;
+            /* 
+             * if the buffer belongs to this stat cache entry
+             * and the buffer mutex can be obtained, check the
+             * reference count and if it is zero, remove the buffer
+             * from the hash tables.  If there are references,
+             * the buffer might be updated to the current version
+             * so leave it in place.
+             */
+            if (cm_FidCmp(&scp->fid, &bp->fid) == 0 &&
+                 lock_TryMutex(&bp->mx)) {
+                if (bp->refCount == 0) {
+                    prevBp = bp->fileHashBackp;
+                    bp->fileHashBackp = bp->fileHashp = NULL;
+                    if (prevBp)
+                        prevBp->fileHashp = nextBp;
+                    else
+                        cm_data.buf_fileHashTablepp[i] = nextBp;
+                    if (nextBp)
+                        nextBp->fileHashBackp = prevBp;
+
+                    j = BUF_HASH(&bp->fid, &bp->offset);
+                    lbpp = &(cm_data.buf_scacheHashTablepp[j]);
+                    for(tbp = *lbpp; tbp; lbpp = &tbp->hashp, tbp = *lbpp) {
+                        if (tbp == bp) 
+                            break;
+                    }
 
-            if (cm_FidCmp(&scp->fid, &bp->fid) == 0) {
-                prevBp = bp->fileHashBackp;
-                bp->fileHashBackp = bp->fileHashp = NULL;
-                if (prevBp)
-                    prevBp->fileHashp = nextBp;
-                else
-                    cm_data.buf_fileHashTablepp[i] = nextBp;
-                if (nextBp)
-                    nextBp->fileHashBackp = prevBp;
-
-                j = BUF_HASH(&bp->fid, &bp->offset);
-                lbpp = &(cm_data.buf_scacheHashTablepp[j]);
-                for(tbp = *lbpp; tbp; lbpp = &tbp->hashp, tbp = *lbpp) {
-                    if (tbp == bp) 
-                        break;
-                }
-
-                *lbpp = bp->hashp;     /* hash out */
-                bp->hashp = NULL;
+                    *lbpp = bp->hashp; /* hash out */
+                    bp->hashp = NULL;
 
-                bp->flags &= ~CM_BUF_INHASH;
+                    bp->flags &= ~CM_BUF_INHASH;
+                }
+                lock_ReleaseMutex(&bp->mx);
             }
        }
-
         lock_ReleaseWrite(&buf_globalLock);
     }
     scp->dataVersion = dataVersion;
index c3464b1..3d6c771 100644 (file)
@@ -1698,7 +1698,9 @@ long cm_HandleLink(cm_scache_t *linkScp, cm_user_t *userp, cm_req_t *reqp)
         /* read the link data */
         lock_ReleaseMutex(&linkScp->mx);
         thyper.LowPart = thyper.HighPart = 0;
+        lock_ObtainRead(&linkScp->bufCreateLock);
         code = buf_Get(linkScp, &thyper, &bufp);
+        lock_ReleaseRead(&linkScp->bufCreateLock);
         lock_ObtainMutex(&linkScp->mx);
         if (code) 
             return code;