Windows: Direct IO Support for Service
[openafs.git] / src / WINNT / afsd / cm_dcache.c
index 040671a..5ced48f 100644 (file)
@@ -34,11 +34,6 @@ extern osi_mutex_t cm_Freelance_Lock;
 
 #define USE_RX_IOVEC 1
 
-/* we can access connp->serverp without holding a lock because that
-   never changes since the connection is made. */
-#define SERVERHAS64BIT(connp) (!((connp)->serverp->flags & CM_SERVERFLAG_NO64BIT))
-#define SET_SERVERHASNO64BIT(connp) (cm_SetServerNo64Bit((connp)->serverp, TRUE))
-
 /* functions called back from the buffer package when reading or writing data,
  * or when holding or releasing a vnode pointer.
  */
@@ -375,7 +370,7 @@ long cm_BufWrite(void *vscp, osi_hyper_t *offsetp, long length, long flags,
             osi_Log2(afsd_logp, "rx_EndCall converted 0x%x to 0x%x", code, code1);
             code = code1;
         }
-    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 1, &volSync, NULL, NULL, code));
+    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 1, &outStatus, &volSync, NULL, NULL, code));
 
     code = cm_MapRPCError(code, reqp);
 
@@ -418,7 +413,7 @@ long cm_BufWrite(void *vscp, osi_hyper_t *offsetp, long length, long flags,
         if (LargeIntegerGreaterThanOrEqualTo(t, scp->length))
             _InterlockedAnd(&scp->mask, ~CM_SCACHEMASK_LENGTH);
 
-        cm_MergeStatus(NULL, scp, &outStatus, &volSync, userp, reqp, CM_MERGEFLAG_STOREDATA);
+        code = cm_MergeStatus(NULL, scp, &outStatus, &volSync, userp, reqp, CM_MERGEFLAG_STOREDATA);
     } else {
         InterlockedDecrement(&scp->activeRPCs);
         if (code == CM_ERROR_SPACE)
@@ -564,7 +559,7 @@ long cm_StoreMini(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
         /* prefer StoreData error over rx_EndCall error */
         if (code == 0 && code1 != 0)
             code = code1;
-    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 1, &volSync, NULL, NULL, code));
+    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 1, &outStatus, &volSync, NULL, NULL, code));
     code = cm_MapRPCError(code, reqp);
 
     /* now, clean up our state */
@@ -585,7 +580,7 @@ long cm_StoreMini(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
 
         if (LargeIntegerGreaterThanOrEqualTo(t, scp->length))
             _InterlockedAnd(&scp->mask, ~CM_SCACHEMASK_LENGTH);
-        cm_MergeStatus(NULL, scp, &outStatus, &volSync, userp, reqp, CM_MERGEFLAG_STOREDATA);
+        code = cm_MergeStatus(NULL, scp, &outStatus, &volSync, userp, reqp, CM_MERGEFLAG_STOREDATA);
     } else {
         InterlockedDecrement(&scp->activeRPCs);
     }
@@ -778,29 +773,30 @@ cm_CheckFetchRange(cm_scache_t *scp, osi_hyper_t *startBasep, osi_hyper_t *lengt
 }
 
 afs_int32
-cm_BkgStore(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
-           cm_user_t *userp, cm_req_t *reqp)
+cm_BkgStore(cm_scache_t *scp, void *rockp, cm_user_t *userp, cm_req_t *reqp)
 {
     osi_hyper_t toffset;
-    long length;
+    afs_uint32 length;
     long code = 0;
     afs_uint32 req_flags = reqp->flags;
 
+    toffset = ((rock_BkgStore_t *)rockp)->offset;
+    length = ((rock_BkgStore_t *)rockp)->length;
+
     if (scp->flags & CM_SCACHEFLAG_DELETED) {
-       osi_Log4(afsd_logp, "Skipping BKG store - Deleted scp 0x%p, offset 0x%x:%08x, length 0x%x", scp, p2, p1, p3);
+       osi_Log4(afsd_logp, "Skipping BKG store - Deleted scp 0x%p, offset 0x%x:%08x, length 0x%x",
+                 scp, toffset.HighPart, toffset.LowPart, length);
     } else {
        /* Retries will be performed by the BkgDaemon thread if appropriate */
        reqp->flags |= CM_REQ_NORETRY;
 
-       toffset.LowPart = p1;
-       toffset.HighPart = p2;
-       length = p3;
-
-       osi_Log4(afsd_logp, "Starting BKG store scp 0x%p, offset 0x%x:%08x, length 0x%x", scp, p2, p1, p3);
+       osi_Log4(afsd_logp, "Starting BKG store scp 0x%p, offset 0x%x:%08x, length 0x%x",
+                 scp, toffset.HighPart, toffset.LowPart, length);
 
        code = cm_BufWrite(scp, &toffset, length, /* flags */ 0, userp, reqp);
 
-       osi_Log4(afsd_logp, "Finished BKG store scp 0x%p, offset 0x%x:%08x, code 0x%x", scp, p2, p1, code);
+       osi_Log5(afsd_logp, "Finished BKG store scp 0x%p, offset 0x%x:%08x, length 0x%x, code 0x%x",
+                 scp, toffset.HighPart, toffset.LowPart, length, code);
 
         reqp->flags = req_flags;
     }
@@ -846,8 +842,7 @@ void cm_ClearPrefetchFlag(long code, cm_scache_t *scp, osi_hyper_t *base, osi_hy
 /* do the prefetch.  if the prefetch fails, return 0 (success)
  * because there is no harm done.  */
 afs_int32
-cm_BkgPrefetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
-              cm_user_t *userp, cm_req_t *reqp)
+cm_BkgPrefetch(cm_scache_t *scp, void *rockp, cm_user_t *userp, cm_req_t *reqp)
 {
     osi_hyper_t length;
     osi_hyper_t base;
@@ -867,15 +862,13 @@ cm_BkgPrefetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, af
     fetched.LowPart = 0;
     fetched.HighPart = 0;
     tblocksize = ConvertLongToLargeInteger(cm_data.buf_blockSize);
-    base.LowPart = p1;
-    base.HighPart = p2;
-    length.LowPart = p3;
-    length.HighPart = p4;
+    base = ((rock_BkgFetch_t *)rockp)->base;
+    length = ((rock_BkgFetch_t *)rockp)->length;
 
     end = LargeIntegerAdd(base, length);
 
     osi_Log5(afsd_logp, "Starting BKG prefetch scp 0x%p offset 0x%x:%x length 0x%x:%x",
-             scp, p2, p1, p4, p3);
+             scp, base.HighPart, base.LowPart, length.HighPart, length.LowPart);
 
     for ( code = 0, offset = base;
           code == 0 && LargeIntegerLessThan(offset, end);
@@ -886,7 +879,7 @@ cm_BkgPrefetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, af
             rxheld = 0;
         }
 
-        code = buf_Get(scp, &offset, reqp, &bp);
+        code = buf_Get(scp, &offset, reqp, 0, &bp);
         if (code)
             break;
 
@@ -921,7 +914,7 @@ cm_BkgPrefetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, af
                          scp, &base, &fetched);
 
     /* wakeup anyone who is waiting */
-    if (scp->flags & CM_SCACHEFLAG_WAITING) {
+    if (!osi_QIsEmpty(&scp->waitQueueH)) {
         osi_Log1(afsd_logp, "CM BkgPrefetch Waking scp 0x%p", scp);
         osi_Wakeup((LONG_PTR) &scp->flags);
     }
@@ -947,6 +940,7 @@ void cm_ConsiderPrefetch(cm_scache_t *scp, osi_hyper_t *offsetp, afs_uint32 coun
     osi_hyper_t readLength;
     osi_hyper_t readEnd;
     osi_hyper_t tblocksize;            /* a long long temp variable */
+    rock_BkgFetch_t *rockp;
 
     tblocksize = ConvertLongToLargeInteger(cm_data.buf_blockSize);
 
@@ -988,10 +982,16 @@ void cm_ConsiderPrefetch(cm_scache_t *scp, osi_hyper_t *offsetp, afs_uint32 coun
     osi_Log2(afsd_logp, "BKG Prefetch request scp 0x%p, base 0x%x",
              scp, realBase.LowPart);
 
-    cm_QueueBKGRequest(scp, cm_BkgPrefetch,
-                       realBase.LowPart, realBase.HighPart,
-                       readLength.LowPart, readLength.HighPart,
-                       userp, reqp);
+    rockp = malloc(sizeof(*rockp));
+    if (rockp == NULL) {
+        return;        /* can't proceed without a rock */
+    }
+
+    rockp->base = realBase;
+    rockp->length = readLength;
+
+    /* cm_BkgDaemon frees the rock */
+    cm_QueueBKGRequest(scp, cm_BkgPrefetch, rockp, userp, reqp);
 }
 
 /* scp must be locked; temporarily unlocked during processing.
@@ -1031,7 +1031,8 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
 
     /* reserve a chunk's worth of buffers */
     lock_ReleaseWrite(&scp->rw);
-    buf_ReserveBuffers(cm_chunkSize / cm_data.buf_blockSize);
+    biop->reserved = (cm_chunkSize / cm_data.buf_blockSize);
+    buf_ReserveBuffers(biop->reserved);
     lock_ObtainWrite(&scp->rw);
 
     bufp = NULL;
@@ -1079,8 +1080,6 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
         }
     }
 
-    biop->reserved = 1;
-
     /* if we get here, if bufp is null, we didn't find any dirty buffers
      * that weren't already being stored back, so we just quit now.
      */
@@ -1268,7 +1267,7 @@ long cm_SetupFetchBIOD(cm_scache_t *scp, osi_hyper_t *offsetp,
     osi_hyper_t fileSize;              /* the # of bytes in the file */
     osi_queueData_t *heldBufListp;     /* we hold all buffers in this list */
     osi_queueData_t *heldBufListEndp;  /* first one */
-    int reserving;
+    afs_uint64 reserving;
 
     tblocksize = ConvertLongToLargeInteger(cm_data.buf_blockSize);
 
@@ -1325,7 +1324,7 @@ long cm_SetupFetchBIOD(cm_scache_t *scp, osi_hyper_t *offsetp,
         if (LargeIntegerGreaterThanOrEqualTo(pageBase, fileSize))
             break;
 
-        code = buf_Get(scp, &pageBase, reqp, &tbp);
+        code = buf_Get(scp, &pageBase, reqp, 0, &tbp);
         if (code) {
             lock_ObtainWrite(&scp->rw);
             cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
@@ -1490,7 +1489,7 @@ void cm_ReleaseBIOD(cm_bulkIO_t *biop, int isStore, long code, int scp_locked)
 
     /* Give back reserved buffers */
     if (biop->reserved)
-        buf_UnreserveBuffers(cm_chunkSize / cm_data.buf_blockSize);
+        buf_UnreserveBuffers(biop->reserved);
 
     if (isStore)
         flags = CM_SCACHESYNC_STOREDATA;
@@ -1534,12 +1533,14 @@ void cm_ReleaseBIOD(cm_bulkIO_t *biop, int isStore, long code, int scp_locked)
                     case CM_ERROR_TOOBIG:
                     case CM_ERROR_READONLY:
                     case CM_ERROR_NOSUCHPATH:
+                    case EIO:
+                    case CM_ERROR_INVAL_NET_RESP:
+                    case CM_ERROR_UNKNOWN:
                         /*
                          * Apply the fatal error to this buffer.
                          */
                         _InterlockedAnd(&bufp->flags, ~CM_BUF_DIRTY);
                         _InterlockedOr(&bufp->flags, CM_BUF_ERROR);
-                        bufp->dirty_offset = 0;
                         bufp->dirty_length = 0;
                         bufp->error = code;
                         bufp->dataVersion = CM_BUF_VERSION_BAD;
@@ -1651,7 +1652,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
     afs_uint32 nbytes;                 /* bytes in transfer */
     afs_uint32 nbytes_hi = 0;            /* high-order 32 bits of bytes in transfer */
     afs_uint64 length_found = 0;
-    long rbytes;                       /* bytes in rx_Read call */
+    long rxbytes;                      /* bytes in rx_Read call */
     long temp;
     AFSFetchStatus afsStatus;
     AFSCallBack callback;
@@ -1998,9 +1999,9 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
 
                 iov = 0;
                 iov_offset = 0;
-                rbytes = temp;
+                rxbytes = temp;
 
-                while (rbytes > 0) {
+                while (rxbytes > 0) {
                     afs_int32 len;
 
                     osi_assertx(bufferp != NULL, "null cm_buf_t");
@@ -2009,7 +2010,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
                     memcpy(bufferp + buffer_offset, tiov[iov].iov_base + iov_offset, len);
                     iov_offset += len;
                     buffer_offset += len;
-                    rbytes -= len;
+                    rxbytes -= len;
 
                     if (iov_offset == tiov[iov].iov_len) {
                         iov++;
@@ -2024,7 +2025,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
                         */
                         _InterlockedOr(&tbufp->cmFlags, CM_BUF_CMFULLYFETCHED);
                         lock_ObtainWrite(&scp->rw);
-                        if (scp->flags & CM_SCACHEFLAG_WAITING) {
+                        if (!osi_QIsEmpty(&scp->waitQueueH)) {
                             osi_Log1(afsd_logp, "CM GetBuffer Waking scp 0x%p", scp);
                             osi_Wakeup((LONG_PTR) &scp->flags);
                         }
@@ -2055,10 +2056,10 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
                  */
                 osi_assertx(bufferp != NULL, "null cm_buf_t");
 
-                /* read rbytes of data */
-                rbytes = (afs_uint32)(length_found > cm_data.buf_blockSize ? cm_data.buf_blockSize : length_found);
-                temp = rx_Read(rxcallp, bufferp, rbytes);
-                if (temp < rbytes) {
+                /* read rxbytes of data */
+                rxbytes = (afs_uint32)(length_found > cm_data.buf_blockSize ? cm_data.buf_blockSize : length_found);
+                temp = rx_Read(rxcallp, bufferp, rxbytes);
+                if (temp < rxbytes) {
                     /*
                      * If the file server returned (filesize - offset),
                      * then the first rx_Read will return zero octets of data.
@@ -2083,7 +2084,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
                  */
                 _InterlockedOr(&tbufp->cmFlags, CM_BUF_CMFULLYFETCHED);
                 lock_ObtainWrite(&scp->rw);
-                if (scp->flags & CM_SCACHEFLAG_WAITING) {
+                if (!osi_QIsEmpty(&scp->waitQueueH)) {
                     osi_Log1(afsd_logp, "CM GetBuffer Waking scp 0x%p", scp);
                     osi_Wakeup((LONG_PTR) &scp->flags);
                 }
@@ -2118,26 +2119,26 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
              * all of the rest of the pages.
              */
 #ifdef USE_RX_IOVEC
-            rbytes = cm_data.buf_blockSize - buffer_offset;
+            rxbytes = cm_data.buf_blockSize - buffer_offset;
             bufferp = tbufp->datap + buffer_offset;
 #else /* USE_RX_IOVEC */
             /* bytes fetched */
            osi_assertx((bufferp - tbufp->datap) < LONG_MAX, "data >= LONG_MAX");
-            rbytes = (long) (bufferp - tbufp->datap);
+            rxbytes = (long) (bufferp - tbufp->datap);
 
             /* bytes left to zero */
-            rbytes = cm_data.buf_blockSize - rbytes;
+            rxbytes = cm_data.buf_blockSize - rxbytes;
 #endif /* USE_RX_IOVEC */
             while(qdp) {
-                if (rbytes != 0)
-                    memset(bufferp, 0, rbytes);
+                if (rxbytes != 0)
+                    memset(bufferp, 0, rxbytes);
                 qdp = (osi_queueData_t *) osi_QPrev(&qdp->q);
                 if (qdp == NULL)
                     break;
                 tbufp = osi_GetQData(qdp);
                 bufferp = tbufp->datap;
                 /* bytes to clear in this page */
-                rbytes = cm_data.buf_blockSize;
+                rxbytes = cm_data.buf_blockSize;
             }
         }
 
@@ -2173,7 +2174,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
             code = code1;
         osi_Log0(afsd_logp, "CALL FetchData DONE");
 
-    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 0, &volSync, NULL, NULL, code));
+    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 0, &afsStatus, &volSync, NULL, NULL, code));
 
   fetchingcompleted:
     code = cm_MapRPCError(code, reqp);
@@ -2204,7 +2205,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
     }
 
     if (code == 0)
-        cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, CM_MERGEFLAG_FETCHDATA);
+        code = cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, CM_MERGEFLAG_FETCHDATA);
     else
         InterlockedDecrement(&scp->activeRPCs);
 
@@ -2229,7 +2230,7 @@ long cm_GetData(cm_scache_t *scp, osi_hyper_t *offsetp, char *datap, int data_le
     afs_uint64 length_found = 0;
     char *bufferp = datap;
     afs_uint32 buffer_offset = 0;
-    long rbytes;                       /* bytes in rx_Read call */
+    long rxbytes;                      /* bytes in rx_Read call */
     long temp;
     AFSFetchStatus afsStatus;
     AFSCallBack callback;
@@ -2451,9 +2452,9 @@ long cm_GetData(cm_scache_t *scp, osi_hyper_t *offsetp, char *datap, int data_le
 
                 iov = 0;
                 iov_offset = 0;
-                rbytes = temp;
+                rxbytes = temp;
 
-                while (rbytes > 0) {
+                while (rxbytes > 0) {
                     afs_int32 len;
 
                     osi_assertx(bufferp != NULL, "null cm_buf_t");
@@ -2462,7 +2463,7 @@ long cm_GetData(cm_scache_t *scp, osi_hyper_t *offsetp, char *datap, int data_le
                     memcpy(bufferp + buffer_offset, tiov[iov].iov_base + iov_offset, len);
                     iov_offset += len;
                     buffer_offset += len;
-                    rbytes -= len;
+                    rxbytes -= len;
 
                     if (iov_offset == tiov[iov].iov_len) {
                         iov++;
@@ -2478,10 +2479,10 @@ long cm_GetData(cm_scache_t *scp, osi_hyper_t *offsetp, char *datap, int data_le
                  */
                 osi_assertx(bufferp != NULL, "null cm_buf_t");
 
-                /* read rbytes of data */
-                rbytes = (afs_uint32)(length_found > data_length ? data_length : length_found);
-                temp = rx_Read(rxcallp, bufferp, rbytes);
-                if (temp < rbytes) {
+                /* read rxbytes of data */
+                rxbytes = (afs_uint32)(length_found > data_length ? data_length : length_found);
+                temp = rx_Read(rxcallp, bufferp, rxbytes);
+                if (temp < rxbytes) {
                     /*
                      * If the file server returned (filesize - offset),
                      * then the first rx_Read will return zero octets of data.
@@ -2511,18 +2512,18 @@ long cm_GetData(cm_scache_t *scp, osi_hyper_t *offsetp, char *datap, int data_le
              * all of the rest of the pages.
              */
 #ifdef USE_RX_IOVEC
-            rbytes = data_length - buffer_offset;
+            rxbytes = data_length - buffer_offset;
             bufferp = datap + buffer_offset;
 #else /* USE_RX_IOVEC */
             /* bytes fetched */
            osi_assertx((bufferp - datap) < LONG_MAX, "data >= LONG_MAX");
-            rbytes = (long) (bufferp - datap);
+            rxbytes = (long) (bufferp - datap);
 
             /* bytes left to zero */
-            rbytes = data_length - rbytes;
+            rxbytes = data_length - rxbytes;
 #endif /* USE_RX_IOVEC */
-            if (rbytes != 0)
-                memset(bufferp, 0, rbytes);
+            if (rxbytes != 0)
+                memset(bufferp, 0, rxbytes);
         }
 
         if (code == 0) {
@@ -2557,7 +2558,7 @@ long cm_GetData(cm_scache_t *scp, osi_hyper_t *offsetp, char *datap, int data_le
             code = code1;
         osi_Log0(afsd_logp, "CALL FetchData DONE");
 
-    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 0, &volSync, NULL, NULL, code));
+    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 0, &afsStatus, &volSync, NULL, NULL, code));
 
   fetchingcompleted:
     code = cm_MapRPCError(code, reqp);
@@ -2566,7 +2567,7 @@ long cm_GetData(cm_scache_t *scp, osi_hyper_t *offsetp, char *datap, int data_le
         lock_ObtainWrite(&scp->rw);
 
     if (code == 0)
-        cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, CM_MERGEFLAG_FETCHDATA);
+        code = cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, CM_MERGEFLAG_FETCHDATA);
     else
         InterlockedDecrement(&scp->activeRPCs);
 
@@ -2586,7 +2587,7 @@ cm_VerifyStoreData(cm_bulkIO_t *biod, cm_scache_t *savedScp)
     afs_uint32 nbytes;                 /* bytes in transfer */
     afs_uint32 nbytes_hi = 0;           /* high-order 32 bits of bytes in transfer */
     afs_uint64 length_found = 0;
-    long rbytes;                       /* bytes in rx_Read call */
+    long rxbytes;                      /* bytes in rx_Read call */
     long temp;
     AFSFetchStatus afsStatus;
     AFSCallBack callback;
@@ -2723,10 +2724,10 @@ cm_VerifyStoreData(cm_bulkIO_t *biod, cm_scache_t *savedScp)
                  */
                 osi_assertx(bufferp != NULL, "null cm_buf_t");
 
-                /* read rbytes of data */
-                rbytes = (afs_uint32)(length_found > biod->length ? biod->length : length_found);
-                temp = rx_Read(rxcallp, bufferp, rbytes);
-                if (temp < rbytes) {
+                /* read rxbytes of data */
+                rxbytes = (afs_uint32)(length_found > biod->length ? biod->length : length_found);
+                temp = rx_Read(rxcallp, bufferp, rxbytes);
+                if (temp < rxbytes) {
                     /*
                      * If the file server returned (filesize - offset),
                      * then the first rx_Read will return zero octets of data.
@@ -2781,7 +2782,7 @@ cm_VerifyStoreData(cm_bulkIO_t *biod, cm_scache_t *savedScp)
             code = code1;
         osi_Log0(afsd_logp, "CALL FetchData DONE");
 
-    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 0, &volSync, NULL, NULL, code));
+    } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 0, &afsStatus, &volSync, NULL, NULL, code));
 
   fetchingcompleted:
     code = cm_MapRPCError(code, reqp);
@@ -2790,7 +2791,7 @@ cm_VerifyStoreData(cm_bulkIO_t *biod, cm_scache_t *savedScp)
         lock_ObtainWrite(&scp->rw);
 
     if (code == 0)
-        cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, CM_MERGEFLAG_FETCHDATA);
+        code = cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, CM_MERGEFLAG_FETCHDATA);
     else
         InterlockedDecrement(&scp->activeRPCs);
 
@@ -2817,6 +2818,8 @@ cm_VerifyStoreData(cm_bulkIO_t *biod, cm_scache_t *savedScp)
                     buf_offset = 0;
                 }
                 cmp_length =  cm_data.buf_blockSize - buf_offset;
+                if (cmp_length > biod->length - bytes_compared)
+                    cmp_length = biod->length - bytes_compared;
 
                 osi_assertx(qdp != NULL, "null osi_queueData_t");
                 bufp = osi_GetQData(qdp);