From 581aafaa698e395bfcfb7b82b595fbdef4b11279 Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Tue, 8 Jun 2010 17:28:39 -0500 Subject: [PATCH] GetVolume: do not wait for offlining volumes In non-DAFS GetVolume, previously we waited for a volume with vp->goingOffline set to go offline before we return. However, the fileserver afsfileprocs.c case can treat the "going offline" case and the "is offline" case identically, so there is no reason to wait. So make the fileserver call a new GetVolume variant that does not wait. Without this, all of the threads in the fileserver can potentially be tied up by waiting for a volume to go offline, if the volume is taking a long time to go offline due to an offline request following a client slowly accessing the volume. Change-Id: I58ae11e585852130154389d8df0567432cd0c2df Reviewed-on: http://gerrit.openafs.org/2124 Reviewed-by: Derrick Brashear Reviewed-by: Tom Keiser Tested-by: Derrick Brashear --- src/viced/afsfileprocs.c | 2 +- src/vol/volume.c | 21 +++++++++++++++++---- src/vol/volume.h | 1 + 3 files changed, 19 insertions(+), 5 deletions(-) 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 *);