Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Mar 1998 22:43:49 +0100 (CET)
From:      Tor Egge <Tor.Egge@idi.ntnu.no>
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   kern/5893: Recursive locking attempts on vp->v_interlock
Message-ID:  <199803012143.WAA02526@skarven.itea.ntnu.no>

next in thread | raw e-mail | index | archive | help

>Number:         5893
>Category:       kern
>Synopsis:       Recursive locking attempts on vp->v_interlock
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Mar  1 13:50:00 PST 1998
>Last-Modified:
>Originator:     Tor Egge
>Organization:
Norwegian University of Science and Technology, Trondheim, Norway
>Release:        FreeBSD 3.0-CURRENT i386
>Environment:

FreeBSD skarven.itea.ntnu.no 3.0-CURRENT FreeBSD 3.0-CURRENT #2: Sun Mar  1 00:37:17 CET 1998     root@skarven.itea.ntnu.no:/usr/src/sys/compile/SKARVEN_SMP  i386

>Description:

vdrop can be called from interrupts.  Sometimes, the v_interlock on
the vnode is already held when vdrop tries to obtain the lock.

On systems where increment and decrement is implemented as multiple
instructions, a race condition is probably present unless bio
interrupts are disabled during the vhold/vdrop operations.

Appended is a stack trace from a crash which occured when the vm_fault
handler was interrupted by the scsi controller after having obtained a
v_interlock simple lock. vdrop was called with the same vnode as
argument from the interrupt, with a panic as the result.

(Between #13 and #14, vdrop() should be shown, and between #24 and
#25, vget() should be shown. gdb does not like frameless functions).

Current directory is /export/ftpsearch2/crash/
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.16 (i386-unknown-freebsd), 
Copyright 1996 Free Software Foundation, Inc...
SMP(1:2) IdlePTD 9d7000
panicstr: rslock: cpu: %d, addr: 0x%08x, lock: 0x%08x
panic messages:
---
panic: rslock: cpu: 1, addr: 0xeadcc7e0, lock: 0x01000001
mp_lock = 01000002; cpuid = 1; lapic.id = 00000000
boot() called on cpu#1
I'm on cpu#1, I need to be on cpu#0, sleeping..
[... snip ..]
---
#0  boot (howto=260) at ../../kern/kern_shutdown.c:286
(kgdb) where
#0  boot (howto=260) at ../../kern/kern_shutdown.c:286
#1  0xe01170a1 in panic (
    fmt=0xe01bfbee "bogus vm_page_alloc call at interrupt time")
    at ../../kern/kern_shutdown.c:426
#2  0xe01bfc7f in vm_page_alloc (object=0xe021ec08, pindex=29610, page_req=0)
    at ../../vm/vm_page.c:819
#3  0xe013310f in vm_hold_load_pages (bp=0xe6bcc328, from=3878850560, 
    to=3878858752) at ../../kern/vfs_bio.c:2287
#4  0xe01321c4 in allocbuf (bp=0xe6bcc328, size=8192)
    at ../../kern/vfs_bio.c:1616
#5  0xe0131f6e in getblk (vp=0xeab4ef60, blkno=65632, size=8192, slpflag=0, 
    slptimeo=0) at ../../kern/vfs_bio.c:1484
#6  0xe01306e1 in bread (vp=0xeab4ef60, blkno=65632, size=8192, cred=0x0, 
    bpp=0xeae9ab4c) at ../../kern/vfs_bio.c:283
#7  0xe01ab305 in ffs_update (vp=0xeabd3440, access=0xeae9abb0, 
    modify=0xeae9abb0, waitfor=0) at ../../ufs/ffs/ffs_inode.c:126
#8  0xe01af4c8 in ffs_fsync (ap=0xeae9abec) at ../../ufs/ffs/ffs_vnops.c:211
#9  0xe01ada76 in ffs_sync (mp=0xe1b60800, waitfor=2, cred=0xe1b61700, 
    p=0xe022e648) at vnode_if.h:499
#10 0xe0139387 in sync (p=0xe022e648, uap=0x0) at ../../kern/vfs_syscalls.c:505
#11 0xe0116c2f in boot (howto=256) at ../../kern/kern_shutdown.c:218
#12 0xe01170a1 in panic (
    fmt=0xe01d6011 "rslock: cpu: %d, addr: 0x%08x, lock: 0x%08x")
    at ../../kern/kern_shutdown.c:426
#13 0xe01d6011 in bsl1 ()
#14 0xe0136b87 in brelvp (bp=0xe6ba9f48) at ../../kern/vfs_subr.c:702
#15 0xe01312e6 in vfs_vmio_release (bp=0xe6ba9f48) at ../../kern/vfs_bio.c:825
#16 0xe0130e3d in brelse (bp=0xe6ba9f48) at ../../kern/vfs_bio.c:650
#17 0xe01329fe in biodone (bp=0xe6ba9f48) at ../../kern/vfs_bio.c:1971
#18 0xe0101758 in ccdintr (cs=0xe1c21b30, bp=0xe6ba9f48)
    at ../../dev/ccd/ccd.c:961
#19 0xe0101836 in ccdiodone (cbp=0xe2016400) at ../../dev/ccd/ccd.c:1021
#20 0xe01327c8 in biodone (bp=0xe2016400) at ../../kern/vfs_bio.c:1843
#21 0xe01a267c in scsi_done (xs=0xe1cb9f00) at ../../scsi/scsi_base.c:448
#22 0xe01fdd84 in ahc_done (ahc=0xe1b64000, scb=0xe1ca6a60)
    at ../../i386/scsi/aic7xxx.c:1959
#23 0xe01fb6fe in ahc_intr (arg=0xe1b64000) at ../../i386/scsi/aic7xxx.c:821
#24 0xe01d5fe9 in setlock ()
#25 0xe01bdccb in vm_object_reference (object=0xeacbe9cc)
    at ../../vm/vm_object.c:247
#26 0xe01b7f8c in vm_fault (map=0xeacc2980, vaddr=2506088448, 
    fault_type=3 '\003', fault_flags=8) at ../../vm/vm_fault.c:235
#27 0xe01d78ea in trap_pfault (frame=0xeae9afac, usermode=1)
    at ../../i386/i386/trap.c:723
#28 0xe01d747f in trap (frame={tf_es = -541130713, tf_ds = -353828825, 
      tf_edi = 4, tf_esi = 1436336, tf_ebp = -541075100, tf_isp = -353783852, 
      tf_ebx = 83900717, tf_edx = 4, tf_ecx = 637248, tf_eax = -1790312448, 
      tf_trapno = 12, tf_err = 7, tf_eip = 10113, tf_cs = 31, 
      tf_eflags = 66183, tf_esp = -541076400, tf_ss = 39})
    at ../../i386/i386/trap.c:290
#29 0x2781 in ?? ()
#30 0x3218 in ?? ()
#31 0x1095 in ?? ()
(kgdb) 

>How-To-Repeat:

	A lot of disk activity (vnode paging) on a 3.0-CURRENT -SMP system.

>Fix:
	
I suggest replacing the obtain/release of v_interlock in vdrop/vhold
with splbio/splx pairs, and changing the comment in /usr/src/sys/sys/vnode.h
to no longer say that v_holdcnt is locked by v_interlock.

Index: vfs_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.134
diff -u -r1.134 vfs_subr.c
--- vfs_subr.c	1998/02/23 06:59:52	1.134
+++ vfs_subr.c	1998/03/01 19:31:49
@@ -1048,12 +1056,13 @@
 vhold(vp)
 	register struct vnode *vp;
 {
+	int s;
 
-	simple_lock(&vp->v_interlock);
+  	s = splbio();
 	vp->v_holdcnt++;
 	if (VSHOULDBUSY(vp))
 		vbusy(vp);
-	simple_unlock(&vp->v_interlock);
+	splx(s);
 }
 
 /*
@@ -1063,14 +1072,15 @@
 vdrop(vp)
 	register struct vnode *vp;
 {
+	int s;
 
-	simple_lock(&vp->v_interlock);
+	s = splbio();
 	if (vp->v_holdcnt <= 0)
 		panic("holdrele: holdcnt");
 	vp->v_holdcnt--;
 	if (VSHOULDFREE(vp))
 		vfree(vp);
-	simple_unlock(&vp->v_interlock);
+	splx(s);
 }
 
 /*
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199803012143.WAA02526>