diff --git a/src/WINNT/afsd/cm_daemon.c b/src/WINNT/afsd/cm_daemon.c index fac1be3682..72ec250962 100644 --- a/src/WINNT/afsd/cm_daemon.c +++ b/src/WINNT/afsd/cm_daemon.c @@ -507,11 +507,15 @@ void cm_Daemon(long parm) cm_VolStatus_Network_Addr_Change(); } - if (now > lastVolCheck + cm_daemonCheckVolInterval && + /* + * Once every five minutes inspect the volume list and enforce + * the volume location expiration time. + */ + if (now > lastVolCheck + 300 && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastVolCheck = now; - cm_RefreshVolumes(); + cm_RefreshVolumes(cm_daemonCheckVolInterval); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index b25cc0cfa9..a9bcf15bd5 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -1285,7 +1285,7 @@ cm_IoctlCheckServers(struct cm_ioctl *ioctlp, struct cm_user *userp) afs_int32 cm_IoctlCheckVolumes(cm_ioctl_t *ioctlp, cm_user_t *userp) { - cm_RefreshVolumes(); + cm_RefreshVolumes(0); return 0; } diff --git a/src/WINNT/afsd/cm_memmap.c b/src/WINNT/afsd/cm_memmap.c index 3b94612916..6fb91ed220 100644 --- a/src/WINNT/afsd/cm_memmap.c +++ b/src/WINNT/afsd/cm_memmap.c @@ -874,7 +874,7 @@ cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD max cm_data.buf_blockSize = blockSize; cm_data.buf_hashSize = osi_PrimeLessThan((afs_uint32)(cacheBlocks/7 + 1)); - cm_data.mountRootGen = time(NULL); + cm_data.mountRootGen = 0; baseAddress += ComputeSizeOfConfigData(); cm_data.volumeBaseAddress = (cm_volume_t *) baseAddress; diff --git a/src/WINNT/afsd/cm_scache.h b/src/WINNT/afsd/cm_scache.h index 5bfc6fa1b9..a04f314027 100644 --- a/src/WINNT/afsd/cm_scache.h +++ b/src/WINNT/afsd/cm_scache.h @@ -145,7 +145,7 @@ typedef struct cm_scache { * the link contents here. */ cm_fid_t mountRootFid; /* mounted on root */ - time_t mountRootGen; /* time to update mountRootFidp? */ + time_t mountRootGen; /* time to update mountRootFid? */ cm_fid_t dotdotFid; /* parent of volume root */ /* callback info */ diff --git a/src/WINNT/afsd/cm_volume.c b/src/WINNT/afsd/cm_volume.c index 9976fe53b3..ffdfa43fa7 100644 --- a/src/WINNT/afsd/cm_volume.c +++ b/src/WINNT/afsd/cm_volume.c @@ -190,6 +190,17 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t * lock_AssertWrite(&volp->rw); + /* + * If the last volume update was in the last five + * minutes and it did not exist, then avoid the RPC + * and return No Such Volume immediately. + */ + if ((volp->flags & CM_VOLUMEFLAG_NOEXIST) && + volp->lastUpdateTime + 600 < time(0)) + { + return CM_ERROR_NOSUCHVOLUME; + } + #ifdef AFS_FREELANCE_CLIENT if ( cellp->cellID == AFS_FAKE_ROOT_CELL_ID && volp->vol[RWVOL].ID == AFS_FAKE_ROOT_VOL_ID ) { @@ -614,28 +625,13 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t * cm_RandomizeServer(&volp->vol[ROVOL].serversp); } - rwNewstate = rwServers_alldown ? vl_alldown : vl_online; roNewstate = roServers_alldown ? vl_alldown : vl_online; bkNewstate = bkServers_alldown ? vl_alldown : vl_online; + + volp->flags &= ~CM_VOLUMEFLAG_NOEXIST; } else if (code == CM_ERROR_NOSUCHVOLUME || code == VL_NOENT || code == VL_BADNAME) { - /* this volume does not exist - we should discard it */ - if (volp->flags & CM_VOLUMEFLAG_IN_HASH) - cm_RemoveVolumeFromNameHashTable(volp); - 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); - - volp->namep[0] ='\0'; + volp->flags |= CM_VOLUMEFLAG_NOEXIST; } else { rwNewstate = roNewstate = bkNewstate = vl_alldown; } @@ -656,6 +652,8 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t * volp->vol[BACKVOL].state = bkNewstate; } + volp->lastUpdateTime = time(0); + if (code == 0) volp->flags &= ~CM_VOLUMEFLAG_RESET; @@ -1144,48 +1142,40 @@ long cm_GetROVolumeID(cm_volume_t *volp) return id; } -void cm_RefreshVolumes(void) +void cm_RefreshVolumes(int lifetime) { cm_volume_t *volp; cm_scache_t *scp; afs_int32 refCount; + time_t now; - cm_data.mountRootGen = time(NULL); + now = time(NULL); - /* force a re-loading of volume data from the vldb */ + /* force mount point target updates */ + if (cm_data.mountRootGen + lifetime <= now) + cm_data.mountRootGen = now; + + /* + * force a re-loading of volume data from the vldb + * if the lifetime for the cached data has expired + */ lock_ObtainRead(&cm_volumeLock); for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp) { InterlockedIncrement(&volp->refCount); lock_ReleaseRead(&cm_volumeLock); - lock_ObtainWrite(&volp->rw); - volp->flags |= CM_VOLUMEFLAG_RESET; - lock_ReleaseWrite(&volp->rw); - + if (!(volp->flags & CM_VOLUMEFLAG_RESET)) { + lock_ObtainWrite(&volp->rw); + if (volp->lastUpdateTime + lifetime <= now) + volp->flags |= CM_VOLUMEFLAG_RESET; + lock_ReleaseWrite(&volp->rw); + } + lock_ObtainRead(&cm_volumeLock); refCount = InterlockedDecrement(&volp->refCount); osi_assertx(refCount >= 0, "cm_volume_t refCount underflow"); } lock_ReleaseRead(&cm_volumeLock); - - /* force mount points to be re-evaluated so that - * if the volume location has changed we will pick - * that up - */ - for ( scp = cm_data.scacheLRUFirstp; - scp; - scp = (cm_scache_t *) osi_QNext(&scp->q)) { - if ( scp->fileType == CM_SCACHETYPE_MOUNTPOINT -#ifdef AFS_FREELANCE_CLIENT - && !(scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID) -#endif - ) { - lock_ObtainWrite(&scp->rw); - scp->mountPointStringp[0] = '\0'; - lock_ReleaseWrite(&scp->rw); - } - } - } void diff --git a/src/WINNT/afsd/cm_volume.h b/src/WINNT/afsd/cm_volume.h index 7ec1a8c7a7..44f92c6eec 100644 --- a/src/WINNT/afsd/cm_volume.h +++ b/src/WINNT/afsd/cm_volume.h @@ -45,6 +45,7 @@ typedef struct cm_volume { struct cm_server *cbServerpRO; /* server granting RO callback; by cm_scacheLock */ time_t cbExpiresRO; /* latest RO expiration time; by cm_scacheLock */ time_t creationDateRO; /* latest volume creation date; 0 if unknown; by cm_scacheLock */ + time_t lastUpdateTime; /* most recent volume location update cm_volumeLock */ } cm_volume_t; #define CM_VOLUMEFLAG_RESET 1 /* reload this info on next use */ @@ -52,6 +53,7 @@ typedef struct cm_volume { #define CM_VOLUMEFLAG_IN_LRU_QUEUE 4 #define CM_VOLUMEFLAG_UPDATING_VL 8 #define CM_VOLUMEFLAG_DFS_VOLUME 16 +#define CM_VOLUMEFLAG_NOEXIST 32 typedef struct cm_volumeRef { struct cm_volumeRef * next; @@ -100,7 +102,7 @@ extern cm_serverRef_t **cm_GetVolServers(cm_volume_t *volp, afs_uint32 volume, extern void cm_ChangeRankVolume(cm_server_t *tsp); -extern void cm_RefreshVolumes(void); +extern void cm_RefreshVolumes(int lifetime); extern long cm_ValidateVolume(void);