windows-cm-buf-misc-20080229
authorJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 29 Feb 2008 22:50:54 +0000 (22:50 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 29 Feb 2008 22:50:54 +0000 (22:50 +0000)
LICENSE MIT

(1) Add an undocumented store behind mode for use in testing.  Set
    EnableSMBAsyncStore to 2.  When set all smb_WriteData calls are
    background writes, all calls to cm_FSync are skipped and file close
    operations do not block for dirty buffers to be written.  This
    permits all writes to be performed in the buf_IncrSyncer thread.

(2) Do not use I64 in osi_Log() format strings as all parameters are
    converted to size_t which is 32-bit on 32-bit Windows.

(3) Reduce the number of times the cm_buf_t mutex is obtained, dropped,
    obtained, dropped in buf_IncrSyncer

(4) In buf_CleanAsyncLocked, request that a full chunk be written instead
    of just the current buffer.  cm_SetupStoreBIOD will stop at the
    first clean buffer.  This reduces the overall number of RPCs that
    must be performed.

(5) Define CM_BUF_VERSION_BAD and use it instead of -1.

src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/cm_buf.c
src/WINNT/afsd/cm_buf.h
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_dir.c
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/smb.c

index def1eb3..a05cb9e 100644 (file)
@@ -1397,7 +1397,7 @@ int afsd_InitSMB(char **reasonP, void *aMBfunc)
         code = RegQueryValueEx(parmKey, "EnableSMBAsyncStore", NULL, NULL,
                                 (BYTE *) &dwValue, &dummyLen);
         if (code == ERROR_SUCCESS)
-            smb_AsyncStore = dwValue ? 1 : 0;
+            smb_AsyncStore = dwValue == 2 ? 2 : (dwValue ? 1 : 0);
         afsi_log("EnableSMBAsyncStore = %d", smb_AsyncStore);
 
         dummyLen = sizeof(DWORD);
index b2fc84a..1b3cc1c 100644 (file)
@@ -194,11 +194,10 @@ void buf_IncrSyncer(long parm)
 
         /* now go through our percentage of the buffers */
         for (bpp = &cm_data.buf_dirtyListp; bp = *bpp; ) {
-
            /* all dirty buffers are held when they are added to the
             * dirty list.  No need for an additional hold.
             */
-
+            lock_ObtainMutex(&bp->mx);
            if (bp->flags & CM_BUF_DIRTY) {
                /* start cleaning the buffer; don't touch log pages since
                 * the log code counts on knowing exactly who is writing
@@ -206,33 +205,27 @@ void buf_IncrSyncer(long parm)
                 */
                cm_InitReq(&req);
                req.flags |= CM_REQ_NORETRY;
-               wasDirty |= buf_CleanAsync(bp, &req);
+               wasDirty |= buf_CleanAsyncLocked(bp, &req);
            }
 
            /* the buffer may or may not have been dirty
             * and if dirty may or may not have been cleaned
             * successfully.  check the dirty flag again.  
             */
-           if (!(bp->flags & CM_BUF_DIRTY)) {
-               lock_ObtainMutex(&bp->mx);
-               if (!(bp->flags & CM_BUF_DIRTY)) {
-                   /* remove the buffer from the dirty list */
-                   lock_ObtainWrite(&buf_globalLock);
-                   *bpp = bp->dirtyp;
-                   bp->dirtyp = NULL;
-                   if (cm_data.buf_dirtyListp == NULL)
-                       cm_data.buf_dirtyListEndp = NULL;
-                   buf_ReleaseLocked(bp, TRUE);
-                   lock_ReleaseWrite(&buf_globalLock);
-               } else {
-                   /* advance the pointer so we don't loop forever */
-                   bpp = &bp->dirtyp;
-               }
-               lock_ReleaseMutex(&bp->mx);
-           } else {
-               /* advance the pointer so we don't loop forever */
-               bpp = &bp->dirtyp;
-           }
+            if (!(bp->flags & CM_BUF_DIRTY)) {
+                /* remove the buffer from the dirty list */
+                lock_ObtainWrite(&buf_globalLock);
+                *bpp = bp->dirtyp;
+                bp->dirtyp = NULL;
+                if (cm_data.buf_dirtyListp == NULL)
+                    cm_data.buf_dirtyListEndp = NULL;
+                buf_ReleaseLocked(bp, TRUE);
+                lock_ReleaseWrite(&buf_globalLock);
+            } else {
+                /* advance the pointer so we don't loop forever */
+                bpp = &bp->dirtyp;
+            }
+            lock_ReleaseMutex(&bp->mx);
         }      /* for loop over a bunch of buffers */
     }          /* whole daemon's while loop */
 }
@@ -607,7 +600,16 @@ long buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp)
 
             offset = bp->offset;
             LargeIntegerAdd(offset, ConvertLongToLargeInteger(bp->dirty_offset));
-           code = (*cm_buf_opsp->Writep)(scp, &offset, bp->dirty_length, 0, bp->userp, reqp);
+           code = (*cm_buf_opsp->Writep)(scp, &offset, 
+#if 1
+                                           /* we might as well try to write all of the contiguous 
+                                            * dirty buffers in one RPC 
+                                            */
+                                           cm_chunkSize,
+#else
+                                          bp->dirty_length, 
+#endif
+                                          0, bp->userp, reqp);
            osi_Log3(buf_logp, "buf_CleanAsyncLocked I/O on scp 0x%p buf 0x%p, done=%d", scp, bp, code);
 
            cm_ReleaseSCache(scp);
@@ -628,7 +630,7 @@ long buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp)
             bp->dirty_offset = 0;
             bp->dirty_length = 0;
            bp->error = code;
-           bp->dataVersion = -1; /* bad */
+           bp->dataVersion = CM_BUF_VERSION_BAD; /* bad */
            bp->dirtyCounter++;
        }
 
@@ -864,7 +866,7 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu
 
             /* clean up junk flags */
             bp->flags &= ~(CM_BUF_EOF | CM_BUF_ERROR);
-            bp->dataVersion = -1;      /* unknown so far */
+            bp->dataVersion = CM_BUF_VERSION_BAD;      /* unknown so far */
 
             /* now hash in as our new buffer, and give it the
              * appropriate label, if requested.
@@ -1418,7 +1420,7 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
                 bufp->flags &= ~CM_BUF_DIRTY;
                 bufp->dirty_offset = 0;
                 bufp->dirty_length = 0;
-                bufp->dataVersion = -1;        /* known bad */
+                bufp->dataVersion = CM_BUF_VERSION_BAD;        /* known bad */
                 bufp->dirtyCounter++;
             }
             else {
@@ -1509,7 +1511,7 @@ long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
                 bp->error = CM_ERROR_BADFD;
                 bp->dirty_offset = 0;
                 bp->dirty_length = 0;
-                bp->dataVersion = -1;  /* known bad */
+                bp->dataVersion = CM_BUF_VERSION_BAD;  /* known bad */
                 bp->dirtyCounter++;
                 lock_ReleaseMutex(&bp->mx);
             }
@@ -1801,7 +1803,7 @@ long buf_CleanDirtyBuffers(cm_scache_t *scp)
             bp->dirty_length = 0;
            bp->flags |= CM_BUF_ERROR;
            bp->error = VNOVNODE;
-           bp->dataVersion = -1; /* bad */
+           bp->dataVersion = CM_BUF_VERSION_BAD; /* bad */
            bp->dirtyCounter++;
            if (bp->flags & CM_BUF_WAITING) {
                osi_Log2(buf_logp, "BUF CleanDirtyBuffers Waking [scp 0x%x] bp 0x%x", scp, bp);
index e35bb9e..3d92b8c 100644 (file)
@@ -44,6 +44,8 @@ extern int buf_cacheType;
 
 #define CM_BUF_MAGIC    ('B' | 'U' <<8 | 'F'<<16 | 'F'<<24)
 
+#define CM_BUF_VERSION_BAD 0xFFFFFFFFFFFFFFFF
+
 /* represents a single buffer */
 typedef struct cm_buf {
     osi_queue_t q;             /* queue of all zero-refcount buffers */
index 518dbc7..857872e 100644 (file)
@@ -567,7 +567,7 @@ long cm_CheckFetchRange(cm_scache_t *scp, osi_hyper_t *startBasep, osi_hyper_t *
         /* We cheat slightly by not locking the bp mutex. */
         if (bp) {
             if ((bp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING)) == 0
-                 && bp->dataVersion != scp->dataVersion)
+                 && (bp->dataVersion < scp->bufDataVersionLow || bp->dataVersion > scp->dataVersion))
                 stop = 1;
             buf_Release(bp);
            bp = NULL;
@@ -1375,13 +1375,13 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
      * which case we just retry.
      */
     if (bufp->dataVersion <= scp->dataVersion && bufp->dataVersion >= scp->bufDataVersionLow || biod.length == 0) {
-        if ((bufp->dataVersion == -1 || bufp->dataVersion < scp->dataVersion) && 
+        if ((bufp->dataVersion == CM_BUF_VERSION_BAD || bufp->dataVersion < scp->bufDataVersionLow) && 
              LargeIntegerGreaterThanOrEqualTo(bufp->offset, scp->serverLength)) 
         {
-            osi_Log3(afsd_logp, "Bad DVs %I64d, %I64d or length 0x%x",
-                      bufp->dataVersion, scp->dataVersion, biod.length);
+            osi_Log4(afsd_logp, "Bad DVs 0x%x != (0x%x -> 0x%x) or length 0x%x",
+                     bufp->dataVersion, scp->bufDataVersionLow, scp->dataVersion, biod.length);
 
-            if (bufp->dataVersion == -1)
+            if (bufp->dataVersion == CM_BUF_VERSION_BAD)
                 memset(bufp->datap, 0, cm_data.buf_blockSize);
             bufp->dataVersion = scp->dataVersion;
         }
@@ -1389,6 +1389,15 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
         cm_ReleaseBIOD(&biod, 0, 0);
         lock_ObtainMutex(&scp->mx);
         return 0;
+    } else if ((bufp->dataVersion == CM_BUF_VERSION_BAD || bufp->dataVersion < scp->bufDataVersionLow)
+                && (scp->mask & CM_SCACHEMASK_TRUNCPOS) &&
+                LargeIntegerGreaterThanOrEqualTo(bufp->offset, scp->truncPos)) {
+        memset(bufp->datap, 0, cm_data.buf_blockSize);
+        bufp->dataVersion = scp->dataVersion;
+        lock_ReleaseMutex(&scp->mx);
+        cm_ReleaseBIOD(&biod, 0, 0);
+        lock_ObtainMutex(&scp->mx);
+        return 0;
     }
 
     lock_ReleaseMutex(&scp->mx);
@@ -1399,10 +1408,9 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
         require_64bit_ops = 1;
     }
 
-#ifdef DISKCACHE95
-    DPRINTF("cm_GetBuffer: fetching data scpDV=%I64d bufDV=%I64d scp=%x bp=%x dcp=%x\n",
-            scp->dataVersion, bufp->dataVersion, scp, bufp, bufp->dcp);
-#endif /* DISKCACHE95 */
+    osi_Log2(afsd_logp, "cm_GetBuffer: fetching data scp %p bufp %p", scp, bufp);
+    osi_Log3(afsd_logp, "cm_GetBuffer: fetching data scpDV 0x%x scpDVLow 0x%x bufDV 0x%x",
+             scp->dataVersion, scp->bufDataVersionLow, bufp->dataVersion);
 
 #ifdef AFS_FREELANCE_CLIENT
 
index 11ad9a1..75d13b2 100644 (file)
@@ -1149,7 +1149,7 @@ cm_CheckDirOpForSingleChange(cm_dirOp_t * op)
         osi_Log0(afsd_logp, "cm_CheckDirOpForSingleChange succeeded");
     else
         osi_Log3(afsd_logp,
-                 "cm_CheckDirOpForSingleChange failed.  code=0x%x, old dv=%I64d, new dv=%I64d",
+                 "cm_CheckDirOpForSingleChange failed.  code=0x%x, old dv=%d, new dv=%d",
                  code, op->dataVersion, op->scp->dataVersion);
     return rc;
 }
@@ -1270,7 +1270,7 @@ cm_DirOpAddBuffer(cm_dirOp_t * op, cm_buf_t * bufferp)
                          CM_SCACHESYNC_BUFLOCKED);
 
         if (code == 0 && bufferp->dataVersion != op->dataVersion) {
-            osi_Log2(afsd_logp, "cm_DirOpAddBuffer: buffer data version mismatch. buf dv = %I64d. needs %I64d", 
+            osi_Log2(afsd_logp, "cm_DirOpAddBuffer: buffer data version mismatch. buf dv = %d. needs %d", 
                      bufferp->dataVersion, op->dataVersion);
 
             cm_SyncOpDone(op->scp, bufferp,
index 564f5cb..8f158ce 100644 (file)
@@ -1577,7 +1577,7 @@ void cm_MergeStatus(cm_scache_t *dscp,
             if (volp)
                 cm_PutVolume(volp);
         }
-        osi_Log3(afsd_logp, "Bad merge, scp %x, scp dv %I64d, RPC dv %I64d",
+        osi_Log3(afsd_logp, "Bad merge, scp %x, scp dv %d, RPC dv %d",
                   scp, scp->dataVersion, dataVersion);
         /* we have a number of data fetch/store operations running
          * concurrently, and we can tell which one executed last at the
@@ -1722,7 +1722,8 @@ void cm_MergeStatus(cm_scache_t *dscp,
      * the size of the file.
      */
     if (((flags & CM_MERGEFLAG_STOREDATA) && dataVersion - scp->dataVersion > 1) || 
-         (!(flags & CM_MERGEFLAG_STOREDATA) && scp->dataVersion != dataVersion))
+         (!(flags & CM_MERGEFLAG_STOREDATA) && scp->dataVersion != dataVersion) ||
+         scp->bufDataVersionLow == 0)
         scp->bufDataVersionLow = dataVersion;
     
     scp->dataVersion = dataVersion;
index f5bd160..073c464 100644 (file)
@@ -5731,7 +5731,7 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     userp = smb_GetUserFromVCP(vcp, inp);
 
     lock_ObtainMutex(&fidp->mx);
-    if (fidp->flags & SMB_FID_OPENWRITE) {
+    if ((fidp->flags & SMB_FID_OPENWRITE) && smb_AsyncStore != 2) {
        cm_scache_t * scp = fidp->scp;
        cm_HoldSCache(scp);
        lock_ReleaseMutex(&fidp->mx);
@@ -5866,9 +5866,11 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
             CompensateForSmbClientLastWriteTimeBugs(&dosTime);
             smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
         }
-       lock_ReleaseMutex(&fidp->mx);
-        code = cm_FSync(scp, userp, &req);
-       lock_ObtainMutex(&fidp->mx);
+        if (smb_AsyncStore != 2) {
+            lock_ReleaseMutex(&fidp->mx);
+            code = cm_FSync(scp, userp, &req);
+            lock_ObtainMutex(&fidp->mx);
+        }
     }
     else 
         code = 0;
@@ -6262,7 +6264,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
      * based upon cm_chunkSize but we desire cm_chunkSize to be large
      * so that we can read larger amounts of data at a time.
      */
-    if (smb_AsyncStore && 
+    if (smb_AsyncStore == 1 && 
          (thyper.LowPart & ~(cm_data.buf_blockSize-1)) !=
          (offset.LowPart & ~(cm_data.buf_blockSize-1))) {
         /* they're different */
@@ -6341,7 +6343,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
                                                                                ConvertLongToLargeInteger(count)),
                                                                minLength))) {
                     if (count < cm_data.buf_blockSize
-                         && bufferp->dataVersion == -1)
+                         && bufferp->dataVersion == CM_BUF_VERSION_BAD)
                         memset(bufferp->datap, 0,
                                 cm_data.buf_blockSize);
                     bufferp->dataVersion = scp->dataVersion;
@@ -6415,7 +6417,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
     lock_ReleaseMutex(&fidp->mx);
 
     if (code == 0) {
-        if (smb_AsyncStore) {
+        if (smb_AsyncStore > 0) {
             if (doWriteBack) {
                 long code2;