diff --git a/src/WINNT/afsd/cm_buf.c b/src/WINNT/afsd/cm_buf.c index 4669c1fe98..e5a6abc987 100644 --- a/src/WINNT/afsd/cm_buf.c +++ b/src/WINNT/afsd/cm_buf.c @@ -722,11 +722,12 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu /* does this fix the problem below? it's a simple solution. */ if (!cm_data.buf_freeListEndp) - { + { lock_ReleaseWrite(&buf_globalLock); + osi_Log0(afsd_logp, "buf_GetNewLocked: Free Buffer List is empty - sleeping 200ms"); Sleep(200); goto retry; - } + } /* for debugging, assert free list isn't empty, although we * really should try waiting for a running tranasction to finish @@ -828,17 +829,12 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu cm_data.buf_fileHashTablepp[i] = bp; } - /* prepare to return it. Start by giving it a good - * refcount */ - bp->refCount = 1; - - /* and since it has a non-zero ref count, we should move - * it from the lru queue. It better be still there, - * since we've held the global (big) lock since we found - * it there. + /* we should move it from the lru queue. It better still be there, + * since we've held the global (big) lock since we found it there. */ osi_assertx(bp->flags & CM_BUF_INLRU, "buf_GetNewLocked: LRU screwup"); + if (cm_data.buf_freeListEndp == bp) { /* we're the last guy in this queue, so maintain it */ cm_data.buf_freeListEndp = (cm_buf_t *) osi_QPrev(&bp->q); @@ -846,13 +842,19 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu osi_QRemove((osi_queue_t **) &cm_data.buf_freeListp, &bp->q); bp->flags &= ~CM_BUF_INLRU; - /* finally, grab the mutex so that people don't use it + /* grab the mutex so that people don't use it * before the caller fills it with data. Again, no one * should have been able to get to this dude to lock it. */ - osi_assertx(lock_TryMutex(&bp->mx), - "buf_GetNewLocked: TryMutex failed"); + if (!lock_TryMutex(&bp->mx)) { + osi_Log2(afsd_logp, "buf_GetNewLocked bp 0x%p cannot be mutex locked. refCount %d should be 0", + bp, bp->refCount); + osi_panic("buf_GetNewLocked: TryMutex failed",__FILE__,__LINE__); + } + /* prepare to return it. Give it a refcount */ + bp->refCount = 1; + lock_ReleaseWrite(&buf_globalLock); *bufpp = bp; @@ -862,7 +864,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu return 0; } /* for all buffers in lru queue */ lock_ReleaseWrite(&buf_globalLock); - Sleep(100); /* give some time for a buffer to be freed */ + osi_Log0(afsd_logp, "buf_GetNewLocked: Free Buffer List has no buffers with a zero refcount - sleeping 100ms"); + Sleep(100); /* give some time for a buffer to be freed */ } /* while loop over everything */ /* not reached */ } /* the proc */ @@ -1297,7 +1300,7 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, buf_HoldLocked(bufp); lock_ReleaseWrite(&buf_globalLock); - for(; bufp; bufp = nbufp) { + while (bufp) { lock_ObtainMutex(&bufp->mx); bufEnd.HighPart = 0; @@ -1374,6 +1377,7 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, } buf_ReleaseLocked(bufp); lock_ReleaseWrite(&buf_globalLock); + bufp = nbufp; } #ifdef TESTING @@ -1568,21 +1572,44 @@ int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock) { for (bp = cm_data.buf_hashTablepp[i]; bp; bp=bp->hashp) { - if (bp->refCount) - { - StringCbPrintfA(output, sizeof(output), - "%s bp=0x%08X, hash=%d, fid (cell=%d, volume=%d, " - "vnode=%d, unique=%d), size=%d refCount=%d\r\n", - cookie, (void *)bp, i, bp->fid.cell, bp->fid.volume, - bp->fid.vnode, bp->fid.unique, bp->size, bp->refCount); - WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); - } + StringCbPrintfA(output, sizeof(output), + "%s bp=0x%08X, hash=%d, fid (cell=%d, volume=%d, " + "vnode=%d, unique=%d), size=%d flags=0x%x, refCount=%d\r\n", + cookie, (void *)bp, i, bp->fid.cell, bp->fid.volume, + bp->fid.vnode, bp->fid.unique, bp->size, bp->flags, bp->refCount); + WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); } } StringCbPrintfA(output, sizeof(output), "%s - Done dumping buf_HashTable.\r\n", cookie); WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); + StringCbPrintfA(output, sizeof(output), "%s - dumping buf_freeListEndp\r\n", cookie); + WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); + for(bp = cm_data.buf_freeListEndp; bp; bp=(cm_buf_t *) osi_QPrev(&bp->q)) { + StringCbPrintfA(output, sizeof(output), + "%s bp=0x%08X, fid (cell=%d, volume=%d, " + "vnode=%d, unique=%d), size=%d flags=0x%x, refCount=%d\r\n", + cookie, (void *)bp, bp->fid.cell, bp->fid.volume, + bp->fid.vnode, bp->fid.unique, bp->size, bp->flags, bp->refCount); + WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); + } + StringCbPrintfA(output, sizeof(output), "%s - Done dumping buf_FreeListEndp.\r\n", cookie); + WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); + + StringCbPrintfA(output, sizeof(output), "%s - dumping buf_dirtyListEndp\r\n", cookie); + WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); + for(bp = cm_data.buf_dirtyListEndp; bp; bp=(cm_buf_t *) osi_QPrev(&bp->q)) { + StringCbPrintfA(output, sizeof(output), + "%s bp=0x%08X, fid (cell=%d, volume=%d, " + "vnode=%d, unique=%d), size=%d flags=0x%x, refCount=%d\r\n", + cookie, (void *)bp, bp->fid.cell, bp->fid.volume, + bp->fid.vnode, bp->fid.unique, bp->size, bp->flags, bp->refCount); + WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); + } + StringCbPrintfA(output, sizeof(output), "%s - Done dumping buf_dirtyListEndp.\r\n", cookie); + WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); + if (lock) lock_ReleaseRead(&buf_globalLock); return 0; diff --git a/src/WINNT/afsd/cm_dcache.c b/src/WINNT/afsd/cm_dcache.c index 56c0fffbb4..21b8aa8eb5 100644 --- a/src/WINNT/afsd/cm_dcache.c +++ b/src/WINNT/afsd/cm_dcache.c @@ -644,7 +644,7 @@ void cm_BkgPrefetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p long length; osi_hyper_t base; long code; - cm_buf_t *bp; + cm_buf_t *bp = NULL; int cpff = 0; /* cleared prefetch flag */ cm_req_t req; @@ -664,6 +664,8 @@ void cm_BkgPrefetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p if (code || (bp->cmFlags & CM_BUF_CMFETCHING)) { scp->flags &= ~CM_SCACHEFLAG_PREFETCHING; lock_ReleaseMutex(&scp->mx); + if (bp) + buf_Release(bp); return; } diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index eaf0d51e65..7f40f166c8 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -1210,7 +1210,9 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, afs_uint32 flags) /* now update the buffer pointer */ if (flags & CM_SCACHESYNC_FETCHDATA) { - /* ensure that the buffer isn't already in the I/O list */ + int release = 0; + + /* ensure that the buffer isn't already in the I/O list */ for(qdp = scp->bufReadsp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { tbufp = osi_GetQData(qdp); if (tbufp == bufp) @@ -1219,11 +1221,9 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, afs_uint32 flags) if (qdp) { osi_QRemove((osi_queue_t **) &scp->bufReadsp, &qdp->q); osi_QDFree(qdp); + release = 1; } if (bufp) { - int release = 0; - if (bufp->cmFlags & CM_BUF_CMFETCHING) - release = 1; bufp->cmFlags &= ~(CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED); if (bufp->flags & CM_BUF_WAITING) { osi_Log2(afsd_logp, "CM SyncOpDone Waking [scp 0x%p] bufp 0x%p", scp, bufp); @@ -1236,6 +1236,7 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, afs_uint32 flags) /* now update the buffer pointer */ if (flags & CM_SCACHESYNC_STOREDATA) { + int release = 0; /* ensure that the buffer isn't already in the I/O list */ for(qdp = scp->bufWritesp; qdp; qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) { tbufp = osi_GetQData(qdp); @@ -1245,11 +1246,9 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, afs_uint32 flags) if (qdp) { osi_QRemove((osi_queue_t **) &scp->bufWritesp, &qdp->q); osi_QDFree(qdp); + release = 1; } if (bufp) { - int release = 0; - if (bufp->cmFlags & CM_BUF_CMSTORING) - release = 1; bufp->cmFlags &= ~CM_BUF_CMSTORING; if (bufp->flags & CM_BUF_WAITING) { osi_Log2(afsd_logp, "CM SyncOpDone Waking [scp 0x%p] bufp 0x%p", scp, bufp); @@ -1554,8 +1553,8 @@ int cm_DumpSCache(FILE *outputFile, char *cookie, int lock) { if (scp->refCount != 0) { - sprintf(output, "%s fid (cell=%d, volume=%d, vnode=%d, unique=%d) refCount=%u\r\n", - cookie, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique, + sprintf(output, "%s scp=0x%p, fid (cell=%d, volume=%d, vnode=%d, unique=%d) refCount=%u\r\n", + cookie, scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique, scp->refCount); WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL); } diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 9d0432237f..ec74fb1bcf 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -935,15 +935,15 @@ long cm_ReadMountPoint(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) lock_ReleaseRead(&scp->bufCreateLock); lock_ObtainMutex(&scp->mx); - if (code) { + if (code) return code; - } + while (1) { code = cm_SyncOp(scp, bufp, userp, reqp, 0, CM_SCACHESYNC_READ | CM_SCACHESYNC_NEEDCALLBACK); - if (code) { + if (code) goto done; - } + cm_SyncOpDone(scp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ); @@ -952,9 +952,8 @@ long cm_ReadMountPoint(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) /* otherwise load buffer */ code = cm_GetBuffer(scp, bufp, NULL, userp, reqp); - if (code) { + if (code) goto done; - } } /* locked, has callback, has valid data in buffer */ if ((tlen = scp->length.LowPart) > 1000)