From 6bb168751bfd040490ee8ff55ccdb28655c5ab8d Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 14 Apr 2008 23:44:03 +0000 Subject: [PATCH] DEVEL15-windows-volume-20080414 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 | 1 + src/WINNT/afsd/cm_callback.c | 8 +- src/WINNT/afsd/cm_conn.c | 37 +-- src/WINNT/afsd/cm_ioctl.c | 31 +- src/WINNT/afsd/cm_performance.c | 24 +- src/WINNT/afsd/cm_scache.c | 10 +- src/WINNT/afsd/cm_vnodeops.c | 42 +-- src/WINNT/afsd/cm_volume.c | 515 ++++++++++++++++---------------- src/WINNT/afsd/cm_volume.h | 30 +- 9 files changed, 319 insertions(+), 379 deletions(-) diff --git a/src/WINNT/afsd/cm.h b/src/WINNT/afsd/cm.h index 14e1c91ba..5101f4cd4 100644 --- a/src/WINNT/afsd/cm.h +++ b/src/WINNT/afsd/cm.h @@ -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 diff --git a/src/WINNT/afsd/cm_callback.c b/src/WINNT/afsd/cm_callback.c index f1489f908..60dd6a05f 100644 --- a/src/WINNT/afsd/cm_callback.c +++ b/src/WINNT/afsd/cm_callback.c @@ -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; diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index 8c292b046..baca5e385 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -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); diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index 0c6254687..72ce2db93 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -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; diff --git a/src/WINNT/afsd/cm_performance.c b/src/WINNT/afsd/cm_performance.c index fd112703e..5ecd84ea7 100644 --- a/src/WINNT/afsd/cm_performance.c +++ b/src/WINNT/afsd/cm_performance.c @@ -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) { diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index 51fdc5ab5..dcf89acd6 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -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) diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 2ae418212..3a81f8594 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -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); diff --git a/src/WINNT/afsd/cm_volume.c b/src/WINNT/afsd/cm_volume.c index 7e30ec94c..4bdd89b6d 100644 --- a/src/WINNT/afsd/cm_volume.c +++ b/src/WINNT/afsd/cm_volume.c @@ -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; irw.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; +} + diff --git a/src/WINNT/afsd/cm_volume.h b/src/WINNT/afsd/cm_volume.h index cb8bdd670..c27104a56 100644 --- a/src/WINNT/afsd/cm_volume.h +++ b/src/WINNT/afsd/cm_volume.h @@ -14,15 +14,22 @@ #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__ */ -- 2.39.5