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 )
{
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;
- } 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 if (code == CM_ERROR_NOSUCHVOLUME || code == VL_NOENT || code == VL_BADNAME) {
+ volp->flags |= CM_VOLUMEFLAG_NOEXIST;
} else {
rwNewstate = roNewstate = bkNewstate = vl_alldown;
}
volp->vol[BACKVOL].state = bkNewstate;
}
+ volp->lastUpdateTime = time(0);
+
if (code == 0)
volp->flags &= ~CM_VOLUMEFLAG_RESET;
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 mount point target updates */
+ if (cm_data.mountRootGen + lifetime <= now)
+ cm_data.mountRootGen = now;
- /* force a re-loading of volume data from the vldb */
+ /*
+ * 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
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 */
#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;
extern void cm_ChangeRankVolume(cm_server_t *tsp);
-extern void cm_RefreshVolumes(void);
+extern void cm_RefreshVolumes(int lifetime);
extern long cm_ValidateVolume(void);