Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 Apr 1997 15:32:01 +0200 (MET DST)
From:      Tor Egge <Tor.Egge@idi.ntnu.no>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/3184: vnodes are used after they are freed.
Message-ID:  <199704031332.PAA00920@ikke.idt.unit.no>
Resent-Message-ID: <199704031340.FAA22753@freefall.freebsd.org>

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

>Number:         3184
>Category:       kern
>Synopsis:       vnodes are used after they are freed.
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Apr  3 05:40:05 PST 1997
>Last-Modified:
>Originator:     Tor Egge
>Organization:
Norwegian University of Science and Technology, Trondheim, Norway
>Release:        FreeBSD 3.0-CURRENT i386
>Environment:

FreeBSD ikke.idt.unit.no 3.0-CURRENT FreeBSD 3.0-CURRENT #5: Thu Apr  3 00:28:21 MET DST 1997     root@ikke.idt.unit.no:/usr/src/sys/compile/TEGGE  i386

>Description:

Current directory is /export/akg7/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...
IdlePTD 230000
current pcb at 20a648
panic: lockmgr: pid %d, not %s %d unlocking
#0  boot (howto=256) at ../../kern/kern_shutdown.c:244
(kgdb) where
#0  boot (howto=256) at ../../kern/kern_shutdown.c:244
#1  0xe0114dc2 in panic (fmt=0xe01101b9 "lockmgr: pid %d, not %s %d unlocking")
    at ../../kern/kern_shutdown.c:368
#2  0xe01105c3 in lockmgr (lkp=0xf0518c34, flags=6, interlkp=0xf05f1360, 
    p=0xefa06400) at ../../kern/kern_lock.c:355
#3  0xe01abca6 in ufs_unlock (ap=0xdfbffd50) at ../../ufs/ufs/ufs_vnops.c:1784
#4  0xe015c01c in nfs_inactive (ap=0xdfbffd78) at vnode_if.h:843
#5  0xe0133985 in vputrele (vp=0xf05f1300, put=0) at vnode_if.h:775
#6  0xe01339ad in vrele (vp=0xf05f1300) at ../../kern/vfs_subr.c:1092
#7  0xe01b97a1 in vnode_pager_dealloc (object=0xf06b6700)
    at ../../vm/vnode_pager.c:203
#8  0xe01b8c96 in vm_pager_deallocate (object=0xf06b6700)
    at ../../vm/vm_pager.c:177
#9  0xe01b49dc in vm_object_terminate (object=0xf06b6700)
    at ../../vm/vm_object.c:420
#10 0xe01b480b in vm_object_deallocate (object=0xf06b6700)
    at ../../vm/vm_object.c:355
#11 0xe0133890 in vputrele (vp=0xf05f1300, put=1) at ../../kern/vfs_subr.c:1033
#12 0xe013399d in vput (vp=0xf05f1300) at ../../kern/vfs_subr.c:1085
#13 0xe0184c1a in nfs_remove (ap=0xdfbffef8) at ../../nfs/nfs_vnops.c:1515
#14 0xe01364a3 in unlink (p=0xefa06400, uap=0xdfbfff94, retval=0xdfbfff84)
    at vnode_if.h:531
#15 0xe01c651f in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi = 66112, 
      tf_esi = 1552370, tf_ebp = -541076432, tf_isp = -541065244, 
      tf_ebx = 7123, tf_edx = 420351332, tf_ecx = 1966080, tf_eax = 10, 
      tf_trapno = 7, tf_err = 7, tf_eip = 420181713, tf_cs = 31, 
      tf_eflags = 531, tf_esp = -541076448, tf_ss = 39})
    at ../../i386/i386/trap.c:890
#16 0x190b76d1 in ?? ()
#17 0x10e2b in ?? ()
#18 0x2c289 in ?? ()
#19 0x1095 in ?? ()
(kgdb) up 12
#12 0xe013399d in vput (vp=0xf05f1300) at ../../kern/vfs_subr.c:1085
(kgdb) print vp->v_op[0]@10
$1 = {0xe0131c74 <vn_default_error>, 0xe01abcd4 <ufs_strategy>, 
  0xe012e28c <vn_bwrite>, 0xe01a7330 <ufs_lookup>, 0xe01a9d30 <ufs_create>, 
  0xe01aa814 <ufs_whiteout>, 0xe01a9d64 <ufs_mknod>, 0xe01a9dd4 <ufs_open>, 
  0xe01a9e04 <ufs_close>, 0xe01a9e5c <ufs_access>}
(kgdb) 	

Somehow, the nfs vnode has been reused as a ufs vnode. This indicates that
the vnode has been put on the freelist too early.

When looking at vputrele, this is indeed the case. First the node is
put on the freelist, THEN the inactive routine is called. 

If VOP_INACTIVE can block for any reason, e.g., NFS sillyrename handling,
then the vnode can be reused by other processes while VOP_INACTIVE blocks.

>How-To-Repeat:

Perform lots of open(), unlink(), close() over NFS, while
there is activity on local (ufs) filesystems.

>Fix:

Insert the vnode onto the freelist AFTER having called VOP_INACTIVE.

Untested (but compileable) diff:
	
Index: vfs_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.81
diff -c -r1.81 vfs_subr.c
*** vfs_subr.c	1997/04/01 13:05:34	1.81
--- vfs_subr.c	1997/04/03 13:16:29
***************
*** 1049,1066 ****
  #endif
  		panic("vputrele: negative ref cnt");
  	}
- 	simple_lock(&vnode_free_list_slock);
- 	if (vp->v_flag & VAGE) {
- 		vp->v_flag &= ~VAGE;
- 		vp->v_usage = 0;
- 		if(vp->v_tag != VT_TFS)
- 			TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
- 	} else {
- 		if(vp->v_tag != VT_TFS)
- 			TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
- 	}
- 	freevnodes++;
- 	simple_unlock(&vnode_free_list_slock);
  
  	/*
  	 * If we are doing a vput, the node is already locked, and we must
--- 1049,1054 ----
***************
*** 1073,1078 ****
--- 1061,1079 ----
  	} else if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0) {
  		VOP_INACTIVE(vp, p);
  	}
+ 
+ 	simple_lock(&vnode_free_list_slock);
+ 	if (vp->v_flag & VAGE) {
+ 		vp->v_flag &= ~VAGE;
+ 		vp->v_usage = 0;
+ 		if(vp->v_tag != VT_TFS)
+ 			TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
+ 	} else {
+ 		if(vp->v_tag != VT_TFS)
+ 			TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+ 	}
+ 	freevnodes++;
+ 	simple_unlock(&vnode_free_list_slock);
  }
  
  /*


>Audit-Trail:
>Unformatted:



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