I tried booting a kernel with lock checking enabled and got the
following panic:

panic: mutex vnode interlock owned at vnode_if.h:24

panic()
_mtx_assert()
VOP_ISLOCKED()
vop_unlock_pre()
vput()
kern_mkdir()+0x9e - the first call to vput() to handle the "found" case?
start_init()
fork_exit()
fork_trampoline()


I believe there is a logic error in the VOP_UNLOCK() assertion logic.
In vput(), there is the following code:

        VI_LOCK(vp);
        /* Skip this v_writecount check if we're going to panic below. */
        KASSERT(vp->v_writecount < vp->v_usecount || vp->v_usecount < 1,
            ("vput: missed vn_close"));
         
        if (vp->v_usecount > 1) {
                vp->v_usecount--;
                VOP_UNLOCK(vp, LK_INTERLOCK, td);
                return;
        }

which looks reasonable.  VOP_UNLOCK() starts off with the following
code:

        struct vop_unlock_args a;
        int rc;
        a.a_desc = VDESC(vop_unlock);
        a.a_vp = vp;
        a.a_flags = flags;
        a.a_td = td;
#ifdef  DEBUG_VFS_LOCKS
        vop_unlock_pre(&a);
#endif

Then vop_unlock_pre() contains the following code:

       if (a->a_flags & LK_INTERLOCK)
                ASSERT_VI_LOCKED(a->a_vp);
   
        ASSERT_VOP_LOCKED(a->a_vp, "VOP_UNLOCK");

Since the LK_INTERLOCK flag is passed to VOP_UNLOCK() and
vop_unlock_pre(), we test the VI_LOCKED assertion.  We get into
trouble with ASSERT_VOP_LOCKED, though, because ASSERT_VOP_LOCKED()
calls VOP_ISLOCKED(), which contains the code:

        a.a_desc = VDESC(vop_islocked);
        a.a_vp = vp;
        a.a_td = td;
        ASSERT_VI_UNLOCKED(vp);

We'll definitely blow up here because we're making the exact opposite
assertion.


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to