]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
DEVEL15-windows-volume-20080414
authorJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 14 Apr 2008 23:44:03 +0000 (23:44 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 14 Apr 2008 23:44:03 +0000 (23:44 +0000)
LICENSE MIT

1. Convert cm_volume_t mutex to a rwlock (rw).

2. Don't hold cm_volume_t lock across RPCs

3. Add CM_VOLUMEFLAG_UPDATING_VL flag to prevent multiple threads
   from performing volume update calls at the same time on the same
   volume set.

4. Convert the .rw, .ro, and .bk cm_vol_state_t members of cm_volume_t
   to an array of cm_vol_state_t members indexed using the pre-existing
   RWVOL, ROVOL and BACKVOL preprocessor symbols.  This will permit
   consolidation of code and make it easier to add new volume types
   to the volume set in the future.

(cherry picked from commit 4440b9a61247a0da020042b4262695f0ef7d35de)

src/WINNT/afsd/cm.h
src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_performance.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

index 14e1c91bad4256cdebc3af208f80b35b9a7e9f92..5101f4cd4e248beaf1063ee0af11c9e67ef66095 100644 (file)
@@ -94,6 +94,7 @@
 #define CM_ERROR_LOCK_NOT_GRANTED       (CM_ERROR_BASE+59)
 
 /* Used by cm_FollowMountPoint and cm_FindVolumeByName */
+/* And as an index in cm_volume_t */
 #define RWVOL  0
 #define ROVOL  1
 #define BACKVOL        2
index f1489f9080e94a7b482e52cb648e74041c1f2514..60dd6a05fec4fbf3f4c963ad6b46aa9168b3acdc 100644 (file)
@@ -1807,13 +1807,7 @@ long cm_CBServersUp(cm_scache_t *scp, time_t * downTime)
     if (!volp)
         return 1;
 
-    if (volp->rw.ID == volID) {
-        statep = &volp->rw;
-    } else if (volp->ro.ID == volID) {
-        statep = &volp->ro;
-    } else if (volp->bk.ID == volID) {
-        statep = &volp->bk;
-    }
+    statep = cm_VolumeStateByID(volp, volID);
     cm_PutVolume(volp);
     if (statep->state == vl_online)
         return 1;
index 8c292b04675c026429698aaf08d5dc5d6499175d..baca5e3857ce434942eab71fdca3fd0d74664542 100644 (file)
@@ -288,13 +288,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                                     CM_GETVOL_FLAG_NO_LRU_UPDATE, 
                                     &volp);
             if (code == 0) {
-                if (fidp->volume == volp->rw.ID)
-                    statep = &volp->rw;
-                else if (fidp->volume == volp->ro.ID)
-                    statep = &volp->ro;
-                else if (fidp->volume == volp->bk.ID)
-                    statep = &volp->bk;
-
+                statep = cm_VolumeStateByID(volp, fidp->volume);
                 if (statep->state != vl_offline && statep->state != vl_unknown) {
                     retry = 1;
                 } else {
@@ -320,13 +314,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                                         CM_GETVOL_FLAG_NO_LRU_UPDATE, 
                                         &volp);
                 if (code == 0) {
-                    if (fidp->volume == volp->rw.ID)
-                        statep = &volp->rw;
-                    else if (fidp->volume == volp->ro.ID)
-                        statep = &volp->ro;
-                    else if (fidp->volume == volp->bk.ID)
-                        statep = &volp->bk;
-
+                    statep = cm_VolumeStateByID(volp, fidp->volume);
                     if (statep->state != vl_offline && 
                         statep->state != vl_busy &&
                         statep->state != vl_unknown) {
@@ -389,14 +377,8 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                     code = cm_FindVolumeByID(cellp, fidp->volume, userp, reqp, 
                                              CM_GETVOL_FLAG_NO_LRU_UPDATE, 
                                              &volp);
-                    if (code == 0) {
-                        if (fidp->volume == volp->rw.ID)
-                            statep = &volp->rw;
-                        else if (fidp->volume == volp->ro.ID)
-                            statep = &volp->ro;
-                        else if (fidp->volume == volp->bk.ID)
-                            statep = &volp->bk;
-                    }
+                    if (code == 0)
+                        statep = cm_VolumeStateByID(volp, fidp->volume);
                 }
                 break;
             }
@@ -500,14 +482,8 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                     code = cm_FindVolumeByID(cellp, fidp->volume, userp, reqp, 
                                              CM_GETVOL_FLAG_NO_LRU_UPDATE, 
                                              &volp);
-                    if (code == 0) {
-                        if (fidp->volume == volp->rw.ID)
-                            statep = &volp->rw;
-                        else if (fidp->volume == volp->ro.ID)
-                            statep = &volp->ro;
-                        else if (fidp->volume == volp->bk.ID)
-                            statep = &volp->bk;
-                    }
+                    if (code == 0)
+                        cm_VolumeStateByID(volp, fidp->volume);
                 }   
             }
         }   
@@ -540,7 +516,6 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                if (scp->fileType != CM_SCACHETYPE_DIRECTORY)
                    pscp = cm_FindSCacheParent(scp);
 
-
                lock_ObtainWrite(&scp->rw);
                lock_ObtainWrite(&cm_scacheLock);
                cm_RemoveSCacheFromHashTable(scp);
index 0c625468774bffcb4383585577249b7a901fd553..72ce2db93796b6ae325a66f2b74d35004204c45b 100644 (file)
@@ -1240,7 +1240,6 @@ long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
        
         cp = ioctlp->outDatap;
         
-        lock_ObtainMutex(&tvp->mx);
         tsrpp = cm_GetVolServers(tvp, volume);
         lock_ObtainRead(&cm_serverLock);
         for (current = *tsrpp; current; current = current->next) {
@@ -1250,7 +1249,6 @@ long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
         }
         lock_ReleaseRead(&cm_serverLock);
         cm_FreeServerList(tsrpp, 0);
-        lock_ReleaseMutex(&tvp->mx);
 
         /* still room for terminating NULL, add it on */
         volume = 0;    /* reuse vbl */
@@ -3174,13 +3172,7 @@ long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
         if (code) 
             return code;
        
-        if (volume == tvp->rw.ID)
-            statep = &tvp->rw;
-        else if (volume == tvp->ro.ID)
-            statep = &tvp->ro;
-        else
-            statep = &tvp->bk;
-
+        statep = cm_VolumeStateByID(tvp, volume);
         switch (statep->state) {
         case vl_online:
         case vl_unknown:
@@ -3275,23 +3267,10 @@ long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp)
     if (code)
         return code;
        
-    if (testp->fid.volume) {
-        if (testp->fid.volume == volp->rw.ID)
-            statep = &volp->rw;
-        else if (testp->fid.volume == volp->ro.ID)
-            statep = &volp->ro;
-        else
-            statep = &volp->bk;
-    } else {
-        len = strlen(testp->volname);
-
-        if (stricmp(".readonly", &testp->volname[len-9]) == 0)
-            statep = &volp->ro;
-        else if (stricmp(".backup", &testp->volname[len-7]) == 0)
-            statep = &volp->bk;
-        else 
-            statep = &volp->rw;
-    }
+    if (testp->fid.volume)
+        statep = cm_VolumeStateByID(volp, testp->fid.volume);
+    else
+        statep = cm_VolumeStateByName(volp, testp->volname);
 
     if (statep) {
         statep->state = testp->state;
index fd112703e65efa2bd7bdf48fa5cbf88f25f4c403..5ecd84ea725369d5d8989f60a2d169eaa3997ae4 100644 (file)
@@ -171,8 +171,8 @@ void cm_PerformanceTuningInit(void)
 
     lock_ObtainRead(&cm_volumeLock);
     for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
-        if (volp->rw.ID) {
-            cm_SetFid(&fid, volp->cellp->cellID, volp->rw.ID, 1, 1);
+        if (volp->vol[RWVOL].ID) {
+            cm_SetFid(&fid, volp->cellp->cellID, volp->vol[RWVOL].ID, 1, 1);
             hash = fid.hash % fidStatsHashTableSize;
 
             for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
@@ -189,8 +189,8 @@ void cm_PerformanceTuningInit(void)
                 cm_PerformanceInsertToHashTable(statp);
             }
         }
-        if (volp->ro.ID) {
-            cm_SetFid(&fid, volp->cellp->cellID, volp->ro.ID, 1, 1);
+        if (volp->vol[ROVOL].ID) {
+            cm_SetFid(&fid, volp->cellp->cellID, volp->vol[ROVOL].ID, 1, 1);
             hash = fid.hash % fidStatsHashTableSize;
 
             for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
@@ -207,8 +207,8 @@ void cm_PerformanceTuningInit(void)
                 cm_PerformanceInsertToHashTable(statp);
             }
         }
-        if (volp->bk.ID) {
-            cm_SetFid(&fid, volp->cellp->cellID, volp->bk.ID, 1, 1);
+        if (volp->vol[BACKVOL].ID) {
+            cm_SetFid(&fid, volp->cellp->cellID, volp->vol[BACKVOL].ID, 1, 1);
             hash = fid.hash % fidStatsHashTableSize;
 
             for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
@@ -311,8 +311,8 @@ void cm_PerformanceTuningCheck(void)
 
     lock_ObtainRead(&cm_volumeLock);
     for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
-        if (volp->rw.ID) {
-            cm_SetFid(&fid, volp->cellp->cellID, volp->rw.ID, 1, 1);
+        if (volp->vol[RWVOL].ID) {
+            cm_SetFid(&fid, volp->cellp->cellID, volp->vol[RWVOL].ID, 1, 1);
             hash = fid.hash % fidStatsHashTableSize;
 
             for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
@@ -329,8 +329,8 @@ void cm_PerformanceTuningCheck(void)
                 cm_PerformanceInsertToHashTable(statp);
             }
         }
-        if (volp->ro.ID) {
-            cm_SetFid(&fid, volp->cellp->cellID, volp->ro.ID, 1, 1);
+        if (volp->vol[ROVOL].ID) {
+            cm_SetFid(&fid, volp->cellp->cellID, volp->vol[ROVOL].ID, 1, 1);
             hash = fid.hash % fidStatsHashTableSize;
 
             for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
@@ -347,8 +347,8 @@ void cm_PerformanceTuningCheck(void)
                 cm_PerformanceInsertToHashTable(statp);
             }
         }
-        if (volp->bk.ID) {
-            cm_SetFid(&fid, volp->cellp->cellID, volp->bk.ID, 1, 1);
+        if (volp->vol[BACKVOL].ID) {
+            cm_SetFid(&fid, volp->cellp->cellID, volp->vol[BACKVOL].ID, 1, 1);
             hash = fid.hash % fidStatsHashTableSize;
 
             for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
index 51fdc5ab589de7340eaed40ae4e77319d0b13ad3..dcf89acd6876e2fbb6562ffa1b067cd4491f6a35 100644 (file)
@@ -846,17 +846,17 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
          * to copy the dotdotFipd from the volume structure where the 
          * "master" copy is stored (defect 11489)
          */
-        if (volp->ro.ID == fidp->volume) {
+        if (volp->vol[ROVOL].ID == fidp->volume) {
            scp->flags |= (CM_SCACHEFLAG_PURERO | CM_SCACHEFLAG_RO);
             if (scp->fid.vnode == 1 && scp->fid.unique == 1)
-                scp->dotdotFid = volp->ro.dotdotFid;
-        } else if (volp->bk.ID == fidp->volume) {
+                scp->dotdotFid = cm_VolumeStateByType(volp, ROVOL)->dotdotFid;
+        } else if (volp->vol[BACKVOL].ID == fidp->volume) {
            scp->flags |= CM_SCACHEFLAG_RO;
             if (scp->fid.vnode == 1 && scp->fid.unique == 1)
-                scp->dotdotFid = volp->bk.dotdotFid;
+                scp->dotdotFid = cm_VolumeStateByType(volp, BACKVOL)->dotdotFid;
         } else {
             if (scp->fid.vnode == 1 && scp->fid.unique == 1)
-                scp->dotdotFid = volp->rw.dotdotFid;
+                scp->dotdotFid = cm_VolumeStateByType(volp, RWVOL)->dotdotFid;
         }
     }
     if (volp)
index 2ae4182127deb95b6167acd1b1f17dcb56950964..3a81f85940c87652d761db72a0f66e548b4ada5e 100644 (file)
@@ -1107,6 +1107,7 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
         
     if (code == 0) {
         afs_uint32 cell, volume;
+        cm_vol_state_t *statep;
 
         cell = cellp->cellID;
         
@@ -1116,9 +1117,9 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
          * instead of the read-write.
          */
         if (cm_followBackupPath && 
-            volp->bk.ID != 0 &&
+            volp->vol[BACKVOL].ID != 0 &&
             (dscp->flags & (CM_SCACHEFLAG_RO|CM_SCACHEFLAG_PURERO)) == CM_SCACHEFLAG_RO &&
-            (targetType == RWVOL || targetType == ROVOL && volp->ro.ID == 0)
+            (targetType == RWVOL || targetType == ROVOL && volp->vol[ROVOL].ID == 0)
             ) {
             targetType = BACKVOL;
         } 
@@ -1129,25 +1130,15 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
          */
         else if (mtType == '#' && targetType == RWVOL && 
                  (scp->flags & CM_SCACHEFLAG_PURERO) && 
-                 volp->ro.ID != 0) {
+                 volp->vol[ROVOL].ID != 0) {
             targetType = ROVOL;
         }
-        if (targetType == ROVOL) {
-            volume = volp->ro.ID;
-            lock_ObtainMutex(&volp->mx);
-            volp->ro.dotdotFid = dscp->fid;
-            lock_ReleaseMutex(&volp->mx);
-        } else if (targetType == BACKVOL) {
-            volume = volp->bk.ID;
-            lock_ObtainMutex(&volp->mx);
-            volp->bk.dotdotFid = dscp->fid;
-            lock_ReleaseMutex(&volp->mx);
-        } else {
-            volume = volp->rw.ID;
-            lock_ObtainMutex(&volp->mx);
-            volp->rw.dotdotFid = dscp->fid;
-            lock_ReleaseMutex(&volp->mx);
-        }
+
+        lock_ObtainWrite(&volp->rw);
+        statep = cm_VolumeStateByType(volp, targetType);
+        volume = statep->ID;
+        statep->dotdotFid = dscp->fid;
+        lock_ReleaseWrite(&volp->rw);
 
         /* the rest of the fid is a magic number */
         cm_SetFid(&scp->mountRootFid, cell, volume, 1, 1);
@@ -1489,12 +1480,12 @@ long cm_EvaluateVolumeReference(char * namep, long flags, cm_user_t * userp,
         goto _exit_cleanup;
 
     if (volType == BACKVOL)
-        volume = volp->bk.ID;
+        volume = volp->vol[BACKVOL].ID;
     else if (volType == ROVOL ||
-             (volType == RWVOL && mountType == ROVOL && volp->ro.ID != 0))
-        volume = volp->ro.ID;
+             (volType == RWVOL && mountType == ROVOL && volp->vol[ROVOL].ID != 0))
+        volume = volp->vol[ROVOL].ID;
     else
-        volume = volp->rw.ID;
+        volume = volp->vol[RWVOL].ID;
 
     cm_SetFid(&fid, cellp->cellID, volume, 1, 1);
 
@@ -4880,11 +4871,6 @@ void cm_LockMarkSCacheLost(cm_scache_t * scp)
 
     osi_Log1(afsd_logp, "cm_LockMarkSCacheLost scp 0x%x", scp);
 
-#ifdef DEBUG
-    /* With the current code, we can't lose a lock on a RO scp */
-    osi_assertx(!(scp->flags & CM_SCACHEFLAG_RO), "CM_SCACHEFLAG_RO unexpected");
-#endif
-
     /* cm_scacheLock needed because we are modifying fileLock->flags */
     lock_ObtainWrite(&cm_scacheLock);
 
index 7e30ec94c69a5809e1d433c9fcbb188344513d4f..4bdd89b6dc270b297b103e48127798bc84ed6d8e 100644 (file)
@@ -70,15 +70,13 @@ cm_ShutdownVolume(void)
     cm_volume_t * volp;
 
     for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
-
-        if (volp->rw.ID)
-            cm_VolumeStatusNotification(volp, volp->rw.ID, volp->rw.state, vl_alldown);
-        if (volp->ro.ID)
-            cm_VolumeStatusNotification(volp, volp->ro.ID, volp->ro.state, vl_alldown);
-        if (volp->bk.ID)
-            cm_VolumeStatusNotification(volp, volp->bk.ID, volp->bk.state, vl_alldown);
+        afs_uint32 volType;
+        for ( volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
+            if (volp->vol[volType].ID)
+                cm_VolumeStatusNotification(volp, volp->vol[volType].ID, volp->vol[volType].state, vl_alldown);
+        }
         volp->cbExpiresRO = 0;
-        lock_FinalizeMutex(&volp->mx);
+        lock_FinalizeRWLock(&volp->rw);
     }
 
     return 0;
@@ -104,20 +102,16 @@ void cm_InitVolume(int newFile, long maxVols)
             cm_volume_t * volp;
 
             for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
-                lock_InitializeMutex(&volp->mx, "cm_volume_t mutex");
+                afs_uint32 volType;
+
+                lock_InitializeRWLock(&volp->rw, "cm_volume_t rwlock");
                 volp->flags |= CM_VOLUMEFLAG_RESET;
-                volp->rw.state = vl_unknown;
-                volp->rw.serversp = NULL;
-                volp->ro.state = vl_unknown;
-                volp->ro.serversp = NULL;
-                volp->bk.state = vl_unknown;
-                volp->bk.serversp = NULL;
-                if (volp->rw.ID)
-                    cm_VolumeStatusNotification(volp, volp->rw.ID, vl_alldown, volp->rw.state);
-                if (volp->ro.ID)
-                    cm_VolumeStatusNotification(volp, volp->ro.ID, vl_alldown, volp->ro.state);
-                if (volp->bk.ID)
-                    cm_VolumeStatusNotification(volp, volp->bk.ID, vl_alldown, volp->bk.state);
+                for (volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
+                    volp->vol[volType].state = vl_unknown;
+                    volp->vol[volType].serversp = NULL;
+                    if (volp->vol[volType].ID)
+                        cm_VolumeStatusNotification(volp, volp->vol[volType].ID, vl_alldown, volp->vol[volType].state);
+                }
                 volp->cbExpiresRO = 0;
             }
         }
@@ -142,7 +136,7 @@ cm_VolNameIsID(char *aname)
 
 
 /*
- * Update a volume.  Caller holds volume's lock (volp->mx).
+ * Update a volume.  Caller holds a write lock on the volume (volp->rw).
  *
  *
  *  shadow / openafs / jhutz@CS.CMU.EDU {ANDREW.CMU.EDU}  01:38    (JHutz)
@@ -168,7 +162,7 @@ cm_VolNameIsID(char *aname)
  *    RXGEN_OPCODE.
  */
 #define MULTIHOMED 1
-long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
+long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
                     cm_volume_t *volp)
 {
     cm_conn_t *connp;
@@ -192,17 +186,16 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
 #ifdef AFS_FREELANCE_CLIENT
     int freelance = 0;
 #endif
+    afs_uint32 volType;
 
     /* clear out old bindings */
-    if (volp->rw.serversp)
-        cm_FreeServerList(&volp->rw.serversp, CM_FREESERVERLIST_DELETE);
-    if (volp->ro.serversp)
-        cm_FreeServerList(&volp->ro.serversp, CM_FREESERVERLIST_DELETE);
-    if (volp->bk.serversp)
-        cm_FreeServerList(&volp->bk.serversp, CM_FREESERVERLIST_DELETE);
+    for ( volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
+        if (volp->vol[volType].serversp)
+            cm_FreeServerList(&volp->vol[volType].serversp, CM_FREESERVERLIST_DELETE);
+    }
 
 #ifdef AFS_FREELANCE_CLIENT
-    if ( cellp->cellID == AFS_FAKE_ROOT_CELL_ID && volp->rw.ID == AFS_FAKE_ROOT_VOL_ID ) 
+    if ( cellp->cellID == AFS_FAKE_ROOT_CELL_ID && volp->vol[RWVOL].ID == AFS_FAKE_ROOT_VOL_ID ) 
     {
        freelance = 1;
         memset(&vldbEntry, 0, sizeof(vldbEntry));
@@ -213,6 +206,17 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
     } else
 #endif
     {
+        while (volp->flags & CM_VOLUMEFLAG_UPDATING_VL) {
+            osi_SleepW((LONG_PTR) &volp->flags, &volp->rw);
+            lock_ObtainWrite(&volp->rw);
+
+            if (!(volp->flags & CM_VOLUMEFLAG_RESET))
+                return 0;
+        }
+
+        volp->flags |= CM_VOLUMEFLAG_UPDATING_VL;
+        lock_ReleaseWrite(&volp->rw);
+
         if (cellp->flags & CM_CELLFLAG_VLSERVER_INVALID)
             cm_UpdateCell(cellp, 0);
 
@@ -250,7 +254,7 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
      * doesn't exist we will not care about the .backup that might be left behind
      * since there should be no method to access it.  
      */
-    if (code == CM_ERROR_NOSUCHVOLUME && volp->rw.ID == 0 && strlen(volp->namep) < (VL_MAXNAMELEN - 9)) {
+    if (code == CM_ERROR_NOSUCHVOLUME && volp->vol[RWVOL].ID == 0 && strlen(volp->namep) < (VL_MAXNAMELEN - 9)) {
         char name[VL_MAXNAMELEN];
 
         snprintf(name, VL_MAXNAMELEN, "%s.readonly", volp->namep);
@@ -284,7 +288,8 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
            osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s SUCCESS", 
                      volp->cellp->name, osi_LogSaveString(afsd_logp,name));
     }
-
+    
+    lock_ObtainWrite(&volp->rw);
     if (code == 0) {
         afs_int32 flags;
         afs_int32 nServers;
@@ -408,40 +413,40 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
         }
 
         if (flags & VLF_RWEXISTS) {
-            if (volp->rw.ID != rwID) {
-                if (volp->rw.flags & CM_VOLUMEFLAG_IN_HASH)
+            if (volp->vol[RWVOL].ID != rwID) {
+                if (volp->vol[RWVOL].flags & CM_VOLUMEFLAG_IN_HASH)
                     cm_RemoveVolumeFromIDHashTable(volp, RWVOL);
-                volp->rw.ID = rwID;
+                volp->vol[RWVOL].ID = rwID;
                 cm_AddVolumeToIDHashTable(volp, RWVOL);
             }
         } else {
-            if (volp->rw.flags & CM_VOLUMEFLAG_IN_HASH)
+            if (volp->vol[RWVOL].flags & CM_VOLUMEFLAG_IN_HASH)
                 cm_RemoveVolumeFromIDHashTable(volp, RWVOL);
-            volp->rw.ID = 0;
+            volp->vol[RWVOL].ID = 0;
         }
         if (flags & VLF_ROEXISTS) {
-            if (volp->ro.ID != roID) {
-                if (volp->ro.flags & CM_VOLUMEFLAG_IN_HASH)
+            if (volp->vol[ROVOL].ID != roID) {
+                if (volp->vol[ROVOL].flags & CM_VOLUMEFLAG_IN_HASH)
                     cm_RemoveVolumeFromIDHashTable(volp, ROVOL);
-                volp->ro.ID = roID;
+                volp->vol[ROVOL].ID = roID;
                 cm_AddVolumeToIDHashTable(volp, ROVOL);
             }
         } else {
-            if (volp->ro.flags & CM_VOLUMEFLAG_IN_HASH)
+            if (volp->vol[ROVOL].flags & CM_VOLUMEFLAG_IN_HASH)
                 cm_RemoveVolumeFromIDHashTable(volp, ROVOL);
-            volp->ro.ID = 0;
+            volp->vol[ROVOL].ID = 0;
         }
         if (flags & VLF_BACKEXISTS) {
-            if (volp->bk.ID != bkID) {
-                if (volp->bk.flags & CM_VOLUMEFLAG_IN_HASH)
+            if (volp->vol[BACKVOL].ID != bkID) {
+                if (volp->vol[BACKVOL].flags & CM_VOLUMEFLAG_IN_HASH)
                     cm_RemoveVolumeFromIDHashTable(volp, BACKVOL);
-                volp->bk.ID = bkID;
+                volp->vol[BACKVOL].ID = bkID;
                 cm_AddVolumeToIDHashTable(volp, BACKVOL);
             }
         } else {
-            if (volp->bk.flags & CM_VOLUMEFLAG_IN_HASH)
+            if (volp->vol[BACKVOL].flags & CM_VOLUMEFLAG_IN_HASH)
                 cm_RemoveVolumeFromIDHashTable(volp, BACKVOL);
-            volp->bk.ID = 0;
+            volp->vol[BACKVOL].ID = 0;
         }
         lock_ReleaseWrite(&cm_volumeLock);
         for (i=0; i<nServers; i++) {
@@ -472,7 +477,7 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
              */
             if ((tflags & VLSF_RWVOL) && (flags & VLF_RWEXISTS)) {
                 tsrp = cm_NewServerRef(tsp, rwID);
-                cm_InsertServerList(&volp->rw.serversp, tsrp);
+                cm_InsertServerList(&volp->vol[RWVOL].serversp, tsrp);
 
                 lock_ObtainWrite(&cm_serverLock);
                 tsrp->refCount--;       /* drop allocation reference */
@@ -483,7 +488,7 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
             }
             if ((tflags & VLSF_ROVOL) && (flags & VLF_ROEXISTS)) {
                 tsrp = cm_NewServerRef(tsp, roID);
-                cm_InsertServerList(&volp->ro.serversp, tsrp);
+                cm_InsertServerList(&volp->vol[ROVOL].serversp, tsrp);
                 lock_ObtainWrite(&cm_serverLock);
                 tsrp->refCount--;       /* drop allocation reference */
                 lock_ReleaseWrite(&cm_serverLock);
@@ -499,7 +504,7 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
              */
             if ((tflags & VLSF_RWVOL) && (flags & VLF_BACKEXISTS)) {
                 tsrp = cm_NewServerRef(tsp, bkID);
-                cm_InsertServerList(&volp->bk.serversp, tsrp);
+                cm_InsertServerList(&volp->vol[BACKVOL].serversp, tsrp);
                 lock_ObtainWrite(&cm_serverLock);
                 tsrp->refCount--;       /* drop allocation reference */
                 lock_ReleaseWrite(&cm_serverLock);
@@ -522,7 +527,7 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
          * lists are length 1.
          */
         if (ROcount > 1) {
-            cm_RandomizeServer(&volp->ro.serversp);
+            cm_RandomizeServer(&volp->vol[ROVOL].serversp);
         }
 
         rwNewstate = rwServers_alldown ? vl_alldown : vl_online;
@@ -532,48 +537,43 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
         /* this volume does not exist - we should discard it */
         if (volp->flags & CM_VOLUMEFLAG_IN_HASH)
             cm_RemoveVolumeFromNameHashTable(volp);
-        if (volp->rw.flags & CM_VOLUMEFLAG_IN_HASH)
-            cm_RemoveVolumeFromIDHashTable(volp, RWVOL);
-        if (volp->ro.flags & CM_VOLUMEFLAG_IN_HASH)
-            cm_RemoveVolumeFromIDHashTable(volp, ROVOL);
-        if (volp->bk.flags & CM_VOLUMEFLAG_IN_HASH)
-            cm_RemoveVolumeFromIDHashTable(volp, BACKVOL);
+        for ( volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
+            if (volp->vol[volType].flags & CM_VOLUMEFLAG_IN_HASH)
+                cm_RemoveVolumeFromIDHashTable(volp, volType);
+            if (volp->vol[volType].ID) {
+                cm_VolumeStatusNotification(volp, volp->vol[volType].ID, volp->vol[volType].state, vl_alldown);
+                volp->vol[volType].ID = 0;
+            }
+            cm_SetFid(&volp->vol[volType].dotdotFid, 0, 0, 0, 0);
+        }
 
         /* Move to the end so it will be recycled first */
         cm_MoveVolumeToLRULast(volp);
 
-        if (volp->rw.ID)
-            cm_VolumeStatusNotification(volp, volp->rw.ID, volp->rw.state, vl_alldown);
-        if (volp->ro.ID)
-            cm_VolumeStatusNotification(volp, volp->ro.ID, volp->ro.state, vl_alldown);
-        if (volp->bk.ID)
-            cm_VolumeStatusNotification(volp, volp->bk.ID, volp->bk.state, vl_alldown);
-
-        volp->rw.ID = volp->ro.ID = volp->bk.ID = 0;
-        cm_SetFid(&volp->rw.dotdotFid, 0, 0, 0, 0);
-        cm_SetFid(&volp->ro.dotdotFid, 0, 0, 0, 0);
-        cm_SetFid(&volp->bk.dotdotFid, 0, 0, 0, 0);
         volp->namep[0] ='\0';
     } else {
         rwNewstate = roNewstate = bkNewstate = vl_alldown;
     }
 
-    if (volp->rw.state != rwNewstate) {
-        if (volp->rw.ID)
-            cm_VolumeStatusNotification(volp, volp->rw.ID, volp->rw.state, rwNewstate);
-        volp->rw.state = rwNewstate;
+    if (volp->vol[RWVOL].state != rwNewstate) {
+        if (volp->vol[RWVOL].ID)
+            cm_VolumeStatusNotification(volp, volp->vol[RWVOL].ID, volp->vol[RWVOL].state, rwNewstate);
+        volp->vol[RWVOL].state = rwNewstate;
     }
-    if (volp->ro.state != roNewstate) {
-        if (volp->ro.ID)
-            cm_VolumeStatusNotification(volp, volp->ro.ID, volp->ro.state, roNewstate);
-        volp->ro.state = roNewstate;
+    if (volp->vol[ROVOL].state != roNewstate) {
+        if (volp->vol[ROVOL].ID)
+            cm_VolumeStatusNotification(volp, volp->vol[ROVOL].ID, volp->vol[ROVOL].state, roNewstate);
+        volp->vol[ROVOL].state = roNewstate;
     }
-    if (volp->bk.state != bkNewstate) {
-        if (volp->bk.ID)
-            cm_VolumeStatusNotification(volp, volp->bk.ID, volp->bk.state, bkNewstate);
-        volp->bk.state = bkNewstate;
+    if (volp->vol[BACKVOL].state != bkNewstate) {
+        if (volp->vol[BACKVOL].ID)
+            cm_VolumeStatusNotification(volp, volp->vol[BACKVOL].ID, volp->vol[BACKVOL].state, bkNewstate);
+        volp->vol[BACKVOL].state = bkNewstate;
     }
 
+    volp->flags &= ~CM_VOLUMEFLAG_UPDATING_VL;
+    osi_Wakeup((LONG_PTR) &volp->flags);
+
     return code;
 }
 
@@ -594,21 +594,21 @@ cm_volume_t *cm_GetVolumeByFID(cm_fid_t *fidp)
      * search the hash table for all three types until we find it.
      * We will search in the order of RO, RW, BK.
      */
-    for ( volp = cm_data.volumeROIDHashTablep[hash]; volp; volp = volp->ro.nextp) {
-        if ( fidp->cell == volp->cellp->cellID && fidp->volume == volp->ro.ID )
+    for ( volp = cm_data.volumeROIDHashTablep[hash]; volp; volp = volp->vol[ROVOL].nextp) {
+        if ( fidp->cell == volp->cellp->cellID && fidp->volume == volp->vol[ROVOL].ID )
             break;
     }
     if (!volp) {
         /* try RW volumes */
-        for ( volp = cm_data.volumeRWIDHashTablep[hash]; volp; volp = volp->rw.nextp) {
-            if ( fidp->cell == volp->cellp->cellID && fidp->volume == volp->rw.ID )
+        for ( volp = cm_data.volumeRWIDHashTablep[hash]; volp; volp = volp->vol[RWVOL].nextp) {
+            if ( fidp->cell == volp->cellp->cellID && fidp->volume == volp->vol[RWVOL].ID )
                 break;
         }
     }
     if (!volp) {
         /* try BK volumes */
-        for ( volp = cm_data.volumeBKIDHashTablep[hash]; volp; volp = volp->bk.nextp) {
-            if ( fidp->cell == volp->cellp->cellID && fidp->volume == volp->bk.ID )
+        for ( volp = cm_data.volumeBKIDHashTablep[hash]; volp; volp = volp->vol[BACKVOL].nextp) {
+            if ( fidp->cell == volp->cellp->cellID && fidp->volume == volp->vol[BACKVOL].ID )
                 break;
         }
     }
@@ -636,9 +636,9 @@ long cm_FindVolumeByID(cm_cell_t *cellp, afs_uint32 volumeID, cm_user_t *userp,
 #ifdef SEARCH_ALL_VOLUMES
     for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
        if (cellp == volp->cellp &&
-            ((unsigned) volumeID == volp->rw.ID ||
-              (unsigned) volumeID == volp->ro.ID ||
-              (unsigned) volumeID == volp->bk.ID))
+            ((unsigned) volumeID == volp->vol[RWVOL].ID ||
+              (unsigned) volumeID == volp->vol[ROVOL].ID ||
+              (unsigned) volumeID == volp->vol[BACKVOL].ID))
            break;
     }  
 
@@ -650,21 +650,21 @@ long cm_FindVolumeByID(cm_cell_t *cellp, afs_uint32 volumeID, cm_user_t *userp,
      * search the hash table for all three types until we find it.
      * We will search in the order of RO, RW, BK.
      */
-    for ( volp = cm_data.volumeROIDHashTablep[hash]; volp; volp = volp->ro.nextp) {
-        if ( cellp == volp->cellp && volumeID == volp->ro.ID )
+    for ( volp = cm_data.volumeROIDHashTablep[hash]; volp; volp = volp->vol[ROVOL].nextp) {
+        if ( cellp == volp->cellp && volumeID == volp->vol[ROVOL].ID )
             break;
     }
     if (!volp) {
         /* try RW volumes */
-        for ( volp = cm_data.volumeRWIDHashTablep[hash]; volp; volp = volp->rw.nextp) {
-            if ( cellp == volp->cellp && volumeID == volp->rw.ID )
+        for ( volp = cm_data.volumeRWIDHashTablep[hash]; volp; volp = volp->vol[RWVOL].nextp) {
+            if ( cellp == volp->cellp && volumeID == volp->vol[RWVOL].ID )
                 break;
         }
     }
     if (!volp) {
         /* try BK volumes */
-        for ( volp = cm_data.volumeBKIDHashTablep[hash]; volp; volp = volp->bk.nextp) {
-            if ( cellp == volp->cellp && volumeID == volp->bk.ID )
+        for ( volp = cm_data.volumeBKIDHashTablep[hash]; volp; volp = volp->vol[BACKVOL].nextp) {
+            if ( cellp == volp->cellp && volumeID == volp->vol[BACKVOL].ID )
                 break;
         }
     }
@@ -681,15 +681,15 @@ long cm_FindVolumeByID(cm_cell_t *cellp, afs_uint32 volumeID, cm_user_t *userp,
 
     /* return it held */
     if (volp) {
-        lock_ObtainMutex(&volp->mx);
+        lock_ObtainWrite(&volp->rw);
         
         code = 0;
         if ((volp->flags & CM_VOLUMEFLAG_RESET) && !(flags & CM_GETVOL_FLAG_NO_RESET)) {
-            code = cm_UpdateVolume(cellp, userp, reqp, volp);
+            code = cm_UpdateVolumeLocation(cellp, userp, reqp, volp);
             if (code == 0)
                 volp->flags &= ~CM_VOLUMEFLAG_RESET;
         }
-        lock_ReleaseMutex(&volp->mx);
+        lock_ReleaseWrite(&volp->rw);
         if (code == 0) {
             *outVolpp = volp;
 
@@ -761,10 +761,10 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
 #endif
 
     if (!volp && (flags & CM_GETVOL_FLAG_CREATE)) {
+        afs_uint32 volType;
         /* otherwise, get from VLDB */
 
        if ( cm_data.currentVolumes >= cm_data.maxVolumes ) {
-
 #ifdef RECYCLE_FROM_ALL_VOLUMES_LIST
            for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
                if ( volp->refCount == 0 ) {
@@ -787,7 +787,7 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
                osi_panic("Exceeded Max Volumes", __FILE__, __LINE__);
 
             lock_ReleaseRead(&cm_volumeLock);
-            lock_ObtainMutex(&volp->mx);
+            lock_ObtainWrite(&volp->rw);
             lock_ObtainWrite(&cm_volumeLock);
 
             osi_Log2(afsd_logp, "Recycling Volume %s:%s",
@@ -797,33 +797,24 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
                 cm_RemoveVolumeFromLRU(volp);
             if (volp->flags & CM_VOLUMEFLAG_IN_HASH)
                 cm_RemoveVolumeFromNameHashTable(volp);
-            if (volp->rw.flags & CM_VOLUMEFLAG_IN_HASH)
-                cm_RemoveVolumeFromIDHashTable(volp, RWVOL);
-            if (volp->ro.flags & CM_VOLUMEFLAG_IN_HASH)
-                cm_RemoveVolumeFromIDHashTable(volp, ROVOL);
-            if (volp->bk.flags & CM_VOLUMEFLAG_IN_HASH)
-                cm_RemoveVolumeFromIDHashTable(volp, BACKVOL);
 
-            if (volp->rw.ID)
-                cm_VolumeStatusNotification(volp, volp->rw.ID, volp->rw.state, vl_unknown);
-            if (volp->ro.ID)
-                cm_VolumeStatusNotification(volp, volp->ro.ID, volp->ro.state, vl_unknown);
-            if (volp->bk.ID)
-                cm_VolumeStatusNotification(volp, volp->bk.ID, volp->bk.state, vl_unknown);
-
-            volp->rw.ID = volp->ro.ID = volp->bk.ID = 0;
-            cm_SetFid(&volp->rw.dotdotFid, 0, 0, 0, 0);
-            cm_SetFid(&volp->ro.dotdotFid, 0, 0, 0, 0);
-            cm_SetFid(&volp->bk.dotdotFid, 0, 0, 0, 0);
+            for ( volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
+                if (volp->vol[volType].flags & CM_VOLUMEFLAG_IN_HASH)
+                    cm_RemoveVolumeFromIDHashTable(volp, volType);
+                if (volp->vol[volType].ID)
+                    cm_VolumeStatusNotification(volp, volp->vol[volType].ID, volp->vol[volType].state, vl_unknown);
+                volp->vol[volType].ID = 0;
+                cm_SetFid(&volp->vol[volType].dotdotFid, 0, 0, 0, 0);
+            }
        } else {
            volp = &cm_data.volumeBaseAddress[cm_data.currentVolumes++];
            memset(volp, 0, sizeof(cm_volume_t));
            volp->magic = CM_VOLUME_MAGIC;
            volp->allNextp = cm_data.allVolumesp;
            cm_data.allVolumesp = volp;
-           lock_InitializeMutex(&volp->mx, "cm_volume_t mutex");
+           lock_InitializeRWLock(&volp->rw, "cm_volume_t rwlock");
             lock_ReleaseRead(&cm_volumeLock);
-            lock_ObtainMutex(&volp->mx);
+            lock_ObtainWrite(&volp->rw);
             lock_ObtainWrite(&cm_volumeLock);
         }
        volp->cellp = cellp;
@@ -831,9 +822,12 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
        volp->namep[VL_MAXNAMELEN-1] = '\0';
         volp->refCount = 1;    /* starts off held */
        volp->flags = CM_VOLUMEFLAG_RESET;
-        volp->rw.state = volp->ro.state = volp->bk.state = vl_unknown;
-        volp->rw.nextp = volp->ro.nextp = volp->bk.nextp = NULL;
-        volp->rw.flags = volp->ro.flags = volp->bk.flags = 0;
+    
+        for ( volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
+            volp->vol[volType].state = vl_unknown;
+            volp->vol[volType].nextp = NULL;
+            volp->vol[volType].flags = 0;
+        }
         volp->cbExpiresRO = 0;
         cm_AddVolumeToNameHashTable(volp);
         lock_ReleaseWrite(&cm_volumeLock);
@@ -846,19 +840,19 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
         if (!volp)
             return CM_ERROR_NOSUCHVOLUME;
 
-        lock_ObtainMutex(&volp->mx);
+        lock_ObtainWrite(&volp->rw);
     }
 
     /* if we get here we are holding the mutex */
     if ((volp->flags & CM_VOLUMEFLAG_RESET) && !(flags & CM_GETVOL_FLAG_NO_RESET)) {
-        code = cm_UpdateVolume(cellp, userp, reqp, volp);
+        code = cm_UpdateVolumeLocation(cellp, userp, reqp, volp);
         if (code == 0)
             volp->flags &= ~CM_VOLUMEFLAG_RESET;
     }  
-    lock_ReleaseMutex(&volp->mx);
+    lock_ReleaseWrite(&volp->rw);
 
-    if (code == 0 && (type == BACKVOL && volp->bk.ID == 0 ||
-                      type == ROVOL && volp->ro.ID == 0))
+    if (code == 0 && (type == BACKVOL && volp->vol[BACKVOL].ID == 0 ||
+                      type == ROVOL && volp->vol[ROVOL].ID == 0))
         code = CM_ERROR_NOSUCHVOLUME;
 
     if (code == 0) {
@@ -894,9 +888,9 @@ void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp)
 #ifdef SEARCH_ALL_VOLUMES
     for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
        if (cellp == volp->cellp &&
-            (fidp->volume == volp->rw.ID ||
-              fidp->volume == volp->ro.ID ||
-              fidp->volume == volp->bk.ID))
+            (fidp->volume == volp->vol[RWVOL].ID ||
+              fidp->volume == volp->vol[ROVOL].ID ||
+              fidp->volume == volp->vol[BACKVOL].ID))
            break;
     }  
 #endif /* SEARCH_ALL_VOLUMES */
@@ -906,21 +900,21 @@ void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp)
      * search the hash table for all three types until we find it.
      * We will search in the order of RO, RW, BK.
      */
-    for ( volp = cm_data.volumeROIDHashTablep[hash]; volp; volp = volp->ro.nextp) {
-        if ( cellp == volp->cellp && fidp->volume == volp->ro.ID )
+    for ( volp = cm_data.volumeROIDHashTablep[hash]; volp; volp = volp->vol[ROVOL].nextp) {
+        if ( cellp == volp->cellp && fidp->volume == volp->vol[ROVOL].ID )
             break;
     }
     if (!volp) {
         /* try RW volumes */
-        for ( volp = cm_data.volumeRWIDHashTablep[hash]; volp; volp = volp->rw.nextp) {
-            if ( cellp == volp->cellp && fidp->volume == volp->rw.ID )
+        for ( volp = cm_data.volumeRWIDHashTablep[hash]; volp; volp = volp->vol[RWVOL].nextp) {
+            if ( cellp == volp->cellp && fidp->volume == volp->vol[RWVOL].ID )
                 break;
         }
     }
     if (!volp) {
         /* try BK volumes */
-        for ( volp = cm_data.volumeBKIDHashTablep[hash]; volp; volp = volp->bk.nextp) {
-            if ( cellp == volp->cellp && fidp->volume == volp->bk.ID )
+        for ( volp = cm_data.volumeBKIDHashTablep[hash]; volp; volp = volp->vol[BACKVOL].nextp) {
+            if ( cellp == volp->cellp && fidp->volume == volp->vol[BACKVOL].ID )
                 break;
         }
     }
@@ -936,7 +930,7 @@ void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp)
 
     /* update it */
     cm_data.mountRootGen = time(NULL);
-    lock_ObtainMutex(&volp->mx);
+    lock_ObtainWrite(&volp->rw);
     volp->flags |= CM_VOLUMEFLAG_RESET;
 #ifdef COMMENT
     /* Mark the volume to be updated but don't update it now.
@@ -949,11 +943,11 @@ 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);
+    code = cm_UpdateVolumeLocation(cellp, userp, reqp, volp);
     if (code == 0)
        volp->flags &= ~CM_VOLUMEFLAG_RESET;
 #endif
-    lock_ReleaseMutex(&volp->mx);
+    lock_ReleaseWrite(&volp->rw);
 
     cm_PutVolume(volp);
 }
@@ -966,12 +960,12 @@ cm_serverRef_t **cm_GetVolServers(cm_volume_t *volp, afs_uint32 volume)
 
     lock_ObtainWrite(&cm_serverLock);
 
-    if (volume == volp->rw.ID)
-        serverspp = &volp->rw.serversp;
-    else if (volume == volp->ro.ID)
-        serverspp = &volp->ro.serversp;
-    else if (volume == volp->bk.ID)
-        serverspp = &volp->bk.serversp;
+    if (volume == volp->vol[RWVOL].ID)
+        serverspp = &volp->vol[RWVOL].serversp;
+    else if (volume == volp->vol[ROVOL].ID)
+        serverspp = &volp->vol[ROVOL].serversp;
+    else if (volume == volp->vol[BACKVOL].ID)
+        serverspp = &volp->vol[BACKVOL].serversp;
     else 
         osi_panic("bad volume ID in cm_GetVolServers", __FILE__, __LINE__);
         
@@ -996,12 +990,12 @@ long cm_GetROVolumeID(cm_volume_t *volp)
 {
     long id;
 
-    lock_ObtainMutex(&volp->mx);
-    if (volp->ro.ID && volp->ro.serversp)
-       id = volp->ro.ID;
+    lock_ObtainRead(&volp->rw);
+    if (volp->vol[ROVOL].ID && volp->vol[ROVOL].serversp)
+       id = volp->vol[ROVOL].ID;
     else
-       id = volp->rw.ID;
-    lock_ReleaseMutex(&volp->mx);
+       id = volp->vol[RWVOL].ID;
+    lock_ReleaseRead(&volp->rw);
 
     return id;
 }
@@ -1020,9 +1014,9 @@ void cm_RefreshVolumes(void)
        InterlockedIncrement(&volp->refCount);
        lock_ReleaseRead(&cm_volumeLock);
 
-       lock_ObtainMutex(&volp->mx);
+       lock_ObtainWrite(&volp->rw);
        volp->flags |= CM_VOLUMEFLAG_RESET;
-       lock_ReleaseMutex(&volp->mx);
+       lock_ReleaseWrite(&volp->rw);
        
         lock_ObtainRead(&cm_volumeLock);
         refCount = InterlockedDecrement(&volp->refCount);
@@ -1075,124 +1069,124 @@ cm_CheckOfflineVolume(cm_volume_t *volp, afs_uint32 volID)
     OfflineMsg = offLineMsg;
     MOTD = motd;
 
-    lock_ObtainMutex(&volp->mx);
+    lock_ObtainWrite(&volp->rw);
 
     if (volp->flags & CM_VOLUMEFLAG_RESET) {
         cm_InitReq(&req);
-        code = cm_UpdateVolume(volp->cellp, cm_rootUserp, &req, volp);
+        code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp);
         if (code == 0)
             volp->flags &= ~CM_VOLUMEFLAG_RESET;
     }
 
-    if (volp->rw.ID != 0 && (!volID || volID == volp->rw.ID) &&
-               volp->rw.serversp &&
-         (volp->rw.state == vl_busy || volp->rw.state == vl_offline || volp->rw.state == vl_unknown)) {
+    if (volp->vol[RWVOL].ID != 0 && (!volID || volID == volp->vol[RWVOL].ID) &&
+         volp->vol[RWVOL].serversp &&
+         (volp->vol[RWVOL].state == vl_busy || volp->vol[RWVOL].state == vl_offline || volp->vol[RWVOL].state == vl_unknown)) {
         cm_InitReq(&req);
 
-        for (serversp = volp->rw.serversp; serversp; serversp = serversp->next) {
+        for (serversp = volp->vol[RWVOL].serversp; serversp; serversp = serversp->next) {
             if (serversp->status == srv_busy || serversp->status == srv_offline)
                 serversp->status = srv_not_busy;
         }
 
-        lock_ReleaseMutex(&volp->mx);
+        lock_ReleaseWrite(&volp->rw);
         do {
-            code = cm_ConnFromVolume(volp, volp->rw.ID, cm_rootUserp, &req, &connp);
+            code = cm_ConnFromVolume(volp, volp->vol[RWVOL].ID, cm_rootUserp, &req, &connp);
             if (code) 
                 continue;
 
             callp = cm_GetRxConn(connp);
-            code = RXAFS_GetVolumeStatus(callp, volp->rw.ID,
+            code = RXAFS_GetVolumeStatus(callp, volp->vol[RWVOL].ID,
                                           &volStat, &Name, &OfflineMsg, &MOTD);
             rx_PutConnection(callp);        
 
         } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code));
         code = cm_MapRPCError(code, &req);
 
-        lock_ObtainMutex(&volp->mx);
+        lock_ObtainWrite(&volp->rw);
         if (code == 0 && volStat.Online) {
-            cm_VolumeStatusNotification(volp, volp->rw.ID, volp->rw.state, vl_online);
-            volp->rw.state = vl_online;
+            cm_VolumeStatusNotification(volp, volp->vol[RWVOL].ID, volp->vol[RWVOL].state, vl_online);
+            volp->vol[RWVOL].state = vl_online;
             online = 1;
         } else if (code == CM_ERROR_NOACCESS) {
-            cm_VolumeStatusNotification(volp, volp->rw.ID, volp->rw.state, vl_unknown);
-            volp->rw.state = vl_unknown;
+            cm_VolumeStatusNotification(volp, volp->vol[RWVOL].ID, volp->vol[RWVOL].state, vl_unknown);
+            volp->vol[RWVOL].state = vl_unknown;
             online = 1;
         }
     }
 
-    if (volp->ro.ID != 0 && (!volID || volID == volp->ro.ID) &&
-               volp->ro.serversp &&
-         (volp->ro.state == vl_busy || volp->ro.state == vl_offline || volp->ro.state == vl_unknown)) {
+    if (volp->vol[ROVOL].ID != 0 && (!volID || volID == volp->vol[ROVOL].ID) &&
+         volp->vol[ROVOL].serversp &&
+         (volp->vol[ROVOL].state == vl_busy || volp->vol[ROVOL].state == vl_offline || volp->vol[ROVOL].state == vl_unknown)) {
         cm_InitReq(&req);
 
-        for (serversp = volp->ro.serversp; serversp; serversp = serversp->next) {
+        for (serversp = volp->vol[ROVOL].serversp; serversp; serversp = serversp->next) {
             if (serversp->status == srv_busy || serversp->status == srv_offline)
                 serversp->status = srv_not_busy;
         }
 
-        lock_ReleaseMutex(&volp->mx);
+        lock_ReleaseWrite(&volp->rw);
         do {
-            code = cm_ConnFromVolume(volp, volp->ro.ID, cm_rootUserp, &req, &connp);
+            code = cm_ConnFromVolume(volp, volp->vol[ROVOL].ID, cm_rootUserp, &req, &connp);
             if (code) 
                 continue;
 
             callp = cm_GetRxConn(connp);
-            code = RXAFS_GetVolumeStatus(callp, volp->ro.ID,
+            code = RXAFS_GetVolumeStatus(callp, volp->vol[ROVOL].ID,
                                           &volStat, &Name, &OfflineMsg, &MOTD);
             rx_PutConnection(callp);        
 
         } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code));
         code = cm_MapRPCError(code, &req);
 
-        lock_ObtainMutex(&volp->mx);
+        lock_ObtainWrite(&volp->rw);
         if (code == 0 && volStat.Online) {
-            cm_VolumeStatusNotification(volp, volp->ro.ID, volp->ro.state, vl_online);
-            volp->ro.state = vl_online;
+            cm_VolumeStatusNotification(volp, volp->vol[ROVOL].ID, volp->vol[ROVOL].state, vl_online);
+            volp->vol[ROVOL].state = vl_online;
             online = 1;
         } else if (code == CM_ERROR_NOACCESS) {
-            cm_VolumeStatusNotification(volp, volp->ro.ID, volp->ro.state, vl_unknown);
-            volp->ro.state = vl_unknown;
+            cm_VolumeStatusNotification(volp, volp->vol[ROVOL].ID, volp->vol[ROVOL].state, vl_unknown);
+            volp->vol[ROVOL].state = vl_unknown;
             online = 1;
         }
     }
 
-    if (volp->bk.ID != 0 && (!volID || volID == volp->bk.ID) &&
-               volp->bk.serversp &&
-         (volp->bk.state == vl_busy || volp->bk.state == vl_offline || volp->bk.state == vl_unknown)) {
+    if (volp->vol[BACKVOL].ID != 0 && (!volID || volID == volp->vol[BACKVOL].ID) &&
+         volp->vol[BACKVOL].serversp &&
+         (volp->vol[BACKVOL].state == vl_busy || volp->vol[BACKVOL].state == vl_offline || volp->vol[BACKVOL].state == vl_unknown)) {
         cm_InitReq(&req);
 
-        for (serversp = volp->bk.serversp; serversp; serversp = serversp->next) {
+        for (serversp = volp->vol[BACKVOL].serversp; serversp; serversp = serversp->next) {
             if (serversp->status == srv_busy || serversp->status == srv_offline)
                 serversp->status = srv_not_busy;
         }
 
-        lock_ReleaseMutex(&volp->mx);
+        lock_ReleaseWrite(&volp->rw);
         do {
-            code = cm_ConnFromVolume(volp, volp->bk.ID, cm_rootUserp, &req, &connp);
+            code = cm_ConnFromVolume(volp, volp->vol[BACKVOL].ID, cm_rootUserp, &req, &connp);
             if (code) 
                 continue;
 
             callp = cm_GetRxConn(connp);
-            code = RXAFS_GetVolumeStatus(callp, volp->bk.ID,
+            code = RXAFS_GetVolumeStatus(callp, volp->vol[BACKVOL].ID,
                                           &volStat, &Name, &OfflineMsg, &MOTD);
             rx_PutConnection(callp);        
 
         } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code));
         code = cm_MapRPCError(code, &req);
 
-        lock_ObtainMutex(&volp->mx);
+        lock_ObtainWrite(&volp->rw);
         if (code == 0 && volStat.Online) {
-            cm_VolumeStatusNotification(volp, volp->bk.ID, volp->bk.state, vl_online);
-            volp->bk.state = vl_online;
+            cm_VolumeStatusNotification(volp, volp->vol[BACKVOL].ID, volp->vol[BACKVOL].state, vl_online);
+            volp->vol[BACKVOL].state = vl_online;
             online = 1;
         } else if (code == CM_ERROR_NOACCESS) {
-            cm_VolumeStatusNotification(volp, volp->bk.ID, volp->bk.state, vl_unknown);
-            volp->bk.state = vl_unknown;
+            cm_VolumeStatusNotification(volp, volp->vol[BACKVOL].ID, volp->vol[BACKVOL].state, vl_unknown);
+            volp->vol[BACKVOL].state = vl_unknown;
             online = 1;
         }
     }
 
-    lock_ReleaseMutex(&volp->mx);
+    lock_ReleaseWrite(&volp->rw);
     return online;
 }
 
@@ -1273,12 +1267,12 @@ void
 cm_UpdateVolumeStatus(cm_volume_t *volp, afs_uint32 volID)
 {
 
-    if (volp->rw.ID == volID) {
-        cm_UpdateVolumeStatusInt(volp, &volp->rw);
-    } else if (volp->ro.ID == volID) {
-        cm_UpdateVolumeStatusInt(volp, &volp->ro);
-    } else if (volp->bk.ID == volID) {
-        cm_UpdateVolumeStatusInt(volp, &volp->bk);
+    if (volp->vol[RWVOL].ID == volID) {
+        cm_UpdateVolumeStatusInt(volp, &volp->vol[RWVOL]);
+    } else if (volp->vol[ROVOL].ID == volID) {
+        cm_UpdateVolumeStatusInt(volp, &volp->vol[ROVOL]);
+    } else if (volp->vol[BACKVOL].ID == volID) {
+        cm_UpdateVolumeStatusInt(volp, &volp->vol[BACKVOL]);
     } else {
         /*
          * If we are called with volID == 0 then something has gone wrong.
@@ -1287,12 +1281,11 @@ cm_UpdateVolumeStatus(cm_volume_t *volp, afs_uint32 volID)
          * just update all of them that are known to exist.  Better to be 
          * correct than fast.
          */
-        if (volp->rw.ID != 0)
-            cm_UpdateVolumeStatusInt(volp, &volp->rw);
-        if (volp->ro.ID != 0)
-            cm_UpdateVolumeStatusInt(volp, &volp->ro);
-        if (volp->bk.ID != 0)
-            cm_UpdateVolumeStatusInt(volp, &volp->bk);
+        afs_uint32 volType;
+        for ( volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
+            if (volp->vol[volType].ID != 0)
+                cm_UpdateVolumeStatusInt(volp, &volp->vol[volType]);
+        }
     }
 }
 
@@ -1313,16 +1306,16 @@ void cm_ChangeRankVolume(cm_server_t *tsp)
        code = 1 ;      /* assume that list is unchanged */
        InterlockedIncrement(&volp->refCount);
        lock_ReleaseRead(&cm_volumeLock);
-       lock_ObtainMutex(&volp->mx);
+       lock_ObtainWrite(&volp->rw);
 
-       if ((tsp->cellp==volp->cellp) && (volp->ro.serversp))
-           code =cm_ChangeRankServer(&volp->ro.serversp, tsp);
+       if ((tsp->cellp==volp->cellp) && (volp->vol[ROVOL].serversp))
+           code =cm_ChangeRankServer(&volp->vol[ROVOL].serversp, tsp);
 
        /* this volume list was changed */
        if ( !code )
-           cm_RandomizeServer(&volp->ro.serversp);
+           cm_RandomizeServer(&volp->vol[ROVOL].serversp);
 
-       lock_ReleaseMutex(&volp->mx);
+       lock_ReleaseWrite(&volp->rw);
        lock_ObtainRead(&cm_volumeLock);
         refCount = InterlockedDecrement(&volp->refCount);
        osi_assertx(refCount >= 0, "cm_volume_t refCount underflow");
@@ -1351,7 +1344,7 @@ int cm_DumpVolumes(FILE *outputFile, char *cookie, int lock)
     for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp)
     {
         sprintf(output, "%s - volp=0x%p cell=%s name=%s rwID=%u roID=%u bkID=%u flags=0x%x refCount=%u\r\n", 
-                 cookie, volp, volp->cellp->name, volp->namep, volp->rw.ID, volp->ro.ID, volp->bk.ID, volp->flags, 
+                 cookie, volp, volp->cellp->name, volp->namep, volp->vol[RWVOL].ID, volp->vol[ROVOL].ID, volp->vol[BACKVOL].ID, volp->flags, 
                  volp->refCount);
         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
     }
@@ -1431,19 +1424,7 @@ void cm_AddVolumeToIDHashTable(cm_volume_t *volp, afs_uint32 volType)
     int i;
     struct cm_vol_state * statep;
 
-    switch (volType) {
-    case RWVOL:
-        statep = &volp->rw;
-        break;
-    case ROVOL:                                
-        statep = &volp->ro;
-        break;
-    case BACKVOL:
-        statep = &volp->bk;
-        break;
-    default:
-        return;
-    }
+    statep = cm_VolumeStateByType(volp, volType);
 
     if (statep->flags & CM_VOLUMEFLAG_IN_HASH)
         return;
@@ -1476,19 +1457,7 @@ void cm_RemoveVolumeFromIDHashTable(cm_volume_t *volp, afs_uint32 volType)
     struct cm_vol_state * statep;
     int i;
        
-    switch (volType) {
-    case RWVOL:
-        statep = &volp->rw;
-        break;
-    case ROVOL:                                
-        statep = &volp->ro;
-        break;
-    case BACKVOL:
-        statep = &volp->bk;
-        break;
-    default:
-        return;
-    }
+    statep = cm_VolumeStateByType(volp, volType);
 
     if (statep->flags & CM_VOLUMEFLAG_IN_HASH) {
        /* hash it out first */
@@ -1507,6 +1476,8 @@ void cm_RemoveVolumeFromIDHashTable(cm_volume_t *volp, afs_uint32 volType)
             lvolpp = &cm_data.volumeBKIDHashTablep[i];
             tvolp = cm_data.volumeBKIDHashTablep[i];
             break;
+        default:
+            osi_assertx(0, "invalid volume type");
         }
        do {
            if (tvolp == volp) {
@@ -1516,20 +1487,8 @@ void cm_RemoveVolumeFromIDHashTable(cm_volume_t *volp, afs_uint32 volType)
                break;
            }
 
-            switch (volType) {
-            case RWVOL:
-                lvolpp = &tvolp->rw.nextp;
-                tvolp = tvolp->rw.nextp;
-                break;
-            case ROVOL:                                
-                lvolpp = &tvolp->ro.nextp;
-                tvolp = tvolp->ro.nextp;
-                break;
-            case BACKVOL:
-                lvolpp = &tvolp->bk.nextp;
-                tvolp = tvolp->bk.nextp;
-                break;
-            }
+            lvolpp = &tvolp->vol[volType].nextp;
+            tvolp = tvolp->vol[volType].nextp;
        } while(tvolp);
     }
 }
@@ -1595,11 +1554,11 @@ void cm_VolumeStatusNotification(cm_volume_t * volp, afs_uint32 volID, enum vols
     char volstr[CELL_MAXNAMELEN + VL_MAXNAMELEN]="";
     char *ext = "";
 
-    if (volID == volp->rw.ID)
+    if (volID == volp->vol[RWVOL].ID)
         ext = "";
-    else if (volID == volp->ro.ID)
+    else if (volID == volp->vol[ROVOL].ID)
         ext = ".readonly";
-    else if (volID == volp->bk.ID)
+    else if (volID == volp->vol[BACKVOL].ID)
         ext = ".backup";
     else
         ext = ".nomatch";
@@ -1613,15 +1572,11 @@ void cm_VolumeStatusNotification(cm_volume_t * volp, afs_uint32 volID, enum vols
 
 enum volstatus cm_GetVolumeStatus(cm_volume_t *volp, afs_uint32 volID)
 {
-    if (volp->rw.ID == volID) {
-        return volp->rw.state;
-    } else if (volp->ro.ID == volID) {
-        return volp->ro.state;
-    } else if (volp->bk.ID == volID) {
-        return volp->bk.state;
-    } else {
+    cm_vol_state_t * statep = cm_VolumeStateByID(volp, volID);
+    if (statep)
+        return statep->state;
+    else
         return vl_unknown;
-    }
 }
 
 /* Renew .readonly volume callbacks that are more than
@@ -1640,7 +1595,7 @@ cm_VolumeRenewROCallbacks(void)
             cm_fid_t      fid;
             cm_scache_t * scp;
 
-            cm_SetFid(&fid, volp->cellp->cellID, volp->ro.ID, 1, 1);
+            cm_SetFid(&fid, volp->cellp->cellID, volp->vol[ROVOL].ID, 1, 1);
 
             cm_InitReq(&req);
 
@@ -1656,3 +1611,41 @@ cm_VolumeRenewROCallbacks(void)
     }
     lock_ReleaseRead(&cm_volumeLock);
 }
+
+cm_vol_state_t * 
+cm_VolumeStateByType(cm_volume_t *volp, afs_uint32 volType)
+{
+    return &volp->vol[volType];
+}
+
+cm_vol_state_t * 
+cm_VolumeStateByID(cm_volume_t *volp, afs_uint32 id)
+{
+    cm_vol_state_t * statep = NULL;
+
+    if (id == volp->vol[RWVOL].ID)
+        statep = &volp->vol[RWVOL];
+    else if (id == volp->vol[ROVOL].ID)
+        statep = &volp->vol[ROVOL];
+    else if (id == volp->vol[BACKVOL].ID)
+        statep = &volp->vol[BACKVOL];
+
+    return(statep);
+}
+
+cm_vol_state_t * 
+cm_VolumeStateByName(cm_volume_t *volp, char *volname)
+{
+    size_t len = strlen(volname);
+    cm_vol_state_t *statep;
+
+    if (stricmp(".readonly", &volname[len-9]) == 0)
+        statep = &volp->vol[ROVOL];
+    else if (stricmp(".backup", &volname[len-7]) == 0)
+        statep = &volp->vol[BACKVOL];
+    else 
+        statep = &volp->vol[RWVOL];
+
+    return statep;
+}
+
index cb8bdd670d904e31b13f000cd21e349f03a28898..c27104a56fde843145465d7aff899f65b4407b79 100644 (file)
 
 #define CM_VOLUME_MAGIC    ('V' | 'O' <<8 | 'L'<<16 | 'M'<<24)
 
+/* 
+ *
+ */
+
 typedef struct cm_vol_state {
     struct cm_volume *nextp;            /* volumeIDHashTable; by cm_volumeLock */
-    afs_uint32      ID;                 /* by mx */
+    afs_uint32      ID;                 /* by rw */
     struct cm_fid dotdotFid;           /* parent of volume root */
-    cm_serverRef_t *serversp;           /* by mx */
-    enum volstatus  state;              /* by mx */
-    afs_uint32      flags;              /* by mx */
+    cm_serverRef_t *serversp;           /* by cm_serverLock */
+    enum volstatus  state;              /* by rw */
+    afs_uint32      flags;              /* by rw */
 } cm_vol_state_t;
 
+/* RWVOL, ROVOL, BACKVOL are defined in cm.h */
+#define NUM_VOL_TYPES 3
+
 typedef struct cm_volume {
     osi_queue_t q;                      /* LRU queue; cm_volumeLock */
     afs_uint32  magic;
@@ -31,11 +38,9 @@ typedef struct cm_volume {
     cm_cell_t *cellp;                  /* never changes */
     char namep[VL_MAXNAMELEN];         /* name of the normal volume - assigned during allocation; */
                                         /* by cm_volumeLock */
-    struct cm_vol_state rw;            /* by cm_volumeLock */
-    struct cm_vol_state ro;            /* by cm_volumeLock */
-    struct cm_vol_state bk;            /* by cm_volumeLock */
-    osi_mutex_t mx;
-    afs_uint32 flags;                  /* by mx */
+    struct cm_vol_state vol[NUM_VOL_TYPES]; /* by cm_volumeLock */
+    osi_rwlock_t rw;
+    afs_uint32 flags;                  /* by rw */
     afs_int32 refCount;                        /* by Interlocked operations */
     time_t cbExpiresRO;                 /* latest RO expiration time; by cm_scacheLock */
 } cm_volume_t;
@@ -43,6 +48,7 @@ typedef struct cm_volume {
 #define CM_VOLUMEFLAG_RESET       1    /* reload this info on next use */
 #define CM_VOLUMEFLAG_IN_HASH      2
 #define CM_VOLUMEFLAG_IN_LRU_QUEUE 4
+#define CM_VOLUMEFLAG_UPDATING_VL  8
 
 
 typedef struct cm_volumeRef {
@@ -126,5 +132,11 @@ extern enum volstatus cm_GetVolumeStatus(cm_volume_t *volp, afs_uint32 volID);
 
 extern void cm_VolumeRenewROCallbacks(void);
 
+extern cm_vol_state_t * cm_VolumeStateByType(cm_volume_t *volp, afs_uint32 type);
+
+extern cm_vol_state_t * cm_VolumeStateByID(cm_volume_t *volp, afs_uint32 id);
+
+extern cm_vol_state_t * cm_VolumeStateByName(cm_volume_t *volp, char *volname);
+
 extern osi_rwlock_t cm_volumeLock;
 #endif /*  __CM_VOLUME_H_ENV__ */