From a3ef19e1995a1d3d05c8f3b2decf4301359d8375 Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Sun, 20 May 2012 17:05:12 -0500 Subject: [PATCH] FBSD: Add osi_fbsd_checkinuse Add the osi_fbsd_checkinuse function, which contains code common to the FreeBSD osi_TryEvictVCache and osi_VM_FlushVCache. Implement the latter two in terms of osi_fbsd_checkinuse. This commit should incur no behavior changes. This is just a reorganization so future commits can change the implementations of osi_TryEvictVCache and osi_VM_FlushVCache. Change-Id: I42df9d6efb7b573bd933d0bf04924f668a3608da Reviewed-on: http://gerrit.openafs.org/7432 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Derrick Brashear --- src/afs/FBSD/osi_misc.c | 40 ++++++++++++++++++++++++++++++++ src/afs/FBSD/osi_prototypes.h | 2 ++ src/afs/FBSD/osi_vcache.c | 43 +++++++++++++++++++++++++---------- src/afs/FBSD/osi_vm.c | 28 +++++++---------------- 4 files changed, 81 insertions(+), 32 deletions(-) diff --git a/src/afs/FBSD/osi_misc.c b/src/afs/FBSD/osi_misc.c index 04fe165a8..debc35474 100644 --- a/src/afs/FBSD/osi_misc.c +++ b/src/afs/FBSD/osi_misc.c @@ -91,3 +91,43 @@ osi_fbsd_free(void *p) { free(p, M_AFS); } + +/** + * check if a vcache is in use + * + * @return status + * @retcode 0 success + * @retcode EBUSY vcache is in use by someone else + * @retcode otherwise other error + * + * @pre The caller must hold the vnode interlock for the associated vnode + * @post The vnode interlock for the associated vnode will still be held + * and must be VI_UNLOCK'd by the caller + */ +int +osi_fbsd_checkinuse(struct vcache *avc) +{ + struct vnode *vp = AFSTOV(avc); + + ASSERT_VI_LOCKED(vp, "osi_fbsd_checkinuse"); + + /* The interlock is needed to check the usecount. */ + if (vp->v_usecount > 0) { + return EBUSY; + } + + /* XXX + * The value of avc->opens here came to be, at some point, + * typically -1. This was caused by incorrectly performing afs_close + * processing on vnodes being recycled */ + if (avc->opens) { + return EBUSY; + } + + /* if a lock is held, give up */ + if (CheckLock(&avc->lock)) { + return EBUSY; + } + + return 0; +} diff --git a/src/afs/FBSD/osi_prototypes.h b/src/afs/FBSD/osi_prototypes.h index b62a4f863..c3c3b6042 100644 --- a/src/afs/FBSD/osi_prototypes.h +++ b/src/afs/FBSD/osi_prototypes.h @@ -32,4 +32,6 @@ extern int afs_statfs(struct mount *mp, struct statfs *abp); extern int afs_statfs(struct mount *mp, struct statfs *abp, struct thread *td); #endif +extern int osi_fbsd_checkinuse(struct vcache *avc); + #endif /* _OSI_PROTO_H_ */ diff --git a/src/afs/FBSD/osi_vcache.c b/src/afs/FBSD/osi_vcache.c index 07c332723..8f4df5767 100644 --- a/src/afs/FBSD/osi_vcache.c +++ b/src/afs/FBSD/osi_vcache.c @@ -24,20 +24,39 @@ #endif int -osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { - - /* - * essentially all we want to do here is check that the - * vcache is not in use, then call vgone() (which will call - * inactive and reclaim as needed). This requires some - * kind of complicated locking, which we already need to implement - * for FlushVCache, so just call that routine here and check - * its return value for whether the vcache was evict-able. - */ - if (osi_VM_FlushVCache(avc, slept) != 0) +osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) +{ + struct vnode *vp; + int code; + + vp = AFSTOV(avc); + + if (!VI_TRYLOCK(vp)) return 0; - else + code = osi_fbsd_checkinuse(avc); + if (code != 0) { + VI_UNLOCK(vp); + return 0; + } + + if ((vp->v_iflag & VI_DOOMED) != 0) { + VI_UNLOCK(vp); return 1; + } + + /* must hold the vnode before calling vgone() + * This code largely copied from vfs_subr.c:vlrureclaim() */ + vholdl(vp); + AFS_GUNLOCK(); + *slept = 1; + /* use the interlock while locking, so no one else can DOOM this */ + ma_vn_lock(vp, LK_INTERLOCK|LK_EXCLUSIVE|LK_RETRY, curthread); + vgone(vp); + MA_VOP_UNLOCK(vp, 0, curthread); + vdrop(vp); + + AFS_GLOCK(); + return 1; } struct vcache * diff --git a/src/afs/FBSD/osi_vm.c b/src/afs/FBSD/osi_vm.c index 072142d79..c2f7ce180 100644 --- a/src/afs/FBSD/osi_vm.c +++ b/src/afs/FBSD/osi_vm.c @@ -75,34 +75,22 @@ int osi_VM_FlushVCache(struct vcache *avc, int *slept) { - struct vnode *vp = AFSTOV(avc); - - if (!VI_TRYLOCK(vp)) /* need interlock to check usecount */ - return EBUSY; + struct vnode *vp; + int code; - if (vp->v_usecount > 0) { - VI_UNLOCK(vp); - return EBUSY; - } + vp = AFSTOV(avc); - /* XXX - * The value of avc->opens here came to be, at some point, - * typically -1. This was caused by incorrectly performing afs_close - * processing on vnodes being recycled */ - if (avc->opens) { - VI_UNLOCK(vp); + if (!VI_TRYLOCK(vp)) return EBUSY; - } - - /* if a lock is held, give up */ - if (CheckLock(&avc->lock)) { + code = osi_fbsd_checkinuse(avc); + if (code) { VI_UNLOCK(vp); - return EBUSY; + return code; } if ((vp->v_iflag & VI_DOOMED) != 0) { VI_UNLOCK(vp); - return (0); + return 0; } /* must hold the vnode before calling vgone() -- 2.39.5