| 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;
for ( scp = cm_data.scacheLRUFirstp, lscp = NULL, i = 0;
scp;
lscp = scp, scp = (cm_scache_t *) osi_QNext(&scp->q), i++ ) {
+
+ if ( scp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+ scp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+ afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+ fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+ return -18;
+ }
+
if (scp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC");
fprintf(stderr, "cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC\n");
return -1;
}
+
+ if ( scp->nextp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+ scp->nextp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+ afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+ fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+ return -21;
+ }
+
if (scp->nextp && scp->nextp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC");
fprintf(stderr, "cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC\n");
return -2;
}
+
+ if ( scp->randomACLp < (cm_aclent_t *)cm_data.aclBaseAddress ||
+ scp->randomACLp >= (cm_aclent_t *)cm_data.scacheBaseAddress) {
+ afsi_log("cm_ValidateSCache failure: out of range cm_aclent_t pointers");
+ fprintf(stderr, "cm_ValidateSCache failure: out of range cm_aclent_t pointers\n");
+ return -32;
+ }
+
if (scp->randomACLp && scp->randomACLp->magic != CM_ACLENT_MAGIC) {
afsi_log("cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC");
fprintf(stderr, "cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC\n");
for ( scp = cm_data.scacheLRULastp, lscp = NULL, i = 0; scp;
lscp = scp, scp = (cm_scache_t *) osi_QPrev(&scp->q), i++ ) {
+
+ if ( scp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+ scp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+ afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+ fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+ return -19;
+ }
+
if (scp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC");
fprintf(stderr, "cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC\n");
return -5;
}
+
+ if ( scp->nextp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+ scp->nextp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+ afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+ fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+ return -22;
+ }
+
if (scp->nextp && scp->nextp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC");
fprintf(stderr, "cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC\n");
return -6;
}
+
+ if ( scp->randomACLp < (cm_aclent_t *)cm_data.aclBaseAddress ||
+ scp->randomACLp >= (cm_aclent_t *)cm_data.scacheBaseAddress) {
+ afsi_log("cm_ValidateSCache failure: out of range cm_aclent_t pointers");
+ fprintf(stderr, "cm_ValidateSCache failure: out of range cm_aclent_t pointers\n");
+ return -31;
+ }
+
if (scp->randomACLp && scp->randomACLp->magic != CM_ACLENT_MAGIC) {
afsi_log("cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC");
fprintf(stderr, "cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC\n");
for ( i=0; i < cm_data.scacheHashTableSize; i++ ) {
for ( scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp ) {
afs_uint32 hash;
+
+ if ( scp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+ scp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+ afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+ fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+ return -20;
+ }
+
hash = CM_SCACHE_HASH(&scp->fid);
+
if (scp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC");
fprintf(stderr, "cm_ValidateSCache failure: scp->magic != CM_SCACHE_MAGIC\n");
return -9;
}
+
+ if ( scp->nextp < (cm_scache_t *)cm_data.scacheBaseAddress ||
+ scp->nextp >= (cm_scache_t *)cm_data.dnlcBaseAddress) {
+ afsi_log("cm_ValidateSCache failure: out of range cm_scache_t pointers");
+ fprintf(stderr, "cm_ValidateSCache failure: out of range cm_scache_t pointers\n");
+ return -23;
+ }
+
if (scp->nextp && scp->nextp->magic != CM_SCACHE_MAGIC) {
afsi_log("cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC");
fprintf(stderr, "cm_ValidateSCache failure: scp->nextp->magic != CM_SCACHE_MAGIC\n");
return -10;
}
+
+ if ( scp->randomACLp < (cm_aclent_t *)cm_data.aclBaseAddress ||
+ scp->randomACLp >= (cm_aclent_t *)cm_data.scacheBaseAddress) {
+ afsi_log("cm_ValidateSCache failure: out of range cm_aclent_t pointers");
+ fprintf(stderr, "cm_ValidateSCache failure: out of range cm_aclent_t pointers\n");
+ return -30;
+ }
+
if (scp->randomACLp && scp->randomACLp->magic != CM_ACLENT_MAGIC) {
afsi_log("cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC");
fprintf(stderr, "cm_ValidateSCache failure: scp->randomACLp->magic != CM_ACLENT_MAGIC\n");
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);
osi_Log1(afsd_logp, "CM SyncOp getting callback on scp 0x%p",
scp);
- if (cm_EAccesFindEntry(userp, &scp->fid))
- return CM_ERROR_NOACCESS;
+ if (cm_EAccesFindEntry(userp, &scp->fid)) {
+ code = CM_ERROR_NOACCESS;
+ goto on_error;
+ }
if (bufLocked)
lock_ReleaseMutex(&bufp->mx);
lock_ObtainWrite(&scp->rw);
}
if (code)
- return code;
+ goto on_error;
+
flags &= ~CM_SCACHESYNC_FORCECB; /* only force once */
continue;
}
/* can't check access rights without a callback */
osi_assertx(flags & CM_SCACHESYNC_NEEDCALLBACK, "!CM_SCACHESYNC_NEEDCALLBACK");
- if ((rights & (PRSFS_WRITE|PRSFS_DELETE)) && (scp->flags & CM_SCACHEFLAG_RO))
- return CM_ERROR_READONLY;
+ if ((rights & (PRSFS_WRITE|PRSFS_DELETE)) && (scp->flags & CM_SCACHEFLAG_RO)) {
+ code = CM_ERROR_READONLY;
+ goto on_error;
+ }
if (cm_HaveAccessRights(scp, userp, reqp, rights, &outRights)) {
- if (~outRights & rights)
- return CM_ERROR_NOACCESS;
+ if (~outRights & rights) {
+ code = CM_ERROR_NOACCESS;
+ goto on_error;
+ }
}
else {
/* we don't know the required access rights */
lock_ObtainWrite(&scp->rw);
}
if (code)
- return code;
+ goto on_error;
continue;
}
}
/* first check if we're not supposed to wait: fail
* in this case, returning with everything still locked.
*/
- if (flags & CM_SCACHESYNC_NOWAIT)
- return CM_ERROR_WOULDBLOCK;
+ if (flags & CM_SCACHESYNC_NOWAIT) {
+ code = CM_ERROR_WOULDBLOCK;
+ goto on_error;
+ }
/* These are used for minidump debugging */
sleep_scp_flags = scp->flags; /* so we know why we slept */
_InterlockedOr(&bufp->cmFlags, CM_BUF_CMWRITING);
}
- return 0;
+ return 0; /* Success */
+
+ on_error:
+ /*
+ * This thread may have been a waiter that was woken up.
+ * If cm_SyncOp completes due to an error, cm_SyncOpDone() will
+ * never be called. If there are additional threads waiting on
+ * scp those threads will never be woken. Make sure we wake the
+ * next waiting thread before we leave.
+ */
+ if ((scp->flags & CM_SCACHEFLAG_WAITING) ||
+ !osi_QIsEmpty(&scp->waitQueueH)) {
+ osi_Log3(afsd_logp, "CM SyncOp 0x%x Waking scp 0x%p bufp 0x%p",
+ flags, scp, bufp);
+ osi_Wakeup((LONG_PTR) &scp->flags);
+ }
+ return code;
}
/* for those syncops that setup for RPCs.
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) {
/*
osi_Log2(afsd_logp,"cm_ReleaseSCacheNoLock scp 0x%p ref %d",scp, refCount);
afsi_log("%s:%d cm_ReleaseSCacheNoLock scp 0x%p ref %d", file, line, scp, refCount);
#endif
-
- if (refCount == 0 && (scp->flags & CM_SCACHEFLAG_DELETED)) {
- int deleted = 0;
- long lockstate;
-
- lockstate = lock_GetRWLockState(&cm_scacheLock);
- if (lockstate != OSI_RWLOCK_WRITEHELD)
- lock_ReleaseRead(&cm_scacheLock);
- else
- lock_ReleaseWrite(&cm_scacheLock);
-
- lock_ObtainWrite(&scp->rw);
- if (scp->flags & CM_SCACHEFLAG_DELETED)
- deleted = 1;
-
- if (refCount == 0 && deleted) {
- lock_ObtainWrite(&cm_scacheLock);
- cm_RecycleSCache(scp, 0);
- if (lockstate != OSI_RWLOCK_WRITEHELD)
- lock_ConvertWToR(&cm_scacheLock);
- } else {
- if (lockstate != OSI_RWLOCK_WRITEHELD)
- lock_ObtainRead(&cm_scacheLock);
- else
- lock_ObtainWrite(&cm_scacheLock);
- }
- lock_ReleaseWrite(&scp->rw);
- }
}
#ifdef DEBUG_REFCOUNT
afsi_log("%s:%d cm_ReleaseSCache scp 0x%p ref %d", file, line, scp, refCount);
#endif
lock_ReleaseRead(&cm_scacheLock);
-
- if (scp->flags & CM_SCACHEFLAG_DELETED) {
- int deleted = 0;
- lock_ObtainWrite(&scp->rw);
- if (scp->flags & CM_SCACHEFLAG_DELETED)
- deleted = 1;
- if (deleted) {
- lock_ObtainWrite(&cm_scacheLock);
- cm_RecycleSCache(scp, 0);
- lock_ReleaseWrite(&cm_scacheLock);
- }
- lock_ReleaseWrite(&scp->rw);
- }
}
/* just look for the scp entry to get filetype */