Windows: cm_BPlusDirEnumBulkStatNext index error
authorJeffrey Altman <jaltman@your-file-system.com>
Thu, 7 Mar 2013 14:25:09 +0000 (09:25 -0500)
committerJeffrey Altman <jaltman@your-file-system.com>
Tue, 12 Mar 2013 00:45:52 +0000 (17:45 -0700)
In cm_BPlusDirEnumBulkStatNext the 'next' variable was being set
even if the FileId was not added to the list of objects added to
the cm_bulkStat array.  Delay the assignment to ensure that 'next'
refers to the first element in the array.

In the CM_ERROR_BULKSTAT_FAILURE processing, 'next' is used to
obtain a reference to the cm_scache object that is supposed to
correlate to the [1] entry in the array.  If 'next' == -1, there
is no such entry.  Add a conditional to ensure that 'next' is not
used when its value is -1.

Change-Id: I4ebc49de4bf67eee5a28790cd49f0128891cc202
Reviewed-on: http://gerrit.openafs.org/9450
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Tested-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsd/cm_btree.c

index f360c52..b6a9f0e 100644 (file)
@@ -2753,8 +2753,6 @@ cm_BPlusDirEnumBulkStatNext(cm_direnum_t *enump)
             continue;
         }
 
-        if (next == -1)
-            next = count;
         tscp = cm_FindSCache(&enump->entry[count].fid);
         if (tscp) {
             if (lock_TryWrite(&tscp->rw)) {
@@ -2775,6 +2773,10 @@ cm_BPlusDirEnumBulkStatNext(cm_direnum_t *enump)
             cm_ReleaseSCache(tscp);
         }      /* found entry */
 
+        /* 'next' is the enump entry that is stored in the [bsp->counter == 1] element */
+        if (next == -1)
+            next = count;
+
         bsp->fids[bsp->counter].Volume = enump->entry[count].fid.volume;
         bsp->fids[bsp->counter].Vnode = enump->entry[count].fid.vnode;
         bsp->fids[bsp->counter].Unique = enump->entry[count].fid.unique;
@@ -2792,19 +2794,22 @@ cm_BPlusDirEnumBulkStatNext(cm_direnum_t *enump)
                 *(bs_flagsp[i]) &= ~CM_DIRENUM_FLAG_GOT_STATUS;
             }
 
-            code = cm_GetSCache(&enump->entry[next].fid, NULL, &tscp, userp, &req);
-            if (code == 0) {
-                if (lock_TryWrite(&tscp->rw)) {
-                    code = cm_SyncOp(tscp, NULL, userp, &req, 0,
-                                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-                    lock_ReleaseWrite(&tscp->rw);
+            /* if next == -1, there is no entry to update the status of */
+            if (next != -1) {
+                code = cm_GetSCache(&enump->entry[next].fid, NULL, &tscp, userp, &req);
+                if (code == 0) {
+                    if (lock_TryWrite(&tscp->rw)) {
+                        code = cm_SyncOp(tscp, NULL, userp, &req, 0,
+                                          CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+                        lock_ReleaseWrite(&tscp->rw);
+                        *(bs_errorCodep[1]) = code;
+                        *(bs_flagsp[1]) |= CM_DIRENUM_FLAG_GOT_STATUS;
+                    }
+                    cm_ReleaseSCache(tscp);
+                } else {
                     *(bs_errorCodep[1]) = code;
                     *(bs_flagsp[1]) |= CM_DIRENUM_FLAG_GOT_STATUS;
                 }
-                cm_ReleaseSCache(tscp);
-            } else {
-                *(bs_errorCodep[1]) = code;
-                *(bs_flagsp[1]) |= CM_DIRENUM_FLAG_GOT_STATUS;
             }
             goto done;
         }