From: Jeffrey Altman Date: Thu, 11 Sep 2008 18:26:21 +0000 (+0000) Subject: DEVEL15-windows-vnovol-20080911 X-Git-Tag: openafs-devel-1_5_53~38 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=a7d08b3bf9f9d96eaf68c024ab2c1a5465849586;p=packages%2Fo%2Fopenafs.git DEVEL15-windows-vnovol-20080911 LICENSE MIT Modify MSG_SERVER_REPORTS_VNOVOL to mention that the volume may have been moved or deleted. In cm_Analyze(), do not call cm_ForceUpdateVolume() or force a retry when processing CM_ERROR_NOSUCHVOLUME. This CM error value is the result of a VNOVOL already being processed which would have forced the update. When a VMOVED or VNOVOL error is received, remove the volume id from the server's volume list. If cm_ForceUpdateVolume() returns a failure, do not retry if a VMOVED or VNOVOL error was received. Make sure that if a cm_serverRef_t object is marked srv_deleted that its references not be used. Now that cm_ForceUpdateVolume() is being called only when processing VMOVED and VNOVOL errors, permit it to call cm_UpdateVolumeLocation() immediately. Refactor cm_CheckOfflineVolume() to reduce code duplication. (cherry picked from commit 5ea02ad1e2bdb98bea27e11c1372f90d1940de17) --- diff --git a/src/WINNT/afsd/afsd_eventmessages.mc b/src/WINNT/afsd/afsd_eventmessages.mc index 2cab32c3b..f01059d0d 100644 --- a/src/WINNT/afsd/afsd_eventmessages.mc +++ b/src/WINNT/afsd/afsd_eventmessages.mc @@ -114,7 +114,7 @@ Severity=Warning Facility=System SymbolicName=MSG_SERVER_REPORTS_VNOVOL Language=English -Server %1 reported volume %2 as not attached. +Server %1 reported volume %2 as not attached (may have been moved or deleted). . MessageId= diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index 8240c6c99..81b17ec86 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -266,14 +266,10 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, */ else if (errorCode == CM_ERROR_NOSUCHVOLUME) { osi_Log0(afsd_logp, "cm_Analyze passed CM_ERROR_NOSUCHVOLUME."); - if (timeLeft > 7) { - thrd_Sleep(5000); - - retry = 1; - - if (fidp != NULL) /* Not a VLDB call */ - cm_ForceUpdateVolume(fidp, userp, reqp); - } + /* + * The VNOVOL or VL_NOENT error has already been translated + * to CM_ERROR_NOSUCHVOLUME. There is nothing for us to do. + */ } else if (errorCode == CM_ERROR_ALLDOWN) { @@ -431,7 +427,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, switch ( errorCode ) { case VNOVOL: msgID = MSG_SERVER_REPORTS_VNOVOL; - format = "Server %s reported volume %d as not attached."; + format = "Server %s reported volume %d as not attached (does not exist)."; break; case VMOVED: msgID = MSG_SERVER_REPORTS_VMOVED; @@ -482,6 +478,8 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, /* REDIRECT */ if (errorCode == VMOVED || errorCode == VNOVOL) { tsrp->status = srv_deleted; + if (fidp) + cm_RemoveVolumeFromServer(serverp, fidp->volume); } else { tsrp->status = srv_offline; } @@ -499,8 +497,11 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, } lock_ReleaseWrite(&cm_serverLock); - if (fidp && (errorCode == VMOVED || errorCode == VNOVOL)) - cm_ForceUpdateVolume(fidp, userp, reqp); + if (fidp && (errorCode == VMOVED || errorCode == VNOVOL)) { + code = cm_ForceUpdateVolume(fidp, userp, reqp); + if (code) + timeLeft = 0; /* prevent a retry on failure */ + } if (statep) { cm_UpdateVolumeStatus(volp, statep->ID); @@ -812,11 +813,9 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, if (tsp) { cm_GetServerNoLock(tsp); lock_ReleaseRead(&cm_serverLock); - if (!(tsp->flags & CM_SERVERFLAG_DOWN)) { + if ((tsrp->status != srv_deleted) && !(tsp->flags & CM_SERVERFLAG_DOWN)) { allDown = 0; - if (tsrp->status == srv_deleted) { - /* skip this entry. no longer valid. */; - } else if (tsrp->status == srv_busy) { + if (tsrp->status == srv_busy) { allOffline = 0; someBusy = 1; } else if (tsrp->status == srv_offline) { @@ -1044,7 +1043,7 @@ long cm_ServerAvailable(struct cm_fid *fidp, struct cm_user *userp) lock_ObtainRead(&cm_serverLock); for (tsrp = *serverspp; tsrp; tsrp=tsrp->next) { tsp = tsrp->server; - if (!(tsp->flags & CM_SERVERFLAG_DOWN)) { + if ((tsrp->status != srv_deleted) && !(tsp->flags & CM_SERVERFLAG_DOWN)) { allDown = 0; if (tsrp->status == srv_busy) { allOffline = 0; diff --git a/src/WINNT/afsd/cm_volume.c b/src/WINNT/afsd/cm_volume.c index 4bf058443..5af199377 100644 --- a/src/WINNT/afsd/cm_volume.c +++ b/src/WINNT/afsd/cm_volume.c @@ -107,7 +107,7 @@ void cm_InitVolume(int newFile, long maxVols) 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); + cm_VolumeStatusNotification(volp, volp->vol[volType].ID, vl_unknown, volp->vol[volType].state); } volp->cbExpiresRO = 0; } @@ -910,7 +910,12 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep, return code; } -void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp) +/* + * Only call this function in response to a VNOVOL or VMOVED error + * from a file server. Do not call it in response to CM_ERROR_NOSUCHVOLUME + * as that can lead to recursive calls. + */ +long cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp) { cm_cell_t *cellp; cm_volume_t *volp; @@ -918,11 +923,14 @@ void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp) cm_volume_t *volp2; #endif afs_uint32 hash; + long code; - if (!fidp) return; + if (!fidp) + return CM_ERROR_INVAL; cellp = cm_FindCellByID(fidp->cell, 0); - if (!cellp) return; + if (!cellp) + return CM_ERROR_NOSUCHCELL; /* search for the volume */ lock_ObtainRead(&cm_volumeLock); @@ -970,30 +978,21 @@ void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp) lock_ReleaseRead(&cm_volumeLock); if (!volp) - return; + return CM_ERROR_NOSUCHVOLUME; /* update it */ cm_data.mountRootGen = time(NULL); lock_ObtainWrite(&volp->rw); volp->flags |= CM_VOLUMEFLAG_RESET; -#ifdef COMMENT - /* Mark the volume to be updated but don't update it now. - * This function is called only from within cm_Analyze - * when cm_ConnByMServers has failed with all servers down - * The problem is that cm_UpdateVolume is going to call - * cm_ConnByMServers which may cause a recursive chain - * of calls each returning a retry on failure. - * Instead, set the flag so the next time the volume is - * accessed by Name or ID the UpdateVolume call will - * occur. - */ + code = cm_UpdateVolumeLocation(cellp, userp, reqp, volp); -#endif lock_ReleaseWrite(&volp->rw); lock_ObtainRead(&cm_volumeLock); cm_PutVolume(volp); lock_ReleaseRead(&cm_volumeLock); + + return code; } /* find the appropriate servers from a volume */ @@ -1088,12 +1087,9 @@ void cm_RefreshVolumes(void) } - -/* The return code is 0 if the volume is not online and - * 1 if the volume is online - */ -long -cm_CheckOfflineVolume(cm_volume_t *volp, afs_uint32 volID) +void +cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, afs_uint32 volID, + afs_uint32 *onlinep, afs_uint32 *volumeUpdatedp) { cm_conn_t *connp; long code; @@ -1106,140 +1102,101 @@ cm_CheckOfflineVolume(cm_volume_t *volp, afs_uint32 volID) char volName[32]; char offLineMsg[256]; char motd[256]; - long online = 0; + long alldown, alldeleted; cm_serverRef_t *serversp; Name = volName; OfflineMsg = offLineMsg; MOTD = motd; - lock_ObtainWrite(&volp->rw); - - if (volp->flags & CM_VOLUMEFLAG_RESET) { - cm_InitReq(&req); - code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp); - } - - if (volp->vol[RWVOL].ID != 0 && (!volID || volID == volp->vol[RWVOL].ID) && - volp->vol[RWVOL].serversp) { - - for (serversp = volp->vol[RWVOL].serversp; serversp; serversp = serversp->next) { - if (serversp->status == srv_busy || serversp->status == srv_offline) { - serversp->status = srv_not_busy; - online = 1; - } - } - - if (volp->vol[RWVOL].state == vl_busy || volp->vol[RWVOL].state == vl_offline || volp->vol[RWVOL].state == vl_unknown) { + if (statep->ID != 0 && (!volID || volID == statep->ID)) { + if (!statep->serversp && !(*volumeUpdatedp)) { cm_InitReq(&req); - - lock_ReleaseWrite(&volp->rw); - do { - code = cm_ConnFromVolume(volp, volp->vol[RWVOL].ID, cm_rootUserp, &req, &connp); - if (code) - continue; - - rxconnp = cm_GetRxConn(connp); - code = RXAFS_GetVolumeStatus(rxconnp, volp->vol[RWVOL].ID, - &volStat, &Name, &OfflineMsg, &MOTD); - rx_PutConnection(rxconnp); - - } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code)); - code = cm_MapRPCError(code, &req); - - lock_ObtainWrite(&volp->rw); - if (code == 0 && volStat.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->vol[RWVOL].ID, volp->vol[RWVOL].state, vl_unknown); - volp->vol[RWVOL].state = vl_unknown; - online = 1; - } + code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp); + *volumeUpdatedp = 1; } - } - if (volp->vol[ROVOL].ID != 0 && (!volID || volID == volp->vol[ROVOL].ID) && - volp->vol[ROVOL].serversp) { + if (statep->serversp) { + alldown = 1; + alldeleted = 1; + for (serversp = statep->serversp; serversp; serversp = serversp->next) { + if (serversp->status != srv_deleted) { + alldeleted = 0; + *onlinep = 1; + alldown = 0; + } + if (serversp->status == srv_busy || serversp->status == srv_offline) + serversp->status = srv_not_busy; + } - for (serversp = volp->vol[ROVOL].serversp; serversp; serversp = serversp->next) { - if (serversp->status == srv_busy || serversp->status == srv_offline) { - serversp->status = srv_not_busy; - online = 1; + if (alldeleted && !(*volumeUpdatedp)) { + cm_InitReq(&req); + code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp); + *volumeUpdatedp = 1; } - } - if (volp->vol[ROVOL].state == vl_busy || volp->vol[ROVOL].state == vl_offline || volp->vol[ROVOL].state == vl_unknown) { - cm_InitReq(&req); + if (statep->state == vl_busy || statep->state == vl_offline || statep->state == vl_unknown || + (!alldown && statep->state == vl_alldown)) { + cm_InitReq(&req); - lock_ReleaseWrite(&volp->rw); - do { - code = cm_ConnFromVolume(volp, volp->vol[ROVOL].ID, cm_rootUserp, &req, &connp); - if (code) - continue; + lock_ReleaseWrite(&volp->rw); + do { + code = cm_ConnFromVolume(volp, statep->ID, cm_rootUserp, &req, &connp); + if (code) + continue; - rxconnp = cm_GetRxConn(connp); - code = RXAFS_GetVolumeStatus(rxconnp, volp->vol[ROVOL].ID, - &volStat, &Name, &OfflineMsg, &MOTD); - rx_PutConnection(rxconnp); + rxconnp = cm_GetRxConn(connp); + 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)); - code = cm_MapRPCError(code, &req); + } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code)); + code = cm_MapRPCError(code, &req); - lock_ObtainWrite(&volp->rw); - if (code == 0 && volStat.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->vol[ROVOL].ID, volp->vol[ROVOL].state, vl_unknown); - volp->vol[ROVOL].state = vl_unknown; - online = 1; + lock_ObtainWrite(&volp->rw); + if (code == 0 && volStat.Online) { + cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_online); + statep->state = vl_online; + *onlinep = 1; + } else if (code == CM_ERROR_NOACCESS) { + cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_unknown); + statep->state = vl_unknown; + *onlinep = 1; + } + } else if (alldown && statep->state != vl_alldown) { + cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_alldown); + statep->state = vl_alldown; } + } else if (statep->state != vl_alldown) { + cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_alldown); + statep->state = vl_alldown; } } +} - if (volp->vol[BACKVOL].ID != 0 && (!volID || volID == volp->vol[BACKVOL].ID) && - volp->vol[BACKVOL].serversp) { - - for (serversp = volp->vol[BACKVOL].serversp; serversp; serversp = serversp->next) { - if (serversp->status == srv_busy || serversp->status == srv_offline) { - serversp->status = srv_not_busy; - online = 1; - } - } - - if (volp->vol[BACKVOL].state == vl_busy || volp->vol[BACKVOL].state == vl_offline || volp->vol[BACKVOL].state == vl_unknown) { - cm_InitReq(&req); - - lock_ReleaseWrite(&volp->rw); - do { - code = cm_ConnFromVolume(volp, volp->vol[BACKVOL].ID, cm_rootUserp, &req, &connp); - if (code) - continue; - - rxconnp = cm_GetRxConn(connp); - code = RXAFS_GetVolumeStatus(rxconnp, volp->vol[BACKVOL].ID, - &volStat, &Name, &OfflineMsg, &MOTD); - rx_PutConnection(rxconnp); +/* The return code is 0 if the volume is not online and + * 1 if the volume is online + */ +long +cm_CheckOfflineVolume(cm_volume_t *volp, afs_uint32 volID) +{ + long code; + cm_req_t req; + afs_uint32 online = 0; + afs_uint32 volumeUpdated = 0; - } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code)); - code = cm_MapRPCError(code, &req); + lock_ObtainWrite(&volp->rw); - lock_ObtainWrite(&volp->rw); - if (code == 0 && volStat.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->vol[BACKVOL].ID, volp->vol[BACKVOL].state, vl_unknown); - volp->vol[BACKVOL].state = vl_unknown; - online = 1; - } - } + if (volp->flags & CM_VOLUMEFLAG_RESET) { + cm_InitReq(&req); + code = cm_UpdateVolumeLocation(volp->cellp, cm_rootUserp, &req, volp); + volumeUpdated = 1; } + cm_CheckOfflineVolumeState(volp, &volp->vol[RWVOL], volID, &online, &volumeUpdated); + cm_CheckOfflineVolumeState(volp, &volp->vol[ROVOL], volID, &online, &volumeUpdated); + cm_CheckOfflineVolumeState(volp, &volp->vol[BACKVOL], volID, &online, &volumeUpdated); + lock_ReleaseWrite(&volp->rw); return online; } diff --git a/src/WINNT/afsd/cm_volume.h b/src/WINNT/afsd/cm_volume.h index cc4f0ba0a..9a2763926 100644 --- a/src/WINNT/afsd/cm_volume.h +++ b/src/WINNT/afsd/cm_volume.h @@ -89,7 +89,7 @@ extern void cm_PutVolume(cm_volume_t *volp); extern long cm_GetROVolumeID(cm_volume_t *volp); -extern void cm_ForceUpdateVolume(struct cm_fid *fidp, cm_user_t *userp, +extern long cm_ForceUpdateVolume(struct cm_fid *fidp, cm_user_t *userp, cm_req_t *reqp); extern cm_serverRef_t **cm_GetVolServers(cm_volume_t *volp, afs_uint32 volume); @@ -124,6 +124,10 @@ extern void cm_CheckOfflineVolumes(void); extern long cm_CheckOfflineVolume(cm_volume_t *volp, afs_uint32 volID); +extern void cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, + afs_uint32 volID, afs_uint32 *onlinep, + afs_uint32 *volumeUpdatedp); + extern void cm_UpdateVolumeStatus(cm_volume_t *volp, afs_uint32 volID); extern void cm_VolumeStatusNotification(cm_volume_t * volp, afs_uint32 volID, enum volstatus oldState, enum volstatus newState);