windows-buf-data-versions-20080224
authorJeffrey Altman <jaltman@secure-endpoints.com>
Sun, 24 Feb 2008 06:31:54 +0000 (06:31 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sun, 24 Feb 2008 06:31:54 +0000 (06:31 +0000)
LICENSE MIT

An implementation of Asanka's idea.

Avoid the need to update the data version number on each buffer associated
with a scache when MergeStatus is called after a StoreData by maintaining
a range of valid data versions as part of the cm_scache_t object.

src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_scache.h

index 3243e38..518dbc7 100644 (file)
@@ -503,7 +503,7 @@ int cm_HaveBuffer(cm_scache_t *scp, cm_buf_t *bufp, int isBufLocked)
         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);
@@ -1159,7 +1159,7 @@ long cm_SetupFetchBIOD(cm_scache_t *scp, osi_hyper_t *offsetp,
         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);
@@ -1353,7 +1353,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
         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;
     }
@@ -1374,7 +1374,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
      * 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)) 
         {
index c9e298f..9aa0475 100644 (file)
@@ -164,6 +164,7 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
                     | CM_SCACHEFLAG_EACCESS);
     scp->serverModTime = 0;
     scp->dataVersion = 0;
+    scp->bufDataVersionLow = 0;
     scp->bulkStatProgress = hzero;
     scp->waitCount = 0;
     scp->waitQueueT = NULL;
@@ -766,6 +767,7 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
         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);
@@ -1542,6 +1544,7 @@ void cm_MergeStatus(cm_scache_t *dscp,
        scp->unixModeBits = 0;
        scp->anyAccess = 0;
        scp->dataVersion = 0;
+        scp->bufDataVersionLow = 0;
 
        if (dscp) {
             scp->parentVnode = dscp->fid.vnode;
@@ -1652,9 +1655,7 @@ void cm_MergeStatus(cm_scache_t *dscp,
         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)) {
         /* 
@@ -1712,6 +1713,17 @@ void cm_MergeStatus(cm_scache_t *dscp,
        }
         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;
 }
 
index b4b4b14..b00220a 100644 (file)
@@ -119,6 +119,7 @@ typedef struct cm_scache {
     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 */