Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -1632,6 +1632,7 @@ KASSERT(vp->v_lockf == NULL, ("stale v_lockf %p", vp)); KASSERT(vp->v_pollinfo == NULL, ("stale v_pollinfo %p", vp)); vp->v_type = VNON; + vp->v_doomed = false; vp->v_tag = tag; vp->v_op = vops; v_init_counters(vp); @@ -3271,6 +3272,7 @@ vp->v_lasta = vp->v_clen = vp->v_cstart = vp->v_lastw = 0; vp->v_iflag = 0; vp->v_vflag = 0; + vp->v_doomed = false; bo->bo_flag = 0; uma_zfree(vnode_zone, vp); } @@ -3584,9 +3586,15 @@ /* * Don't vgonel if we're already doomed. */ - if (vp->v_iflag & VI_DOOMED) + if (vp->v_iflag & VI_DOOMED) { + VNASSERT(vp->v_doomed, vp, + ("%s: VI_DOOMED and v_doomed mismatch", __func__)); return; + } vp->v_iflag |= VI_DOOMED; + VNASSERT(!vp->v_doomed, vp, + ("%s: VI_DOOMED and v_doomed mismatch", __func__)); + vp->v_doomed = true; /* * Check to see if the vnode is in use. If so, we have to call Index: sys/kern/vfs_vnops.c =================================================================== --- sys/kern/vfs_vnops.c +++ sys/kern/vfs_vnops.c @@ -1579,7 +1579,7 @@ ("vn_lock: error %d incompatible with flags %#x", error, flags)); if ((flags & LK_RETRY) == 0) { - if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0) { + if (error == 0 && VN_IS_DOOMED(vp)) { VOP_UNLOCK(vp, 0); error = ENOENT; } Index: sys/sys/vnode.h =================================================================== --- sys/sys/vnode.h +++ sys/sys/vnode.h @@ -103,7 +103,8 @@ * Fields which define the identity of the vnode. These fields are * owned by the filesystem (XXX: and vgone() ?) */ - enum vtype v_type; /* u vnode type */ + enum vtype v_type:8; /* u vnode type */ + bool v_doomed; /* v + i is it doomed */ struct vop_vector *v_op; /* u vnode operations vector */ void *v_data; /* u private data for fs */ @@ -889,6 +890,16 @@ #define VOP_UNSET_TEXT_CHECKED(vp) VOP_UNSET_TEXT((vp)) #endif +#define VN_IS_DOOMED(vp) ({ \ + struct vnode *_vp = (vp); \ + bool _doomed = _vp->v_doomed; \ + bool _flag_doomed = _vp->v_iflag & VI_DOOMED; \ + \ + VNASSERT(((_doomed && _flag_doomed) || (!_doomed && !_flag_doomed)),\ + _vp, ("%s: VI_DOOMED and v_doomed mismatch", __func__)); \ + _doomed; \ +}) + void vput(struct vnode *vp); void vrele(struct vnode *vp); void vref(struct vnode *vp);