From tegge@not.fast.no  Thu Oct 22 17:56:02 1998
Received: from midten.fast.no (midten.fast.no [195.139.251.11])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id RAA01530
          for <FreeBSD-gnats-submit@freebsd.org>; Thu, 22 Oct 1998 17:56:01 -0700 (PDT)
          (envelope-from tegge@not.fast.no)
Received: from not.fast.no (IDENT:tegge@not.fast.no [195.139.251.12])
	by midten.fast.no (8.9.1/8.9.1) with ESMTP id CAA15963
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 23 Oct 1998 02:55:30 +0200 (CEST)
Received: (from tegge@localhost)
	by not.fast.no (8.9.1/8.8.8) id CAA10512;
	Fri, 23 Oct 1998 02:55:30 +0200 (CEST)
	(envelope-from tegge@not.fast.no)
Message-Id: <199810230055.CAA10512@not.fast.no>
Date: Fri, 23 Oct 1998 02:55:30 +0200 (CEST)
From: Tor Egge <tegge@not.fast.no>
Reply-To: tegge@not.fast.no
To: FreeBSD-gnats-submit@freebsd.org
Subject: vm_fault might deadlock when locking backing store vnode
X-Send-Pr-Version: 3.2

>Number:         8416
>Category:       kern
>Synopsis:       vm_fault might deadlock when locking backing store vnode
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct 22 18:00:00 PDT 1998
>Closed-Date:    Tue May 11 01:04:23 PDT 1999
>Last-Modified:  Tue May 11 01:05:31 PDT 1999
>Originator:     Tor Egge
>Release:        FreeBSD 3.0-CURRENT i386
>Organization:
Fast Search & Transfer ASA
>Environment:

FreeBSD not.fast.no 3.0-CURRENT FreeBSD 3.0-CURRENT #1: Fri Oct 23 00:39:19 CEST 1998     root@not.fast.no:/usr/src/sys/compile/NOT  i386

>Description:

A system I manage recently hung due to a user having used the ls command while
a grep process was running.

The grep program was GNU grep version 2.1, which optimizes reads by
using mmap.  The final fragment is retrieved using read.

If, during the read(), another process attempts to obtain an exclusive
lock on the vnode (e.g. via the lstat() system call performed by ls),
vm_fault() blocks when attempting to obtain a second shared lock
on the vnode (vn_read obtained the first shared lock).  Deadlock.

#0  mi_switch () at ../../kern/kern_synch.c:683
#1  0xe013a0cd in tsleep (ident=0xe1c8ae00, priority=8, 
    wmesg=0xe01c75d3 "inode", timo=0) at ../../kern/kern_synch.c:452
#2  0xe0133673 in acquire (lkp=0xe1c8ae00, extflags=16777280, wanted=1792)
    at ../../kern/kern_lock.c:152
#3  0xe013383c in lockmgr (lkp=0xe1c8ae00, flags=16973889, 
    interlkp=0xeb081648, p=0xeae88e00) at ../../kern/kern_lock.c:207
#4  0xe0157720 in vop_stdlock (ap=0xeafc3c84) at ../../kern/vfs_default.c:201
#5  0xe01cfc95 in ufs_vnoperate (ap=0xeafc3c84)
    at ../../ufs/ufs/ufs_vnops.c:2291
#6  0xe0160593 in vn_lock (vp=0xeb0815e0, flags=16973889, p=0xeae88e00)
    at vnode_if.h:811
#7  0xe0159ecf in vget (vp=0xeb0815e0, flags=16908353, p=0xeae88e00)
    at ../../kern/vfs_subr.c:1284
#8  0xe01dfa3a in vnode_pager_lock (object=0xeb031660)
    at ../../vm/vnode_pager.c:933
#9  0xe01d268a in vm_fault (map=0xeae8d440, vaddr=554504192, 
    fault_type=3 '\003', fault_flags=8) at ../../vm/vm_fault.c:246
#10 0xe01f1bd2 in trap_pfault (frame=0xeafc3dd8, usermode=0)
    at ../../i386/i386/trap.c:760
#11 0xe01f186f in trap (frame={tf_es = 16, tf_ds = 16, tf_edi = 554504192, 
      tf_esi = -418590720, tf_ebp = -352567740, tf_isp = -352567808, 
      tf_ebx = 8192, tf_edx = -418590720, tf_ecx = 2048, tf_eax = 554512384, 
      tf_trapno = 12, tf_err = 2, tf_eip = -534838059, tf_cs = 8, 
      tf_eflags = 66054, tf_esp = 8192, tf_ss = -352567504})
    at ../../i386/i386/trap.c:399
#12 0xe01f04d5 in generic_copyout ()
#13 0xe01c8053 in ffs_read (ap=0xeafc3eec) at ../../ufs/ufs/ufs_readwrite.c:204
#14 0xe016004d in vn_read (fp=0xe1ce69c0, uio=0xeafc3f30, cred=0xe1cf8200)
    at vnode_if.h:303
#15 0xe01409fd in read (p=0xeae88e00, uap=0xeafc3f84)
    at ../../kern/sys_generic.c:121
#16 0xe01f2453 in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi = -541076236, 
      tf_esi = 2, tf_ebp = -541076280, tf_isp = -352567340, 
      tf_ebx = -541076224, tf_edx = 0, tf_ecx = 0, tf_eax = 3, tf_trapno = 12, 
      tf_err = 2, tf_eip = 554187896, tf_cs = 31, tf_eflags = 531, 
      tf_esp = -541076412, tf_ss = 39}) at ../../i386/i386/trap.c:1038
#17 0xe01e6e4c in Xint0x80_syscall ()
#18 0x8048519 in ?? ()


>How-To-Repeat:

>Fix:
>Release-Note:
>Audit-Trail:

From: Luoqi Chen <luoqi@watermarkgroup.com>
To: freebsd-gnats-submit@freebsd.org, tegge@not.fast.no
Cc: dg@freebsd.org
Subject: Re: kern/8416: vm_fault might deadlock when locking backing store vnode
Date: Wed, 28 Oct 1998 10:33:00 -0500 (EST)

 I have seen the same problem once. It's a deadlock caused by vm_fault()
 trying to lock vm map and vnode in the wrong order. For detail, you may
 look up my original message in -current archive searching for "deadlock".
 There's fix in that message, which I will reproduce here too. Tor, would
 you review it for me?
 
 -lq
 
 Index: vm_fault.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/vm/vm_fault.c,v
 retrieving revision 1.88
 diff -u -r1.88 vm_fault.c
 --- vm_fault.c	1998/09/04 08:06:57	1.88
 +++ vm_fault.c	1998/09/23 21:54:14
 @@ -656,6 +656,14 @@
  		 */
  
  		/*
 +		 * Unlock vnode before the lookup to avoid deadlock
 +		 */
 +		if (fs.vp != NULL) {
 +			vput(fs.vp);
 +			fs.vp = NULL;
 +		}
 +
 +		/*
  		 * To avoid trying to write_lock the map while another process
  		 * has it read_locked (in vm_map_pageable), we do not try for
  		 * write permission.  If the page is still writable, we will
State-Changed-From-To: open->closed 
State-Changed-By: dg 
State-Changed-When: Tue May 11 01:04:23 PDT 1999 
State-Changed-Why:  
The more extensive fix in -current has been back-ported. Please verify 
ASAP that it fixes the problem. 
>Unformatted:
 >Workaround: 
 
 Allow vm_fault to obtain a shared lock on the vnode even though an exclusive
 lock has been requested (but not obtained) by a different process.
 
 Index: kern_lock.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/kern/kern_lock.c,v
 retrieving revision 1.19
 diff -u -r1.19 kern_lock.c
 --- kern_lock.c	1998/04/17 04:53:44	1.19
 +++ kern_lock.c	1998/10/22 22:34:21
 @@ -203,6 +204,12 @@
  
  	case LK_SHARED:
  		if (lkp->lk_lockholder != pid) {
 +			if ((lkp->lk_flags & LK_SHARE_NONZERO) != 0 &&
 +			    (flags & LK_CANRECURSE) != 0) {
 +				sharelock(lkp, 1);
 +				COUNT(p, 1);
 +				break;
 +			}
  			error = acquire(lkp, extflags,
  				LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE);
  			if (error)
 
 
