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 )
{
}
}
- /* clear out old bindings */
- for ( volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
- if (volp->vol[volType].serversp)
- cm_FreeServerList(&volp->vol[volType].serversp, CM_FREESERVERLIST_DELETE);
- }
-
volp->flags |= CM_VOLUMEFLAG_UPDATING_VL;
lock_ReleaseWrite(&volp->rw);
}
/* We can end up here with code == CM_ERROR_NOSUCHVOLUME if the base volume name
- * does not exist but there might exist a .readonly volume. If the base name
- * doesn't exist we will not care about the .backup that might be left behind
- * since there should be no method to access it.
+ * does not exist and is not a numeric string but there might exist a .readonly volume.
+ * If the base name 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->vol[RWVOL].ID == 0 && strlen(volp->namep) < (VL_MAXNAMELEN - 9)) {
+ if (code == CM_ERROR_NOSUCHVOLUME &&
+ _atoi64(volp->namep) == 0 &&
+ volp->vol[RWVOL].ID == 0 &&
+ strlen(volp->namep) < (VL_MAXNAMELEN - 9)) {
char name[VL_MAXNAMELEN];
snprintf(name, VL_MAXNAMELEN, "%s.readonly", volp->namep);
rwServers_alldown = 0;
#endif
+ /* clear out old bindings */
+ for ( volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
+ if (volp->vol[volType].serversp)
+ cm_FreeServerList(&volp->vol[volType].serversp, CM_FREESERVERLIST_DELETE);
+ }
+
memset(serverUUID, 0, sizeof(serverUUID));
switch ( method ) {
serverUUID[j] = uuid;
}
- xdr_free(addrs.bulkaddrs_val, addrs.bulkaddrs_len * sizeof(*addrs.bulkaddrs_val));
+ xdr_free((xdrproc_t) xdr_bulkaddrs, &addrs);
if (nentries == 0)
code = CM_ERROR_INVAL;
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;
if (code == 0) {
*outVolpp = volp;
- if (!(flags & CM_GETVOL_FLAG_NO_LRU_UPDATE)) {
+ if ((volp->flags & CM_VOLUMEFLAG_IN_LRU_QUEUE) &&
+ !(flags & CM_GETVOL_FLAG_NO_LRU_UPDATE)) {
lock_ObtainWrite(&cm_volumeLock);
cm_AdjustVolumeLRU(volp);
lock_ReleaseWrite(&cm_volumeLock);
}
} else {
+ /*
+ * do not return it to the caller but do insert it in the LRU
+ * otherwise it will be lost
+ */
lock_ObtainRead(&cm_volumeLock);
+ if (!(volp->flags & CM_VOLUMEFLAG_IN_LRU_QUEUE) ||
+ (flags & CM_GETVOL_FLAG_NO_LRU_UPDATE))
+ cm_AdjustVolumeLRU(volp);
cm_PutVolume(volp);
lock_ReleaseRead(&cm_volumeLock);
}
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
char motd[256];
long alldown, alldeleted;
cm_serverRef_t *serversp;
+ cm_fid_t fid;
Name = volName;
OfflineMsg = offLineMsg;
MOTD = motd;
if (statep->ID != 0 && (!volID || volID == statep->ID)) {
+ /* create fid for volume root so that VNOVOL and VMOVED errors can be processed */
+ cm_SetFid(&fid, volp->cellp->cellID, statep->ID, 1, 1);
+
if (!statep->serversp && !(*volumeUpdatedp)) {
cm_InitReq(&req);
code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp);
code = RXAFS_GetVolumeStatus(rxconnp, statep->ID,
&volStat, &Name, &OfflineMsg, &MOTD);
rx_PutConnection(rxconnp);
-
- } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code));
+ } while (cm_Analyze(connp, cm_rootUserp, &req, &fid, NULL, NULL, NULL, code));
code = cm_MapRPCError(code, &req);
lock_ObtainWrite(&volp->rw);
/* must be called with cm_volumeLock write-locked! */
void cm_AdjustVolumeLRU(cm_volume_t *volp)
{
- if (volp == cm_data.volumeLRULastp)
- cm_data.volumeLRULastp = (cm_volume_t *) osi_QPrev(&volp->q);
+ if (volp == cm_data.volumeLRUFirstp)
+ return;
+
if (volp->flags & CM_VOLUMEFLAG_IN_LRU_QUEUE)
osi_QRemoveHT((osi_queue_t **) &cm_data.volumeLRUFirstp, (osi_queue_t **) &cm_data.volumeLRULastp, &volp->q);
- osi_QAdd((osi_queue_t **) &cm_data.volumeLRUFirstp, &volp->q);
+ osi_QAddH((osi_queue_t **) &cm_data.volumeLRUFirstp, (osi_queue_t **) &cm_data.volumeLRULastp, &volp->q);
volp->flags |= CM_VOLUMEFLAG_IN_LRU_QUEUE;
- if (!cm_data.volumeLRULastp)
- cm_data.volumeLRULastp = volp;
}
/* must be called with cm_volumeLock write-locked! */
if (volp == cm_data.volumeLRULastp)
return;
- if (volp == cm_data.volumeLRUFirstp)
- cm_data.volumeLRUFirstp = (cm_volume_t *) osi_QNext(&volp->q);
if (volp->flags & CM_VOLUMEFLAG_IN_LRU_QUEUE)
osi_QRemoveHT((osi_queue_t **) &cm_data.volumeLRUFirstp, (osi_queue_t **) &cm_data.volumeLRULastp, &volp->q);
osi_QAddT((osi_queue_t **) &cm_data.volumeLRUFirstp, (osi_queue_t **) &cm_data.volumeLRULastp, &volp->q);
volp->flags |= CM_VOLUMEFLAG_IN_LRU_QUEUE;
- if (!cm_data.volumeLRULastp)
- cm_data.volumeLRULastp = volp;
}
/* must be called with cm_volumeLock write-locked! */
void cm_RemoveVolumeFromLRU(cm_volume_t *volp)
{
if (volp->flags & CM_VOLUMEFLAG_IN_LRU_QUEUE) {
- if (volp == cm_data.volumeLRULastp)
- cm_data.volumeLRULastp = (cm_volume_t *) osi_QPrev(&volp->q);
osi_QRemoveHT((osi_queue_t **) &cm_data.volumeLRUFirstp, (osi_queue_t **) &cm_data.volumeLRULastp, &volp->q);
volp->flags &= ~CM_VOLUMEFLAG_IN_LRU_QUEUE;
}