windows-fix-volume-refcount-leak-20070121
authorJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 22 Jan 2007 02:16:38 +0000 (02:16 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 22 Jan 2007 02:16:38 +0000 (02:16 +0000)
Plug a volume refcount leak

Add volume data to the "fs memdump" output

Add memmap stat data to the afsd_init.log output at startup and shutdown

src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_memmap.c
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/cm_volume.h
src/WINNT/afsd/fs.c

index 65bd9e4..adaf855 100644 (file)
@@ -728,6 +728,7 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
         cm_ReleaseSCache(scp);
         return code;
     }
+    cm_PutVolume(tvp);
 
     /* Copy the junk out, using cp as a roving pointer. */
     cp = ioctlp->inDatap;
@@ -2703,11 +2704,13 @@ long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
   
     /* dump all interesting data */
     cm_DumpSCache(hLogFile, cookie, 1);
+    cm_DumpVolumes(hLogFile, cookie, 1);
     cm_DumpBufHashTable(hLogFile, cookie, 1);
     smb_DumpVCP(hLogFile, cookie, 1);
 
     CloseHandle(hLogFile);                          
   
+    inValue = 0;       /* success */
     memcpy(ioctlp->outDatap, &inValue, sizeof(long));
     ioctlp->outDatap += sizeof(long);
   
index 900c01b..2433216 100644 (file)
@@ -214,6 +214,21 @@ cm_ShutdownMappedMemory(void)
     cm_config_data_t * config_data_p = (cm_config_data_t *)cm_data.baseAddress;
     int dirty = 0;
 
+    afsi_log("Closing AFS Cache:");
+    afsi_log("  Base Address   = %p", config_data_p);
+    afsi_log("  stats          = %d", cm_data.stats);
+    afsi_log("  chunkSize      = %d", cm_data.chunkSize);
+    afsi_log("  blockSize      = %d", cm_data.blockSize);
+    afsi_log("  bufferSize     = %d", cm_data.bufferSize);
+    afsi_log("  cacheType      = %d", cm_data.cacheType);
+    afsi_log("  currentVolumes = %d", cm_data.currentVolumes);
+    afsi_log("  maxVolumes     = %d", cm_data.maxVolumes);
+    afsi_log("  currentCells   = %d", cm_data.currentCells);
+    afsi_log("  maxCells       = %d", cm_data.maxCells);
+    afsi_log("  hashTableSize  = %d", cm_data.hashTableSize);
+    afsi_log("  currentSCaches = %d", cm_data.currentSCaches);
+    afsi_log("  maxSCaches     = %d", cm_data.maxSCaches);
+
     cm_ShutdownDCache();
     cm_ShutdownSCache();
     cm_ShutdownACLCache();
@@ -393,7 +408,7 @@ cm_ValidateMappedMemory(char * cachePath)
     fprintf(stderr,"  maxVolumes     = %d\n", config_data_p->maxVolumes);
     fprintf(stderr,"  currentCells   = %d\n", config_data_p->currentCells);
     fprintf(stderr,"  maxCells       = %d\n", config_data_p->maxCells);
-    fprintf(stderr,"  hashTableSize  = %d\n", config_data_p->hashTableSize );
+    fprintf(stderr,"  hashTableSize  = %d\n", config_data_p->hashTableSize);
     fprintf(stderr,"  currentSCaches = %d\n", config_data_p->currentSCaches);
     fprintf(stderr,"  maxSCaches     = %d\n", config_data_p->maxSCaches);
     cm_data = *config_data_p;      
@@ -778,9 +793,23 @@ cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD chu
     config_data_p = (cm_config_data_t *) baseAddress;
 
     if (!newFile) {
-        afsi_log("Reusing existing AFS Cache data: Base Address = %lX",baseAddress);
+        afsi_log("Reusing existing AFS Cache data:");
         cm_data = *config_data_p;      
 
+       afsi_log("  Base Address   = %p",baseAddress);
+       afsi_log("  stats          = %d", config_data_p->stats);
+       afsi_log("  chunkSize      = %d", config_data_p->chunkSize);
+       afsi_log("  blockSize      = %d", config_data_p->blockSize);
+       afsi_log("  bufferSize     = %d", config_data_p->bufferSize);
+       afsi_log("  cacheType      = %d", config_data_p->cacheType);
+       afsi_log("  currentVolumes = %d", config_data_p->currentVolumes);
+       afsi_log("  maxVolumes     = %d", config_data_p->maxVolumes);
+       afsi_log("  currentCells   = %d", config_data_p->currentCells);
+       afsi_log("  maxCells       = %d", config_data_p->maxCells);
+       afsi_log("  hashTableSize  = %d", config_data_p->hashTableSize);
+       afsi_log("  currentSCaches = %d", config_data_p->currentSCaches);
+       afsi_log("  maxSCaches     = %d", config_data_p->maxSCaches);
+
         // perform validation of persisted data structures
         // if there is a failure, start from scratch
         if (cm_ValidateCache && !cm_IsCacheValid()) {
index d3595d7..459b2a9 100644 (file)
@@ -543,9 +543,9 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
     long hash;
     cm_scache_t *scp;
     long code;
-    cm_volume_t *volp = 0;
+    cm_volume_t *volp = NULL;
     cm_cell_t *cellp;
-    char* mp = 0;
+    char* mp = NULL;
     int special; // yj: boolean variable to test if file is on root.afs
     int isRoot;
     extern cm_fid_t cm_rootFid;
@@ -629,6 +629,7 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
 #endif
         scp->fid = *fidp;
         scp->volp = cm_data.rootSCachep->volp;
+       cm_GetVolume(scp->volp);        /* grab an additional reference */
         scp->dotdotFid.cell=AFS_FAKE_ROOT_CELL_ID;
         scp->dotdotFid.volume=AFS_FAKE_ROOT_VOL_ID;
         scp->dotdotFid.unique=1;
@@ -712,6 +713,8 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
     if (scp == NULL) {
        osi_Log0(afsd_logp,"cm_GetNewSCache unable to obtain *new* scache entry");
        lock_ReleaseWrite(&cm_scacheLock);
+       if (volp)
+           cm_PutVolume(volp);
        return CM_ERROR_WOULDBLOCK;
     }
     osi_Log2(afsd_logp,"cm_GetNewSCache returns scp 0x%x flags 0x%x", scp, scp->flags);
index 4d1ba03..509fe4f 100644 (file)
@@ -1000,7 +1000,7 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
     long code;
     char *cp;
     char *mpNamep;
-    cm_volume_t *volp;
+    cm_volume_t *volp = NULL;
     cm_cell_t *cellp;
     char mtType;
     cm_fid_t tfid;
@@ -1106,6 +1106,8 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
     }
 
   done:
+    if (volp)
+       cm_PutVolume(volp);
     free(cellNamep);
     free(volNamep);
     return code;
@@ -2112,22 +2114,16 @@ cm_TryBulkStat(cm_scache_t *dscp, osi_hyper_t *offsetp, cm_user_t *userp,
     }  /* while there are still more files to process */
     lock_ObtainMutex(&dscp->mx);
 
-#if 0
-    /* If we did the InlineBulk RPC pull out the return code */
+    /* If we did the InlineBulk RPC pull out the return code and log it */
     if (inlinebulk) {
        if ((&bb.stats[0])->errorCode) {
-           cm_Analyze(NULL /*connp was released by the previous cm_Analyze */, 
-                       userp, reqp, &dscp->fid, &volSync, NULL, NULL, (&bb.stats[0])->errorCode);
-           code = cm_MapRPCError((&bb.stats[0])->errorCode, reqp);
+           osi_Log1(afsd_logp, "cm_TryBulkStat bulk stat error: %d", 
+                    (&bb.stats[0])->errorCode);
        }
-    } else
-#endif 
-    { 
-       code = 0;
     }
 
-    osi_Log1(afsd_logp, "END cm_TryBulkStat code = 0x%x", code);
-    return code;
+    osi_Log0(afsd_logp, "END cm_TryBulkStat");
+    return 0;
 }       
 
 void cm_StatusFromAttr(AFSStoreStatus *statusp, cm_scache_t *scp, cm_attr_t *attrp)
index 7c9959b..9f987df 100644 (file)
@@ -125,7 +125,7 @@ void cm_InitVolume(int newFile, long maxVols)
  */
 #define MULTIHOMED 1
 long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
-       cm_volume_t *volp)
+                    cm_volume_t *volp)
 {
     cm_conn_t *connp;
     int i, j, k;
@@ -359,150 +359,160 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
     return code;
 }
 
+void cm_GetVolume(cm_volume_t *volp)
+{
+    if (volp) {
+       lock_ObtainWrite(&cm_volumeLock);
+       volp->refCount++;
+       lock_ReleaseWrite(&cm_volumeLock);
+    }
+}
+
 long cm_GetVolumeByID(cm_cell_t *cellp, long volumeID, cm_user_t *userp,
        cm_req_t *reqp, cm_volume_t **outVolpp)
 {
-       cm_volume_t *volp;
-        char volNameString[100];
-        long code;
-
-        lock_ObtainWrite(&cm_volumeLock);
-       for(volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
-               if (cellp == volp->cellp &&
-                       ((unsigned) volumeID == volp->rwID ||
-                        (unsigned) volumeID == volp->roID ||
-                         (unsigned) volumeID == volp->bkID))
-                               break;
-        }
+    cm_volume_t *volp;
+    char volNameString[100];
+    long code;
 
-       /* hold the volume if we found it */
+    lock_ObtainWrite(&cm_volumeLock);
+    for(volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
+       if (cellp == volp->cellp &&
+            ((unsigned) volumeID == volp->rwID ||
+              (unsigned) volumeID == volp->roID ||
+              (unsigned) volumeID == volp->bkID))
+           break;
+    }  
+
+    /* hold the volume if we found it */
     if (volp) 
         volp->refCount++;
-        lock_ReleaseWrite(&cm_volumeLock);
+    lock_ReleaseWrite(&cm_volumeLock);
         
-       /* return it held */
-        if (volp) {
-               lock_ObtainMutex(&volp->mx);
+    /* return it held */
+    if (volp) {
+       lock_ObtainMutex(&volp->mx);
         
-               if (volp->flags & CM_VOLUMEFLAG_RESET) {
-                       code = cm_UpdateVolume(cellp, userp, reqp, volp);
-                       if (code == 0) {
-                               volp->flags &= ~CM_VOLUMEFLAG_RESET;
-                       }
-               }
-               else
-                       code = 0;
-               lock_ReleaseMutex(&volp->mx);
-               if (code == 0)
-                       *outVolpp = volp;
-               return code;
-        }
+       if (volp->flags & CM_VOLUMEFLAG_RESET) {
+           code = cm_UpdateVolume(cellp, userp, reqp, volp);
+           if (code == 0) {
+               volp->flags &= ~CM_VOLUMEFLAG_RESET;
+           }
+       }
+       else
+           code = 0;
+       lock_ReleaseMutex(&volp->mx);
+       if (code         == 0)
+           *outVolpp = volp;
+       return code;
+    }
         
-        /* otherwise, we didn't find it so consult the VLDB */
-        sprintf(volNameString, "%u", volumeID);
-        code = cm_GetVolumeByName(cellp, volNameString, userp, reqp,
-                                 0, outVolpp);
-        return code;
+    /* otherwise, we didn't find it so consult the VLDB */
+    sprintf(volNameString, "%u", volumeID);
+    code = cm_GetVolumeByName(cellp, volNameString, userp, reqp,
+                              0, outVolpp);
+    return code;
 }
 
 long cm_GetVolumeByName(struct cm_cell *cellp, char *volumeNamep,
-       struct cm_user *userp, struct cm_req *reqp,
-       long flags, cm_volume_t **outVolpp)
+                        struct cm_user *userp, struct cm_req *reqp,
+                        long flags, cm_volume_t **outVolpp)
 {
-       cm_volume_t *volp;
-        long code;
-        
-       /* initialize this */
-       code = 0;
-
-       lock_ObtainWrite(&cm_volumeLock);
-        for (volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
-            if (cellp == volp->cellp && strcmp(volumeNamep, volp->namep) == 0) {
-                break;
-            }
-        }
+    cm_volume_t *volp;
+    long code;
         
-        /* otherwise, get from VLDB */
-       if (!volp) {
-            if ( cm_data.currentVolumes >= cm_data.maxVolumes ) {
-                for (volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
-                    if ( volp->refCount == 0 ) {
-                        /* There is one we can re-use */
-                        break;
-                    }
-                }
-               if (!volp)
-                   osi_panic("Exceeded Max Volumes", __FILE__, __LINE__);
-            }
+    /* initialize this */
+    code = 0;
 
-            if (volp) {
-                volp->rwID = volp->roID = volp->bkID = 0;
-                volp->dotdotFid.cell = 0;
-                volp->dotdotFid.volume = 0;
-                volp->dotdotFid.unique = 0;
-                volp->dotdotFid.vnode = 0;
-            } else {
-                volp = &cm_data.volumeBaseAddress[cm_data.currentVolumes++];
-                memset(volp, 0, sizeof(cm_volume_t));
-                volp->magic = CM_VOLUME_MAGIC;
-                volp->nextp = cm_data.allVolumesp;
-                cm_data.allVolumesp = volp;
-                lock_InitializeMutex(&volp->mx, "cm_volume_t mutex");
-            }
-            volp->cellp = cellp;
-            strncpy(volp->namep, volumeNamep, VL_MAXNAMELEN);
-            volp->namep[VL_MAXNAMELEN-1] = '\0';
-            volp->refCount = 1;        /* starts off held */
-            volp->flags = CM_VOLUMEFLAG_RESET;
-       }
-        else {
-            volp->refCount++;
+    lock_ObtainWrite(&cm_volumeLock);
+    for (volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
+       if (cellp == volp->cellp && strcmp(volumeNamep, volp->namep) == 0) {
+           break;
        }
+    }  
         
-       /* next should work since no one could have gotten ptr to this structure yet */
-        lock_ReleaseWrite(&cm_volumeLock);
-       lock_ObtainMutex(&volp->mx);
-        
-       if (volp->flags & CM_VOLUMEFLAG_RESET) {
-            code = cm_UpdateVolume(cellp, userp, reqp, volp);
-            if (code == 0)
-                volp->flags &= ~CM_VOLUMEFLAG_RESET;
+    /* otherwise, get from VLDB */
+    if (!volp) {
+       if ( cm_data.currentVolumes >= cm_data.maxVolumes ) {
+           for (volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
+               if ( volp->refCount == 0 ) {
+                   /* There is one we can re-use */
+                   break;
+               }
+           }
+           if (!volp)
+               osi_panic("Exceeded Max Volumes", __FILE__, __LINE__);
+       }       
+
+       if (volp) {
+           volp->rwID = volp->roID = volp->bkID = 0;
+           volp->dotdotFid.cell = 0;
+           volp->dotdotFid.volume = 0;
+           volp->dotdotFid.unique = 0;
+           volp->dotdotFid.vnode = 0;
+       } else {
+           volp = &cm_data.volumeBaseAddress[cm_data.currentVolumes++];
+           memset(volp, 0, sizeof(cm_volume_t));
+           volp->magic = CM_VOLUME_MAGIC;
+           volp->nextp = cm_data.allVolumesp;
+           cm_data.allVolumesp = volp;
+           lock_InitializeMutex(&volp->mx, "cm_volume_t mutex");
        }
+       volp->cellp = cellp;
+       strncpy(volp->namep, volumeNamep, VL_MAXNAMELEN);
+       volp->namep[VL_MAXNAMELEN-1] = '\0';
+       volp->refCount = 1;     /* starts off held */
+       volp->flags = CM_VOLUMEFLAG_RESET;
+    }
+    else {
+       volp->refCount++;
+    }
+
+    /* next should work since no one could have gotten ptr to this structure yet */
+    lock_ReleaseWrite(&cm_volumeLock);
+    lock_ObtainMutex(&volp->mx);
 
+    if (volp->flags & CM_VOLUMEFLAG_RESET) {
+       code = cm_UpdateVolume(cellp, userp, reqp, volp);
        if (code == 0)
-            *outVolpp = volp;
-        lock_ReleaseMutex(&volp->mx);
-        return code;
-}
+           volp->flags &= ~CM_VOLUMEFLAG_RESET;
+    }  
+
+    if (code == 0)
+       *outVolpp = volp;
+    lock_ReleaseMutex(&volp->mx);
+    return code;
+}      
 
 void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp)
 {
-       cm_cell_t *cellp;
-       cm_volume_t *volp;
+    cm_cell_t *cellp;
+    cm_volume_t *volp;
 
-       if (!fidp) return;
+    if (!fidp) return;
 
-       cellp = cm_FindCellByID(fidp->cell);
-       if (!cellp) return;
+    cellp = cm_FindCellByID(fidp->cell);
+    if (!cellp) return;
 
-       /* search for the volume */
-        lock_ObtainWrite(&cm_volumeLock);
-       for(volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
-               if (cellp == volp->cellp &&
-                       (fidp->volume == volp->rwID ||
-                        fidp->volume == volp->roID ||
-                         fidp->volume == volp->bkID))
-                               break;
-        }
-
-       /* hold the volume if we found it */
-        if (volp) volp->refCount++;
-        lock_ReleaseWrite(&cm_volumeLock);
+    /* search for the volume */
+    lock_ObtainWrite(&cm_volumeLock);
+    for(volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
+       if (cellp == volp->cellp &&
+            (fidp->volume == volp->rwID ||
+              fidp->volume == volp->roID ||
+              fidp->volume == volp->bkID))
+           break;
+    }  
+
+    /* hold the volume if we found it */
+    if (volp) 
+       volp->refCount++;
+    lock_ReleaseWrite(&cm_volumeLock);
 
-       /* update it */
-       cm_data.mountRootGen = time(NULL);
-       lock_ObtainMutex(&volp->mx);
-       volp->flags |= CM_VOLUMEFLAG_RESET;
+    /* update it */
+    cm_data.mountRootGen = time(NULL);
+    lock_ObtainMutex(&volp->mx);
+    volp->flags |= CM_VOLUMEFLAG_RESET;
 #ifdef COMMENT
     /* Mark the volume to be updated but don't update it now.
      * This function is called only from within cm_Analyze
@@ -514,13 +524,13 @@ void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp)
      * accessed by Name or ID the UpdateVolume call will
      * occur.
      */
-       code = cm_UpdateVolume(cellp, userp, reqp, volp);
-       if (code == 0)
-               volp->flags &= ~CM_VOLUMEFLAG_RESET;
+    code = cm_UpdateVolume(cellp, userp, reqp, volp);
+    if (code == 0)
+       volp->flags &= ~CM_VOLUMEFLAG_RESET;
 #endif
-       lock_ReleaseMutex(&volp->mx);
+    lock_ReleaseMutex(&volp->mx);
 
-       cm_PutVolume(volp);
+    cm_PutVolume(volp);
 }
 
 /* find the appropriate servers from a volume */
@@ -560,38 +570,38 @@ void cm_PutVolume(cm_volume_t *volp)
  */
 long cm_GetROVolumeID(cm_volume_t *volp)
 {
-       long id;
+    long id;
 
-       lock_ObtainMutex(&volp->mx);
-       if (volp->roID && volp->roServersp)
-               id = volp->roID;
-       else
-               id = volp->rwID;
-       lock_ReleaseMutex(&volp->mx);
+    lock_ObtainMutex(&volp->mx);
+    if (volp->roID && volp->roServersp)
+       id = volp->roID;
+    else
+       id = volp->rwID;
+    lock_ReleaseMutex(&volp->mx);
 
-        return id;
+    return id;
 }
 
 void cm_CheckVolumes(void)
 {
-       cm_volume_t *volp;
+    cm_volume_t *volp;
 
-       cm_data.mountRootGen = time(NULL);
-        lock_ObtainWrite(&cm_volumeLock);
-       for (volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
-               volp->refCount++;
-                lock_ReleaseWrite(&cm_volumeLock);
-                lock_ObtainMutex(&volp->mx);
+    cm_data.mountRootGen = time(NULL);
+    lock_ObtainWrite(&cm_volumeLock);
+    for (volp = cm_data.allVolumesp; volp; volp=volp->nextp) {
+       volp->refCount++;
+       lock_ReleaseWrite(&cm_volumeLock);
+       lock_ObtainMutex(&volp->mx);
 
-                volp->flags |= CM_VOLUMEFLAG_RESET;
+       volp->flags |= CM_VOLUMEFLAG_RESET;
 
-                lock_ReleaseMutex(&volp->mx);
-                lock_ObtainWrite(&cm_volumeLock);
-                osi_assert(volp->refCount-- > 0);
-       }
-        lock_ReleaseWrite(&cm_volumeLock);
+       lock_ReleaseMutex(&volp->mx);
+       lock_ObtainWrite(&cm_volumeLock);
+       osi_assert(volp->refCount-- > 0);
+    }
+    lock_ReleaseWrite(&cm_volumeLock);
 
-       /* We should also refresh cached mount points */
+    /* We should also refresh cached mount points */
 }
 
 /*
@@ -599,29 +609,79 @@ void cm_CheckVolumes(void)
 ** RO list according to the changed rank of server.
 */
 void cm_ChangeRankVolume(cm_server_t       *tsp)
-{
-       int             code;
-       cm_volume_t*    volp;
+{      
+    int                code;
+    cm_volume_t*       volp;
 
-       /* find volumes which might have RO copy on server*/
-       lock_ObtainWrite(&cm_volumeLock);
-       for(volp = cm_data.allVolumesp; volp; volp=volp->nextp)
-       {
-               code = 1 ;      /* assume that list is unchanged */
-               volp->refCount++;
-               lock_ReleaseWrite(&cm_volumeLock);
-               lock_ObtainMutex(&volp->mx);
-
-               if ((tsp->cellp==volp->cellp) && (volp->roServersp))
-                   code =cm_ChangeRankServer(&volp->roServersp, tsp);
-
-               /* this volume list was changed */
-               if ( !code )
-                       cm_RandomizeServer(&volp->roServersp);
-
-               lock_ReleaseMutex(&volp->mx);
-               lock_ObtainWrite(&cm_volumeLock);
-               osi_assert(volp->refCount-- > 0);
-       }
+    /* find volumes which might have RO copy on server*/
+    lock_ObtainWrite(&cm_volumeLock);
+    for(volp = cm_data.allVolumesp; volp; volp=volp->nextp)
+    {
+       code = 1 ;      /* assume that list is unchanged */
+       volp->refCount++;
        lock_ReleaseWrite(&cm_volumeLock);
+       lock_ObtainMutex(&volp->mx);
+
+       if ((tsp->cellp==volp->cellp) && (volp->roServersp))
+           code =cm_ChangeRankServer(&volp->roServersp, tsp);
+
+       /* this volume list was changed */
+       if ( !code )
+           cm_RandomizeServer(&volp->roServersp);
+
+       lock_ReleaseMutex(&volp->mx);
+       lock_ObtainWrite(&cm_volumeLock);
+       osi_assert(volp->refCount-- > 0);
+    }
+    lock_ReleaseWrite(&cm_volumeLock);
+}      
+
+/* dump all scp's that have reference count > 0 to a file. 
+ * cookie is used to identify this batch for easy parsing, 
+ * and it a string provided by a caller 
+ */
+int cm_DumpVolumes(FILE *outputFile, char *cookie, int lock)
+{
+    int zilch;
+    cm_volume_t *volp;
+    char output[1024];
+  
+    if (lock) {
+       lock_ObtainRead(&cm_scacheLock);
+        lock_ObtainRead(&cm_volumeLock);
+    }
+  
+    sprintf(output, "%s - dumping volumes - cm_data.currentVolumes=%d, cm_data.maxVolumes=%d\n", cookie, cm_data.currentVolumes, cm_data.maxVolumes);
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+  
+    for (volp = cm_data.allVolumesp; volp; volp=volp->nextp)
+    {
+        if (volp->refCount != 0)
+        {
+           cm_scache_t *scp;
+           int scprefs = 0;
+
+           for (scp = cm_data.scacheLRULastp; scp; scp = (cm_scache_t *) osi_QPrev(&scp->q)) 
+           {
+               if (scp->volp == volp)
+                   scprefs++;
+           }
+
+            sprintf(output, "%s cell=%s name=%s rwID=%u roID=%u bkID=%u flags=0x%x fid (cell=%d, volume=%d, vnode=%d, unique=%d) refCount=%u scpRefs=%u\n", 
+                    cookie, volp->cellp->name, volp->namep, volp->rwID, volp->roID, volp->bkID, volp->flags, 
+                   volp->dotdotFid.cell, volp->dotdotFid.volume, volp->dotdotFid.vnode, volp->dotdotFid.unique,
+                   volp->refCount, scprefs);
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        }
+    }
+    sprintf(output, "%s - Done dumping volumes.\n", cookie);
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+  
+    if (lock) {
+        lock_ReleaseRead(&cm_volumeLock);
+       lock_ReleaseRead(&cm_scacheLock);
+    }
+    return (0);     
 }
+
+
index 848f4be..30045c3 100644 (file)
@@ -38,13 +38,15 @@ extern void cm_InitVolume(int newFile, long maxVols);
 extern long cm_GetVolumeByName(struct cm_cell *, char *, struct cm_user *,
        struct cm_req *, long, cm_volume_t **);
 
+extern long cm_GetVolumeByID(struct cm_cell *cellp, long volumeID,
+       cm_user_t *userp, cm_req_t *reqp, cm_volume_t **outVolpp);
+
+extern void cm_GetVolume(cm_volume_t *volp);
+
 extern void cm_PutVolume(cm_volume_t *volp);
 
 extern long cm_GetROVolumeID(cm_volume_t *volp);
 
-extern long cm_GetVolumeByID(struct cm_cell *cellp, long volumeID,
-       cm_user_t *userp, cm_req_t *reqp, cm_volume_t **outVolpp);
-
 extern void cm_ForceUpdateVolume(struct cm_fid *fidp, cm_user_t *userp,
        cm_req_t *reqp);
 
@@ -57,4 +59,6 @@ extern void cm_CheckVolumes(void);
 extern long cm_ValidateVolume(void);
 
 extern long cm_ShutdownVolume(void);
+
+extern int cm_DumpVolumes(FILE *outputFile, char *cookie, int lock);
 #endif /*  __CM_VOLUME_H_ENV__ */
index 0259749..f18a322 100644 (file)
@@ -3826,7 +3826,7 @@ MemDumpCmd(struct cmd_syndesc *asp, char *arock)
         return code;
     }
 
-    if (outValue) { 
+    if (!outValue) { 
         printf("AFS memdump created.\n");
         return 0;
     } else {