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;
scp->mask = 0;
/* discard symlink info */
+ scp->mpDataVersion = CM_SCACHE_VERSION_BAD;
scp->mountPointStringp[0] = '\0';
memset(&scp->mountRootFid, 0, sizeof(cm_fid_t));
memset(&scp->dotdotFid, 0, sizeof(cm_fid_t));
/* 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 (!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) {
switch (statusp->errorCode) {
case EACCES:
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;
lock_ReleaseWrite(&buf_globalLock);
}
- /*
- * If the dataVersion has changed, the mountPointStringp must be cleared
- * in order to force a re-evaluation by cm_HandleLink(). The Windows CM
- * does not update a mountpoint or symlink by altering the contents of
- * the file data; but the Unix CM does.
- */
if (scp->dataVersion != dataVersion && !(flags & CM_MERGEFLAG_FETCHDATA)) {
- scp->mountPointStringp[0] = '\0';
-
osi_Log5(afsd_logp, "cm_MergeStatus data version change scp 0x%p cell %u vol %u vn %u uniq %u",
scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
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);
if (scp->fileType == CM_SCACHETYPE_DFSLINK)
cm_VolStatus_Invalidate_DFS_Mapping(scp);
-
- /* Force mount points and symlinks to be re-evaluated */
- scp->mountPointStringp[0] = '\0';
}
void cm_AFSFidFromFid(AFSFid *afsFidp, cm_fid_t *fidp)
}
sprintf(output,
"%s scp=0x%p, fid (cell=%d, volume=%d, vnode=%d, unique=%d) type=%d dv=%I64d len=0x%I64x "
- "mp='%s' Locks (server=0x%x shared=%d excl=%d clnt=%d) fsLockCount=%d linkCount=%d anyAccess=0x%x "
+ "mpDV=%I64d mp='%s' Locks (server=0x%x shared=%d excl=%d clnt=%d) fsLockCount=%d linkCount=%d anyAccess=0x%x "
"flags=0x%x cbServer='%s' cbExpires='%s' volumeCreationDate='%s' refCount=%u\r\n",
cookie, scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
- scp->fileType, scp->dataVersion, scp->length.QuadPart, scp->mountPointStringp,
+ scp->fileType, scp->dataVersion, scp->length.QuadPart, scp->mpDataVersion, scp->mountPointStringp,
scp->serverLock, scp->sharedLocks, scp->exclusiveLocks, scp->clientLocks, scp->fsLockCount,
scp->linkCount, scp->anyAccess, scp->flags, srvStr ? srvStr : "<none>", cbt ? cbt : "<none>",
cdrot ? cdrot : "<none>", scp->refCount);