{
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;
+}
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_ */
#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 *
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()