Module Name:    src
Committed By:   sborrill
Date:           Sat Nov 28 18:59:11 UTC 2009

Modified Files:
        src/sys/kern [netbsd-5]: vfs_subr.c

Log Message:
Pull up the following revisions(s) (requested by bouyer in ticket #1171):
        sys/kern/vfs_subr.c:    revision 1.392

Previous caused a deadlock with layered FS: the vrele thread can sleep on
the vnode lock, while vget is sleeping on the VI_INACTNOW flag (or the vget
caller is looping on vget returning failure because of the VI_INACTNOW
flag). With layered FSes, the upper and lower vnodes share the same lock, so
the vget() caller above can be already holding the vnode lock.

Fix by dropping VI_INACTNOW before sleeping on the vnode lock in
vrelel(), and check the ref count again once we have the lock. If the
vnode has more than one reference, don't VOP_INACTIVE it.
Fix PR kern/42318 and PR kern/42377


To generate a diff of this commit:
cvs rdiff -u -r1.357.4.7 -r1.357.4.8 src/sys/kern/vfs_subr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/vfs_subr.c
diff -u src/sys/kern/vfs_subr.c:1.357.4.7 src/sys/kern/vfs_subr.c:1.357.4.8
--- src/sys/kern/vfs_subr.c:1.357.4.7	Sat Nov 21 20:07:49 2009
+++ src/sys/kern/vfs_subr.c	Sat Nov 28 18:59:11 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_subr.c,v 1.357.4.7 2009/11/21 20:07:49 snj Exp $	*/
+/*	$NetBSD: vfs_subr.c,v 1.357.4.8 2009/11/28 18:59:11 sborrill Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.357.4.7 2009/11/21 20:07:49 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.357.4.8 2009/11/28 18:59:11 sborrill Exp $");
 
 #include "opt_ddb.h"
 #include "opt_compat_netbsd.h"
@@ -1411,14 +1411,30 @@
 			/* The pagedaemon can't wait around; defer. */
 			defer = true;
 		} else if (curlwp == vrele_lwp) {
-			/* We have to try harder. */
-			vp->v_iflag &= ~VI_INACTREDO;
+			/*
+			 * We have to try harder. But we can't sleep
+			 * with VI_INACTNOW as vget() may be waiting on it.
+			 */
+			vp->v_iflag &= ~(VI_INACTREDO|VI_INACTNOW);
+			cv_broadcast(&vp->v_cv);
 			error = vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK |
 			    LK_RETRY);
 			if (error != 0) {
 				/* XXX */
 				vpanic(vp, "vrele: unable to lock %p");
 			}
+			mutex_enter(&vp->v_interlock);
+			/*
+			 * if we did get another reference while
+			 * sleeping, don't try to inactivate it yet.
+			 */
+			if (__predict_false(vtryrele(vp))) {
+				VOP_UNLOCK(vp, 0);
+				mutex_exit(&vp->v_interlock);
+				return;
+			}
+			vp->v_iflag |= VI_INACTNOW;
+			mutex_exit(&vp->v_interlock);
 			defer = false;
 		} else if ((vp->v_iflag & VI_LAYER) != 0) {
 			/* 

Reply via email to