void buf_Release(cm_buf_t *bp)
#endif
{
- afs_int32 refCount;
-
- /* ensure that we're in the LRU queue if our ref count is 0 */
- osi_assertx(bp->magic == CM_BUF_MAGIC,"incorrect cm_buf_t magic");
-
- refCount = InterlockedDecrement(&bp->refCount);
-#ifdef DEBUG_REFCOUNT
- osi_Log2(afsd_logp,"buf_Release bp 0x%p ref %d", bp, refCount);
- afsi_log("%s:%d buf_ReleaseLocked bp 0x%p, ref %d", file, line, bp, refCount);
-#endif
-#ifdef DEBUG
- if (refCount < 0)
- osi_panic("buf refcount 0",__FILE__,__LINE__);;
-#else
- osi_assertx(refCount >= 0, "cm_buf_t refCount == 0");
-#endif
- if (refCount == 0) {
- lock_ObtainWrite(&buf_globalLock);
- if (bp->refCount == 0 &&
- !(bp->qFlags & (CM_BUF_QINLRU|CM_BUF_QREDIR))) {
- osi_QAddH( (osi_queue_t **) &cm_data.buf_freeListp,
- (osi_queue_t **) &cm_data.buf_freeListEndp,
- &bp->q);
- _InterlockedOr(&bp->qFlags, CM_BUF_QINLRU);
- buf_IncrementFreeCount();
- }
- lock_ReleaseWrite(&buf_globalLock);
- }
+ lock_ObtainRead(&buf_globalLock);
+ buf_ReleaseLocked(bp, FALSE);
+ lock_ReleaseRead(&buf_globalLock);
}
long
bp = cm_data.bufHeaderBaseAddress;
data = cm_data.bufDataBaseAddress;
+ lock_ObtainWrite(&buf_globalLock);
for (i=0; i<cm_data.buf_nbuffers; i++) {
lock_InitializeMutex(&bp->mx, "Buffer mutex", LOCK_HIERARCHY_BUFFER);
bp->userp = NULL;
* extent was not returned by the file system driver.
* clean up the mess.
*/
+ buf_RemoveFromRedirQueue(NULL, bp);
bp->dataVersion = CM_BUF_VERSION_BAD;
- _InterlockedAnd(&bp->qFlags, ~CM_BUF_QREDIR);
- osi_QRemoveHT( (osi_queue_t **) &cm_data.buf_redirListp,
- (osi_queue_t **) &cm_data.buf_redirListEndp,
- &bp->q);
- buf_DecrementRedirCount();
bp->redirq.nextp = bp->redirq.prevp = NULL;
bp->redirLastAccess = 0;
bp->redirReleaseRequested = 0;
- buf_Release(bp);
+ buf_ReleaseLocked(bp, TRUE);
}
bp++;
}
* extent was not returned by the file system driver.
* clean up the mess.
*/
+ buf_RemoveFromRedirQueue(NULL, bp);
bp->dataVersion = CM_BUF_VERSION_BAD;
- _InterlockedAnd(&bp->qFlags, ~CM_BUF_QREDIR);
- osi_QRemoveHT( (osi_queue_t **) &cm_data.buf_redirListp,
- (osi_queue_t **) &cm_data.buf_redirListEndp,
- &bp->q);
- buf_DecrementRedirCount();
bp->redirq.nextp = bp->redirq.prevp = NULL;
bp->redirLastAccess = 0;
bp->redirReleaseRequested = 0;
- buf_Release(bp);
+ buf_ReleaseLocked(bp, TRUE);
}
+ lock_ReleaseWrite(&buf_globalLock);
}
#ifdef TESTING
}
if ( scp ) {
lock_ObtainRead(&scp->rw);
- if (scp->flags & CM_SCACHEFLAG_WAITING) {
+ if (!osi_QIsEmpty(&scp->waitQueueH)) {
osi_Log1(buf_logp, "buf_WaitIO waking scp 0x%p", scp);
osi_Wakeup((LONG_PTR)&scp->flags);
}
* that the cm_scache_t was recycled out of the cache even though
* a cm_buf_t with the same FID is in the cache.
*/
- if (scp == NULL) {
- if ((scp = cm_FindSCache(&bp->fid)) ||
- (cm_GetSCache(&bp->fid, &scp,
- bp->userp ? bp->userp : cm_rootUserp,
- reqp) == 0)) {
- release_scp = 1;
+ if (scp == NULL &&
+ cm_GetSCache(&bp->fid, NULL, &scp,
+ bp->userp ? bp->userp : cm_rootUserp,
+ reqp) == 0)
+ {
+ release_scp = 1;
+
+ lock_ObtainWrite(&scp->rw);
+ code = cm_SyncOp(scp, NULL, bp->userp ? bp->userp : cm_rootUserp, reqp, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code == 0) {
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
}
+ lock_ReleaseWrite(&scp->rw);
+ }
+
+ if (scp && (scp->flags & CM_SCACHEFLAG_DELETED)) {
+ _InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
+ _InterlockedOr(&bp->flags, CM_BUF_ERROR);
+ bp->dirty_length = 0;
+ bp->error = code;
+ bp->dataVersion = CM_BUF_VERSION_BAD;
+ bp->dirtyCounter++;
}
while ((bp->flags & CM_BUF_DIRTY) == CM_BUF_DIRTY) {
* to determine if it is appropriate to fill a full chunk of data
* when storing to the file server.
*/
- code = (*cm_buf_opsp->Writep)(scp, &offset,
- bp->dirty_length,
- flags, bp->userp, reqp);
+ code = (*cm_buf_opsp->Writep)(scp, &offset, bp->dirty_length, flags,
+ bp->userp ? bp->userp : cm_rootUserp, reqp);
osi_Log3(buf_logp, "buf_CleanLocked I/O on scp 0x%p buf 0x%p, done=%d", scp, bp, code);
}
lock_ObtainMutex(&bp->mx);
*/
if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BADFD || code == CM_ERROR_NOACCESS ||
code == CM_ERROR_QUOTA || code == CM_ERROR_SPACE || code == CM_ERROR_TOOBIG ||
- code == CM_ERROR_READONLY || code == CM_ERROR_NOSUCHPATH){
+ code == CM_ERROR_READONLY || code == CM_ERROR_NOSUCHPATH || code == EIO){
_InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
_InterlockedOr(&bp->flags, CM_BUF_ERROR);
- bp->dirty_offset = 0;
bp->dirty_length = 0;
bp->error = code;
bp->dataVersion = CM_BUF_VERSION_BAD;
cm_buf_t *bp; /* buffer we're dealing with */
cm_buf_t *nextBp; /* next buffer in file hash chain */
afs_uint32 i; /* temp */
- afs_uint64 n_bufs, n_nonzero, n_busy, n_dirty, n_own;
+ afs_uint64 n_bufs, n_nonzero, n_busy, n_dirty, n_own, n_redir;
#ifdef TESTING
buf_ValidateBufQueues();
n_own = 0;
n_busy = 0;
n_dirty = 0;
+ n_redir = 0;
lock_ObtainRead(&scp->bufCreateLock);
lock_ObtainWrite(&buf_globalLock);
continue;
}
+ /* leave the buffer alone if held by the redirector */
+ if (bp->qFlags & CM_BUF_QREDIR) {
+ n_redir++;
+ continue;
+ }
+
if (bp->flags & CM_BUF_DIRTY) {
n_dirty++;
- /* leave the buffer alone if held by the redirector */
- if (bp->qFlags & CM_BUF_QREDIR)
- continue;
-
/* protect against cleaning the same buffer more than once. */
if (cleaned)
continue;
lock_ReleaseWrite(&buf_globalLock);
lock_ReleaseRead(&scp->bufCreateLock);
- osi_Log1(afsd_logp, "buf_GetNewLocked: Free Buffer List has %u buffers none free", n_bufs);
+ osi_Log2(afsd_logp, "buf_GetNewLocked: Free Buffer List has %u buffers none free; redir %u", n_bufs, n_redir);
osi_Log4(afsd_logp, "... nonzero %u; own %u; busy %u; dirty %u", n_nonzero, n_own, n_busy, n_dirty);
if (RDR_Initialized) {
{
osi_assertx(bp->magic == CM_BUF_MAGIC, "invalid cm_buf_t magic");
osi_assertx(bp->refCount > 0, "cm_buf_t refcount 0");
+ osi_assertx(userp != NULL, "userp is NULL");
if (length == 0)
return;
}
_InterlockedAnd(&bufp->flags, ~CM_BUF_DIRTY);
bufp->error = 0;
- bufp->dirty_offset = 0;
bufp->dirty_length = 0;
bufp->dataVersion = CM_BUF_VERSION_BAD; /* known bad */
bufp->dirtyCounter++;
_InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
_InterlockedOr(&bp->flags, CM_BUF_ERROR);
bp->error = CM_ERROR_BADFD;
- bp->dirty_offset = 0;
bp->dirty_length = 0;
bp->dataVersion = CM_BUF_VERSION_BAD; /* known bad */
bp->dirtyCounter++;
}
/* Must be called with scp->rw held */
+long buf_InvalidateBuffers(cm_scache_t * scp)
+{
+ cm_buf_t * bp;
+ afs_uint32 i;
+ int found = 0;
+
+ lock_AssertAny(&scp->rw);
+
+ i = BUF_FILEHASH(&scp->fid);
+
+ lock_ObtainRead(&buf_globalLock);
+
+ for (bp = cm_data.buf_fileHashTablepp[i]; bp; bp = bp->fileHashp) {
+ if (cm_FidCmp(&bp->fid, &scp->fid) == 0) {
+ bp->dataVersion = CM_BUF_VERSION_BAD;
+ found = 1;
+ }
+ }
+ lock_ReleaseRead(&buf_globalLock);
+
+ if (found)
+ return 0;
+ else
+ return ENOENT;
+}
+
+/* Must be called with scp->rw held */
long buf_ForceDataVersion(cm_scache_t * scp, afs_uint64 fromVersion, afs_uint64 toVersion)
{
cm_buf_t * bp;
case CM_ERROR_TOOBIG:
case CM_ERROR_READONLY:
case CM_ERROR_NOSUCHPATH:
+ case EIO:
/*
* Apply the previous fatal error to this buffer.
* Do not waste the time attempting to store to
*/
_InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
_InterlockedOr(&bp->flags, CM_BUF_ERROR);
- bp->dirty_offset = 0;
bp->dirty_length = 0;
bp->error = code;
bp->dataVersion = CM_BUF_VERSION_BAD;
}
}
lock_ReleaseRead(&buf_globalLock);
- return 0;
+ return found;
}
long buf_RDRBuffersExist(cm_fid_t *fidp)
lock_ObtainMutex(&bp->mx);
_InterlockedAnd(&bp->cmFlags, ~CM_BUF_CMSTORING);
_InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
- bp->dirty_offset = 0;
bp->dirty_length = 0;
_InterlockedOr(&bp->flags, CM_BUF_ERROR);
bp->error = VNOVNODE;
{
lock_AssertWrite(&buf_globalLock);
- lock_ObtainMutex(&scp->redirMx);
+ if (scp) {
+ lock_ObtainMutex(&scp->redirMx);
+ }
if (bufp->qFlags & CM_BUF_QINLRU) {
_InterlockedAnd(&bufp->qFlags, ~CM_BUF_QINLRU);
&bufp->redirq);
scp->redirLastAccess = bufp->redirLastAccess;
InterlockedIncrement(&scp->redirBufCount);
- }
- lock_ReleaseMutex(&scp->redirMx);
+ lock_ReleaseMutex(&scp->redirMx);
+ }
}
void
{
lock_AssertWrite(&buf_globalLock);
- lock_ObtainMutex(&scp->redirMx);
+ if (!(bufp->qFlags & CM_BUF_QREDIR))
+ return;
+
+ if (scp) {
+ lock_ObtainMutex(&scp->redirMx);
+ }
_InterlockedAnd(&bufp->qFlags, ~CM_BUF_QREDIR);
osi_QRemoveHT( (osi_queue_t **) &cm_data.buf_redirListp,
(osi_queue_t **) &cm_data.buf_redirListEndp,
&bufp->q);
buf_DecrementRedirCount();
+
if (scp) {
osi_QRemoveHT( (osi_queue_t **) &scp->redirQueueH,
(osi_queue_t **) &scp->redirQueueT,
&bufp->redirq);
+
InterlockedDecrement(&scp->redirBufCount);
+ lock_ReleaseMutex(&scp->redirMx);
}
-
- lock_ReleaseMutex(&scp->redirMx);
}
void
buf_MoveToHeadOfRedirQueue(cm_scache_t *scp, cm_buf_t *bufp)
{
lock_AssertWrite(&buf_globalLock);
- osi_assertx(bufp->qFlags & CM_BUF_QREDIR,
- "buf_MoveToHeadOfRedirQueue buffer not held by redirector");
+ if (!(bufp->qFlags & CM_BUF_QREDIR))
+ return;
- lock_ObtainMutex(&scp->redirMx);
+ if (scp) {
+ lock_ObtainMutex(&scp->redirMx);
+ }
osi_QRemoveHT( (osi_queue_t **) &cm_data.buf_redirListp,
(osi_queue_t **) &cm_data.buf_redirListEndp,
(osi_queue_t **) &scp->redirQueueT,
&bufp->redirq);
scp->redirLastAccess = bufp->redirLastAccess;
- }
- lock_ReleaseMutex(&scp->redirMx);
+ lock_ReleaseMutex(&scp->redirMx);
+ }
}