void cm_AdjustScacheLRU(cm_scache_t *scp)
{
lock_AssertWrite(&cm_scacheLock);
- osi_QRemoveHT((osi_queue_t **) &cm_data.scacheLRUFirstp, (osi_queue_t **) &cm_data.scacheLRULastp, &scp->q);
- if (scp->flags & CM_SCACHEFLAG_DELETED) {
- /* Since it has been deleted make it the first to be recycled. */
- osi_QAddT((osi_queue_t **) &cm_data.scacheLRUFirstp, (osi_queue_t **) &cm_data.scacheLRULastp, &scp->q);
- } else {
+ if (!(scp->flags & CM_SCACHEFLAG_DELETED)) {
+ osi_QRemoveHT((osi_queue_t **) &cm_data.scacheLRUFirstp, (osi_queue_t **) &cm_data.scacheLRULastp, &scp->q);
osi_QAddH((osi_queue_t **) &cm_data.scacheLRUFirstp, (osi_queue_t **) &cm_data.scacheLRULastp, &scp->q);
}
}
* also initialize some flags */
scp->fileType = 0;
_InterlockedAnd(&scp->flags,
- ~(CM_SCACHEFLAG_STATD
- | CM_SCACHEFLAG_DELETED
+ ~( CM_SCACHEFLAG_DELETED
| CM_SCACHEFLAG_RO
| CM_SCACHEFLAG_PURERO
| CM_SCACHEFLAG_OVERQUOTA
- | CM_SCACHEFLAG_OUTOFSPACE));
+ | CM_SCACHEFLAG_OUTOFSPACE
+ | CM_SCACHEFLAG_ASYNCSTORING));
scp->serverModTime = 0;
scp->dataVersion = CM_SCACHE_VERSION_BAD;
scp->bufDataVersionLow = CM_SCACHE_VERSION_BAD;
/* if we get here, we should allocate a new scache entry. We either are below
* quota or we have a leak and need to allocate a new one to avoid panicing.
*/
- scp = cm_data.scacheBaseAddress + cm_data.currentSCaches;
+ scp = cm_data.scacheBaseAddress + InterlockedIncrement(&cm_data.currentSCaches) - 1;
osi_assertx(scp >= cm_data.scacheBaseAddress && scp < (cm_scache_t *)cm_data.scacheHashTablep,
"invalid cm_scache_t address");
memset(scp, 0, sizeof(cm_scache_t));
scp->dataVersion = CM_SCACHE_VERSION_BAD;
scp->bufDataVersionLow = CM_SCACHE_VERSION_BAD;
scp->lockDataVersion = CM_SCACHE_VERSION_BAD;
+ scp->mpDataVersion = CM_SCACHE_VERSION_BAD;
/* and put it in the LRU queue */
osi_QAddH((osi_queue_t **) &cm_data.scacheLRUFirstp, (osi_queue_t **)&cm_data.scacheLRULastp, &scp->q);
- cm_data.currentSCaches++;
cm_dnlcPurgedp(scp); /* make doubly sure that this is not in dnlc */
cm_dnlcPurgevp(scp);
scp->allNextp = cm_data.allSCachesp;
}
scp->cbExpires = 0;
scp->cbIssued = 0;
- _InterlockedAnd(&scp->flags, ~CM_SCACHEFLAG_CALLBACK);
lock_ReleaseWrite(&scp->rw);
#ifdef USE_BPLUS
scp->dirDataVersion = CM_SCACHE_VERSION_BAD;
#endif
scp->waitQueueT = NULL;
- _InterlockedAnd(&scp->flags, ~(CM_SCACHEFLAG_CALLBACK | CM_SCACHEFLAG_WAITING | CM_SCACHEFLAG_RDR_IN_USE));
+ _InterlockedAnd(&scp->flags, ~(CM_SCACHEFLAG_WAITING | CM_SCACHEFLAG_RDR_IN_USE));
scp->redirBufCount = 0;
scp->redirQueueT = NULL;
if (!cellp) {
/* put back newScp so it can be reused */
lock_ObtainWrite(&cm_scacheLock);
- newScp->flags |= CM_SCACHEFLAG_DELETED;
+ _InterlockedOr(&newScp->flags, CM_SCACHEFLAG_DELETED);
cm_AdjustScacheLRU(newScp);
lock_ReleaseWrite(&newScp->rw);
lock_ReleaseWrite(&cm_scacheLock);
if (code) {
/* put back newScp so it can be reused */
lock_ObtainWrite(&cm_scacheLock);
- newScp->flags |= CM_SCACHEFLAG_DELETED;
+ _InterlockedOr(&newScp->flags, CM_SCACHEFLAG_DELETED);
cm_AdjustScacheLRU(newScp);
lock_ReleaseWrite(&newScp->rw);
lock_ReleaseWrite(&cm_scacheLock);
cm_AdjustScacheLRU(scp);
/* put back newScp so it can be reused */
- newScp->flags |= CM_SCACHEFLAG_DELETED;
+ _InterlockedOr(&newScp->flags, CM_SCACHEFLAG_DELETED);
cm_AdjustScacheLRU(newScp);
lock_ReleaseWrite(&newScp->rw);
lock_ReleaseWrite(&cm_scacheLock);
afs_uint32 sleep_buf_cmflags = 0;
afs_uint32 sleep_scp_bufs = 0;
int wakeupCycle;
+ afs_int32 waitCount;
+ afs_int32 waitRequests;
lock_AssertWrite(&scp->rw);
/* wait here, then try again */
osi_Log1(afsd_logp, "CM SyncOp sleeping scp 0x%p", scp);
- if ( scp->flags & CM_SCACHEFLAG_WAITING ) {
- scp->waitCount++;
- scp->waitRequests++;
+
+ waitCount = InterlockedIncrement(&scp->waitCount);
+ waitRequests = InterlockedIncrement(&scp->waitRequests);
+ if (waitCount > 1) {
osi_Log3(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING already set for 0x%p; %d threads; %d requests",
- scp, scp->waitCount, scp->waitRequests);
+ scp, waitCount, waitRequests);
} else {
osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING set for 0x%p", scp);
_InterlockedOr(&scp->flags, CM_SCACHEFLAG_WAITING);
- scp->waitCount = scp->waitRequests = 1;
}
cm_SyncOpAddToWaitQueue(scp, flags, bufp);
cm_UpdateServerPriority();
- scp->waitCount--;
+ waitCount = InterlockedDecrement(&scp->waitCount);
osi_Log3(afsd_logp, "CM SyncOp woke! scp 0x%p; still waiting %d threads of %d requests",
- scp, scp->waitCount, scp->waitRequests);
- if (scp->waitCount == 0) {
+ scp, waitCount, scp->waitRequests);
+ if (waitCount == 0) {
osi_Log1(afsd_logp, "CM SyncOp CM_SCACHEFLAG_WAITING reset for 0x%p", scp);
_InterlockedAnd(&scp->flags, ~CM_SCACHEFLAG_WAITING);
scp->waitRequests = 0;
}
/* and wakeup anyone who is waiting */
- if (scp->flags & CM_SCACHEFLAG_WAITING) {
+ if ((scp->flags & CM_SCACHEFLAG_WAITING) ||
+ !osi_QIsEmpty(&scp->waitQueueH)) {
osi_Log3(afsd_logp, "CM SyncOpDone 0x%x Waking scp 0x%p bufp 0x%p", flags, scp, bufp);
osi_Wakeup((LONG_PTR) &scp->flags);
}
return (afs_uint32)(dv1 - dv2);
}
+long
+cm_IsStatusValid(AFSFetchStatus *statusp)
+{
+ if (statusp->InterfaceVersion != 0x1 ||
+ !(statusp->FileType > 0 && statusp->FileType <= SymbolicLink)) {
+ return 0;
+ }
+
+ return 1;
+}
+
/* merge in a response from an RPC. The scp must be locked, and the callback
* is optional.
*
* handled after the callback breaking is done, but only one of whose calls
* started before that, can cause old info to be merged from the first call.
*/
-void cm_MergeStatus(cm_scache_t *dscp,
+long cm_MergeStatus(cm_scache_t *dscp,
cm_scache_t *scp, AFSFetchStatus *statusp,
AFSVolSync *volsyncp,
cm_user_t *userp, cm_req_t *reqp, afs_uint32 flags)
}
#endif /* AFS_FREELANCE_CLIENT */
- if (statusp->InterfaceVersion != 0x1) {
- osi_Log2(afsd_logp, "Merge, Failure scp 0x%p Invalid InterfaceVersion %u",
- scp, statusp->InterfaceVersion);
- return;
+ if (!cm_IsStatusValid(statusp)) {
+ osi_Log3(afsd_logp, "Merge: Bad Status scp 0x%p Invalid InterfaceVersion %d FileType %d",
+ scp, statusp->InterfaceVersion, statusp->FileType);
+ return CM_ERROR_INVAL;
}
if (statusp->errorCode != 0) {
if (scp->fid.vnode & 0x1)
scp->fileType = CM_SCACHETYPE_DIRECTORY;
else
- scp->fileType = 0; /* unknown */
+ scp->fileType = CM_SCACHETYPE_UNKNOWN;
scp->serverModTime = 0;
scp->clientModTime = 0;
if (((flags & (CM_MERGEFLAG_STOREDATA|CM_MERGEFLAG_DIROP)) && (dv_diff(dataVersion, scp->dataVersion) > activeRPCs)) ||
(!(flags & (CM_MERGEFLAG_STOREDATA|CM_MERGEFLAG_DIROP)) && (scp->dataVersion != dataVersion)) ||
scp->bufDataVersionLow == CM_SCACHE_VERSION_BAD ||
- scp->fileType == CM_SCACHETYPE_DIRECTORY)
+ scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ flags & CM_MERGEFLAG_CACHE_BYPASS) {
scp->bufDataVersionLow = dataVersion;
+ }
if (RDR_Initialized) {
/*
scp->fileType, AFS_INVALIDATE_DATA_VERSION);
lock_ObtainWrite(&scp->rw);
}
+
+ return 0;
}
/* note that our stat cache info is incorrect, so force us eventually
}
scp->cbExpires = 0;
scp->cbIssued = 0;
- _InterlockedAnd(&scp->flags, ~(CM_SCACHEFLAG_CALLBACK | CM_SCACHEFLAG_LOCAL | CM_SCACHEFLAG_RDR_IN_USE));
+ _InterlockedAnd(&scp->flags, ~(CM_SCACHEFLAG_LOCAL | CM_SCACHEFLAG_RDR_IN_USE));
cm_dnlcPurgedp(scp);
cm_dnlcPurgevp(scp);
cm_FreeAllACLEnts(scp);