From 33bed6296114e16914cecf312c762774d44386c8 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sun, 17 Feb 2008 05:26:51 +0000 Subject: [PATCH] windows-buf-consistency-20080217 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 | 5 +++++ src/WINNT/afsd/cm_scache.c | 52 ++++++++++++++++++++++++++------------------ src/WINNT/afsd/cm_vnodeops.c | 2 ++ 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/WINNT/afsd/cm_dcache.c b/src/WINNT/afsd/cm_dcache.c index 6865daf..8fe7dbe 100644 --- a/src/WINNT/afsd/cm_dcache.c +++ b/src/WINNT/afsd/cm_dcache.c @@ -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); diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index bd3b902..1a4d394 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -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; diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index c3464b1..3d6c771 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -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; -- 1.9.4