On Sat, 2001/05/26 at 11:07:36 -0500, Michael Harnois wrote:
> I finally got this much. I hope it helps.
> lock order reversal
> 1st 0xc03af0a0 mntvnode @ ../../ufs/ffs/ffs_vnops.c:1007
> 2nd 0xc8b539cc vnode interlock @ ../../ufs/ffs/ffs_vfsops.c:1016
> recursed on non-recursive lock (sleep mutex) vm @ ../../ufs/ufs/ufs_readwrite.c:420
> first acquired @ ../../vm/vnode_pager.c:912
> panic:recurse
> Debugger ("panic")
> Stopped at Debugger+0x45: pushl %ebx
> db> t
> Debugger(c0310767b) at Debugger+0x45
> panic(c0313348,c81b9cb8,a0,10,0) at panic+0x70
> witness_lock(c03b3f20,8,c03263b6,1a4) at witness_lock+0x356
> ffs_write(c81b9ca4) at ffs_write+0xba
> vnode_pager_generic_putpages(c8c31d00,c81b9ddc,10000,0,c81b9d74) at 
> vop_stdputpages(c81b9d28,c81b9d0c,c02a7f9d,c81b9d28,c81b9d48) at vop_stdputpages+0x1f
> vop_defaultop(c81b9d28,c81b9d48,c02c5c3d,c81b9d28,0) at vop_defaultop+0x15
> ufs_vnoperate(c81b9d28) at ufs_vnoperate+0x15
> vnode_pager_putpages(c8c4b360,c81b9ddc,10,0,c81b9d74,c03b3f20,1,c0329ffa,91) at 
> [...]

I can relatively reliable reproduce this panic here...
The problem appears to be that the vm_mtx is held when VOP_WRITE is
called in vnode_pager_generic_putpages
(sys/vm/vnode_pager.c:999). This may try to grab the vm_mtx (e.g. the
ufs implementation in sys/ufs/ufs/ufs_readwrite.c), so you end up with
a recursion on the lock. Even if it wouldn't recurse, VOP_WRITE can 
AFAIK block, so there is a potential for other panics, too.
The attached patch just unlocks vm_mtx before this call and reacquires
the it when it's done. This works for me, and I think it theoretically
should be safe because all relevant parts are under Giant again for
now; YMMV, it might cause other panics or corruption, so you've been
warned ;)

        - thomas
Index: sys/vm/vnode_pager.c
RCS file: /home/ncvs/src/sys/vm/vnode_pager.c,v
retrieving revision 1.130
diff -u -r1.130 vnode_pager.c
--- sys/vm/vnode_pager.c        2001/05/23 22:51:23     1.130
+++ sys/vm/vnode_pager.c        2001/05/27 01:07:19
@@ -996,7 +996,9 @@
        auio.uio_rw = UIO_WRITE;
        auio.uio_resid = maxsize;
        auio.uio_procp = (struct proc *) 0;
+       mtx_unlock(&vm_mtx);
        error = VOP_WRITE(vp, &auio, ioflags, curproc->p_ucred);
+       mtx_lock(&vm_mtx);
        cnt.v_vnodepgsout += ncount;

Reply via email to