diff --git a/src/viced/afsfileprocs.c b/src/viced/afsfileprocs.c index b064464a64..55c17dddbc 100644 --- a/src/viced/afsfileprocs.c +++ b/src/viced/afsfileprocs.c @@ -491,7 +491,7 @@ CheckVnode(AFSFid * fid, Volume ** volptr, Vnode ** vptr, int lock) ; errorCode = 0; - *volptr = VGetVolume(&local_errorCode, &errorCode, (afs_int32) fid->Volume); + *volptr = VGetVolumeNoWait(&local_errorCode, &errorCode, (afs_int32) fid->Volume); if (!errorCode) { assert(*volptr); break; diff --git a/src/vol/volume.c b/src/vol/volume.c index 59bd530a6c..65b400491d 100644 --- a/src/vol/volume.c +++ b/src/vol/volume.c @@ -3472,6 +3472,18 @@ VGetVolume(Error * ec, Error * client_ec, VolId volumeId) return retVal; } +/* same as VGetVolume, but if a volume is waiting to go offline, we return + * that it is actually offline, instead of waiting for it to go offline */ +Volume * +VGetVolumeNoWait(Error * ec, Error * client_ec, VolId volumeId) +{ + Volume *retVal; + VOL_LOCK; + retVal = GetVolume(ec, client_ec, volumeId, NULL, 1); + VOL_UNLOCK; + return retVal; +} + Volume * VGetVolume_r(Error * ec, VolId volumeId) { @@ -3493,7 +3505,8 @@ VGetVolumeByVp_r(Error * ec, Volume * vp) * @param[out] client_ec wire error code to be given to clients * @param[in] volumeId ID of the volume we want * @param[in] hint optional hint for hash lookups, or NULL - * @param[in] flags unused; always 0 + * @param[in] nowait 0 to wait for a 'goingOffline' volume to go offline + * before returning, 1 to return immediately * * @return a volume handle for the specified volume * @retval NULL an error occurred, or the volume is in such a state that @@ -3502,7 +3515,7 @@ VGetVolumeByVp_r(Error * ec, Volume * vp) * @note for DAFS, caller must NOT hold a ref count on 'hint' */ static Volume * -GetVolume(Error * ec, Error * client_ec, VolId volumeId, Volume * hint, int flags) +GetVolume(Error * ec, Error * client_ec, VolId volumeId, Volume * hint, int nowait) { Volume *vp = hint; /* pull this profiling/debugging code out of regular builds */ @@ -3755,7 +3768,7 @@ GetVolume(Error * ec, Error * client_ec, VolId volumeId, Volume * hint, int flag if (programType == fileServer) { VGET_CTR_INC(V9); - if (vp->goingOffline) { + if (vp->goingOffline && !nowait) { VGET_CTR_INC(V10); #ifdef AFS_DEMAND_ATTACH_FS /* wait for the volume to go offline */ @@ -3775,7 +3788,7 @@ GetVolume(Error * ec, Error * client_ec, VolId volumeId, Volume * hint, int flag } else if (V_inService(vp) == 0 || V_blessed(vp) == 0) { VGET_CTR_INC(V12); *ec = VNOVOL; - } else if (V_inUse(vp) == 0) { + } else if (V_inUse(vp) == 0 || vp->goingOffline) { VGET_CTR_INC(V13); *ec = VOFFLINE; } else { diff --git a/src/vol/volume.h b/src/vol/volume.h index afc88bd5ca..ddfd868e8e 100644 --- a/src/vol/volume.h +++ b/src/vol/volume.h @@ -758,6 +758,7 @@ struct volHeader { extern char *VSalvageMessage; /* Canonical message when a volume is forced * offline */ extern Volume *VGetVolume(Error * ec, Error * client_ec, VolId volumeId); +extern Volume *VGetVolumeNoWait(Error * ec, Error * client_ec, VolId volumeId); extern Volume *VGetVolume_r(Error * ec, VolId volumeId); extern void VPutVolume(Volume *); extern void VPutVolume_r(Volume *);