Index: sys/fs/unionfs/union_subr.c =================================================================== --- sys/fs/unionfs/union_subr.c +++ sys/fs/unionfs/union_subr.c @@ -442,7 +442,16 @@ int count; int writerefs; - KASSERT(vp->v_vnlock->lk_recurse == 0, + /* + * The root vnode lock may be recursed during forcible, because + * it may share the same lock as the unionfs mount's covered vnode, + * which is locked across VFS_UNMOUNT(). This lock will then be + * recursively taken during the vflush() issued by unionfs_unmount(). + * But we still only need to lock the unionfs lock once, because only + * one of those lock operations was taken against a unionfs vnode and + * will be undone against a unionfs vnode. + */ + KASSERT(vp->v_vnlock->lk_recurse == 0 || (vp->v_vflag & VV_ROOT) != 0, ("%s: vnode %p locked recursively", __func__, vp)); if (lockmgr(&vp->v_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL) != 0) panic("%s: failed to acquire lock for vnode lock", __func__); @@ -821,7 +830,7 @@ VNASSERT(vp->v_writecount == 0, vp, ("%s: non-zero writecount", __func__)); /* - * Uppdate the upper vnode's lock state to match the lower vnode, + * Update the upper vnode's lock state to match the lower vnode, * and then switch the unionfs vnode's lock to the upper vnode. */ lockrec = lvp->v_vnlock->lk_recurse; Index: sys/fs/unionfs/union_vnops.c =================================================================== --- sys/fs/unionfs/union_vnops.c +++ sys/fs/unionfs/union_vnops.c @@ -76,8 +76,8 @@ #endif #define KASSERT_UNIONFS_VNODE(vp) \ - KASSERT(((vp)->v_op == &unionfs_vnodeops), \ - ("unionfs: it is not unionfs-vnode")) + VNASSERT(((vp)->v_op == &unionfs_vnodeops), vp, \ + ("%s: non-unionfs vnode", __func__)) static int unionfs_lookup(struct vop_cachedlookup_args *ap) @@ -1918,8 +1918,6 @@ int interlock; int uhold; - KASSERT_UNIONFS_VNODE(ap->a_vp); - /* * TODO: rework the unionfs locking scheme. * It's not guaranteed to be safe to blindly lock two vnodes on @@ -1945,19 +1943,21 @@ unp = VTOUNIONFS(vp); if (unp == NULL) goto unionfs_lock_null_vnode; + + KASSERT_UNIONFS_VNODE(ap->a_vp); + lvp = unp->un_lowervp; uvp = unp->un_uppervp; if ((revlock = unionfs_get_llt_revlock(vp, flags)) == 0) panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK); - if ((flags & LK_TYPE_MASK) != LK_DOWNGRADE && - (vp->v_iflag & VI_OWEINACT) != 0) - flags |= LK_NOWAIT; - /* - * Sometimes, lower or upper is already exclusive locked. - * (ex. vfs_domount: mounted vnode is already locked.) + * During unmount, the root vnode lock may be taken recursively, + * because it may share the same v_vnlock field as the vnode covered by + * the unionfs mount. The covered vnode is locked across VFS_UNMOUNT(), + * and the same lock may be taken recursively here during vflush() + * issued by unionfs_unmount(). */ if ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE && (vp->v_vflag & VV_ROOT) != 0)