diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index 2d3623a066..881a75a758 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -210,7 +210,7 @@ void cm_InitReq(cm_req_t *reqp) reqp->startTime = GetTickCount(); } -static long cm_GetServerList(struct cm_fid *fidp, struct cm_user *userp, +long cm_GetServerList(struct cm_fid *fidp, struct cm_user *userp, struct cm_req *reqp, afs_uint32 *replicated, cm_serverRef_t ***serversppp) { long code; @@ -638,15 +638,26 @@ cm_Analyze(cm_conn_t *connp, if ((errorCode == VMOVED || errorCode == VNOVOL || errorCode == VOFFLINE) && !(reqp->flags & CM_REQ_VOLUME_UPDATED)) { + LONG_PTR oldSum, newSum; + + oldSum = cm_ChecksumVolumeServerList(fidp, userp, reqp); + code = cm_ForceUpdateVolume(fidp, userp, reqp); - if (code == 0) + if (code == 0) { location_updated = 1; + newSum = cm_ChecksumVolumeServerList(fidp, userp, reqp); + } - /* Even if the update fails, there might still be another replica */ + /* + * Even if the update fails, there might still be another replica. + * If the volume location list changed, permit another update on + * a subsequent error. + */ + if (code || oldSum == newSum) + reqp->flags |= CM_REQ_VOLUME_UPDATED; - reqp->flags |= CM_REQ_VOLUME_UPDATED; osi_Log3(afsd_logp, "cm_Analyze called cm_ForceUpdateVolume cell %u vol %u code 0x%x", - fidp->cell, fidp->volume, code); + fidp->cell, fidp->volume, code); } if (statep) { diff --git a/src/WINNT/afsd/cm_conn.h b/src/WINNT/afsd/cm_conn.h index affae47ae9..b995f27673 100644 --- a/src/WINNT/afsd/cm_conn.h +++ b/src/WINNT/afsd/cm_conn.h @@ -166,4 +166,8 @@ extern void cm_ForceNewConnections(cm_server_t *serverp); extern long cm_ServerAvailable(struct cm_fid *fidp, struct cm_user *userp); +extern long cm_GetServerList(struct cm_fid *fidp, struct cm_user *userp, + struct cm_req *reqp, afs_uint32 *replicated, + cm_serverRef_t ***serversppp); + #endif /* OPENAFS_WINNT_AFSD_CM_CONN_H */ diff --git a/src/WINNT/afsd/cm_volume.c b/src/WINNT/afsd/cm_volume.c index 2506bb0526..dd40e313ca 100644 --- a/src/WINNT/afsd/cm_volume.c +++ b/src/WINNT/afsd/cm_volume.c @@ -1945,3 +1945,19 @@ cm_VolumeType(cm_volume_t *volp, afs_uint32 id) return -1; } + +LONG_PTR +cm_ChecksumVolumeServerList(struct cm_fid *fidp, cm_user_t *userp, cm_req_t *reqp) +{ + LONG_PTR cksum = 0; + long code; + afs_uint32 replicated; + cm_serverRef_t **serverspp; + + code = cm_GetServerList(fidp, userp, reqp, &replicated, &serverspp); + if (code == 0) { + cksum = cm_ChecksumServerList(*serverspp); + cm_FreeServerList(serverspp, 0); + } + return cksum; +} diff --git a/src/WINNT/afsd/cm_volume.h b/src/WINNT/afsd/cm_volume.h index d843d87b59..e17dd2a9e0 100644 --- a/src/WINNT/afsd/cm_volume.h +++ b/src/WINNT/afsd/cm_volume.h @@ -104,6 +104,9 @@ extern void cm_PutVolume(cm_volume_t *volp); extern long cm_GetROVolumeID(cm_volume_t *volp); +extern LONG_PTR cm_ChecksumVolumeServerList(struct cm_fid *fidp, + cm_user_t *userp, cm_req_t *reqp); + extern long cm_ForceUpdateVolume(struct cm_fid *fidp, cm_user_t *userp, cm_req_t *reqp);