diff --git a/sys/vfs/autofs/autofs_vnops.c b/sys/vfs/autofs/autofs_vnops.c --- a/sys/vfs/autofs/autofs_vnops.c +++ b/sys/vfs/autofs/autofs_vnops.c @@ -586,16 +586,24 @@ return (0); } - mtx_unlock_ex(&anp->an_vnode_lock); - + /* + * Hold an_vnode_lock across the sleepable getnewvnode() call to + * serialize vnode creation for this node. mtx_t is a sleeping + * mutex, so this is safe and prevents the create race where two + * threads both observed an_vnode == NULL, both entered + * getnewvnode(), and the loser tripped the KASSERT below (or, + * without INVARIANTS, leaked a vnode + corrupted reclaim state). + */ error = getnewvnode(VT_AUTOFS, mp, &vp, VLKTIMEOUT, LK_CANRECURSE); - if (error) + if (error) { + mtx_unlock_ex(&anp->an_vnode_lock); return (error); + } vp->v_type = VDIR; vp->v_data = anp; - KASSERT(anp->an_vnode == NULL, ("lost race")); anp->an_vnode = vp; + mtx_unlock_ex(&anp->an_vnode_lock); vx_downgrade(vp); /* downgrade VX lock to VN lock */ *vpp = vp;