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 <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
This commit is contained in:
Andrew Deason 2012-05-20 17:05:12 -05:00 committed by Derrick Brashear
parent dda5cc0c5f
commit a3ef19e199
4 changed files with 81 additions and 32 deletions

View File

@ -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;
}

View File

@ -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_ */

View File

@ -24,20 +24,39 @@
#endif
int
osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) {
osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep)
{
struct vnode *vp;
int code;
/*
* 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)
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 *

View File

@ -75,34 +75,22 @@
int
osi_VM_FlushVCache(struct vcache *avc, int *slept)
{
struct vnode *vp = AFSTOV(avc);
struct vnode *vp;
int code;
if (!VI_TRYLOCK(vp)) /* need interlock to check usecount */
vp = AFSTOV(avc);
if (!VI_TRYLOCK(vp))
return EBUSY;
if (vp->v_usecount > 0) {
code = osi_fbsd_checkinuse(avc);
if (code) {
VI_UNLOCK(vp);
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) {
VI_UNLOCK(vp);
return EBUSY;
}
/* if a lock is held, give up */
if (CheckLock(&avc->lock)) {
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()