return 0;
if ((bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED)) == (CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED))
return 1;
- if (bufp->dataVersion == scp->dataVersion)
+ if (bufp->dataVersion <= scp->dataVersion && bufp->dataVersion >= scp->bufDataVersionLow)
return 1;
if (!isBufLocked) {
code = lock_TryMutex(&bufp->mx);
lock_ObtainMutex(&scp->mx);
/* don't bother fetching over data that is already current */
- if (tbp->dataVersion == scp->dataVersion) {
+ if (tbp->dataVersion <= scp->dataVersion && tbp->dataVersion >= scp->bufDataVersionLow) {
/* we don't need this buffer, since it is current */
lock_ReleaseMutex(&scp->mx);
lock_ReleaseMutex(&tbp->mx);
osi_Log1(afsd_logp,"GetBuffer returns cm_data.rootSCachep=%x",cm_data.rootSCachep);
#endif
- if (cm_HaveCallback(scp) && bufp->dataVersion == scp->dataVersion) {
+ if (cm_HaveCallback(scp) && bufp->dataVersion <= scp->dataVersion && bufp->dataVersion >= scp->bufDataVersionLow) {
/* We already have this buffer don't do extra work */
return 0;
}
* We can lose a race condition and end up with biod.length zero, in
* which case we just retry.
*/
- if (bufp->dataVersion == scp->dataVersion || biod.length == 0) {
+ if (bufp->dataVersion <= scp->dataVersion && bufp->dataVersion >= scp->bufDataVersionLow || biod.length == 0) {
if ((bufp->dataVersion == -1 || bufp->dataVersion < scp->dataVersion) &&
LargeIntegerGreaterThanOrEqualTo(bufp->offset, scp->serverLength))
{
| CM_SCACHEFLAG_EACCESS);
scp->serverModTime = 0;
scp->dataVersion = 0;
+ scp->bufDataVersionLow = 0;
scp->bulkStatProgress = hzero;
scp->waitCount = 0;
scp->waitQueueT = NULL;
scp->parentVnode=0x1;
scp->group=0;
scp->dataVersion=cm_data.fakeDirVersion;
+ scp->bufDataVersionLow=cm_data.fakeDirVersion;
scp->lockDataVersion=-1; /* no lock yet */
#if not_too_dangerous
lock_ReleaseMutex(&scp->mx);
scp->unixModeBits = 0;
scp->anyAccess = 0;
scp->dataVersion = 0;
+ scp->bufDataVersionLow = 0;
if (dscp) {
scp->parentVnode = dscp->fid.vnode;
cm_AddACLCache(scp, userp, statusp->CallerAccess);
}
- if ((flags & CM_MERGEFLAG_STOREDATA) && dataVersion - scp->dataVersion == 1) {
- buf_ForceDataVersion(scp, scp->dataVersion, dataVersion);
- } else if (scp->dataVersion != 0 &&
+ if (scp->dataVersion != 0 &&
(!(flags & CM_MERGEFLAG_DIROP) && dataVersion != scp->dataVersion ||
(flags & CM_MERGEFLAG_DIROP) && dataVersion - scp->dataVersion > 1)) {
/*
}
lock_ReleaseWrite(&buf_globalLock);
}
+
+ /* We maintain a range of buffer dataVersion values which are considered
+ * valid. This avoids the need to update the dataVersion on each buffer
+ * object during an uncontested storeData operation. As a result this
+ * merge status no longer has performance characteristics derived from
+ * the size of the file.
+ */
+ if (((flags & CM_MERGEFLAG_STOREDATA) && dataVersion - scp->dataVersion > 1) ||
+ (!(flags & CM_MERGEFLAG_STOREDATA) && scp->dataVersion != dataVersion))
+ scp->bufDataVersionLow = dataVersion;
+
scp->dataVersion = dataVersion;
}
afs_uint32 unixModeBits; /* unix protection mode bits */
afs_uint32 linkCount; /* link count */
afs_uint64 dataVersion; /* data version */
+ afs_uint64 bufDataVersionLow; /* range of valid cm_buf_t dataVersions */
afs_uint32 owner; /* file owner */
afs_uint32 group; /* file owning group */
cm_user_t *creator; /* user, if new file */