Subject: kern/10377: dounmount() leaks vnodes
To: None <gnats-bugs@gnats.netbsd.org>
From: IWAMOTO Toshihiro <iwamoto@sat.t.u-tokyo.ac.jp>
List: netbsd-bugs
Date: 06/16/2000 04:05:19
>Number:         10377
>Category:       kern
>Synopsis:       dounmount() leaks vnodes
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jun 16 04:06:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     IWAMOTO Toshihiro
>Release:        yesterday's -current
>Organization:
	
>Environment:
	
System: NetBSD kiku.my.domain 1.4ZD NetBSD 1.4ZD (KIKU) #35: Fri Jun 16 19:22:06 JST 2000 toshii@kiku.my.domain:/usr/src/syssrc/sys/arch/i386/compile/KIKU i386


>Description:
	vfs_allocate_syncvnode() calls getnewvnode(), which removes
	one element from the vnode free list.
	But, dounmount() doesn't put the allocated vnode onto the free list.
>How-To-Repeat:
	Configure a system with amd(8) and wait about a week,
	or more quickly:

	# i=0; while [ $i -lt 1000 ]; do mount /dev/vnd0a /mnt; umount /mnt; i=$(($i+1)); done
	# pstat -T
	
>Fix:
	The following patch prevents vnode leaks, while I don't feel this
	patch is quite correct.

Index: vfs_syscalls.c
===================================================================
RCS file: /export/kiku/NetBSD/NetBSD-CVS/syssrc/sys/kern/vfs_syscalls.c,v
retrieving revision 1.156
diff -u -r1.156 vfs_syscalls.c
--- vfs_syscalls.c	2000/04/17 14:31:22	1.156
+++ vfs_syscalls.c	2000/06/16 10:21:45
@@ -329,7 +329,8 @@
 				error = vfs_allocate_syncvnode(mp);
 		} else {
 			if (mp->mnt_syncer != NULL) {
-				vgone(mp->mnt_syncer);
+				mp->mnt_syncer->v_writecount--;
+				vrele(mp->mnt_syncer);
 				mp->mnt_syncer = NULL;
 			}
 		}
@@ -498,7 +499,8 @@
 	mp->mnt_flag &= ~MNT_ASYNC;
 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
 	if (mp->mnt_syncer != NULL) {
-		vgone(mp->mnt_syncer);
+		mp->mnt_syncer->v_writecount--;
+		vrele(mp->mnt_syncer);
 		mp->mnt_syncer = NULL;
 	}
 	if (((mp->mnt_flag & MNT_RDONLY) ||
>Release-Note:
>Audit-Trail:
>Unformatted: