Module Name:    src
Committed By:   snj
Date:           Sun Nov  8 22:49:06 UTC 2009

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

Log Message:
Pull up following revision(s) (requested by bouyer in ticket #1129):
        sys/kern/vfs_subr.c: revision 1.386
        sys/ufs/ufs/ufs_ihash.c: revision 1.28
getcleanvnode(): don't vclean() the vnode if it has gained another
  reference while we were getting the v_interlock.
vget(): attempt prevent it from returning a clean vnode:
  if the vnode is being inactivated (by vrelel()), wait for
  vrelel() to complete (or return EBUSY if we can't wait), and return
  ENOENT if the vnode has been vclean'ed by vrelel()
Fix kern/41147 in a better way, hopefully fix other related race conditions.


To generate a diff of this commit:
cvs rdiff -u -r1.357.4.5 -r1.357.4.6 src/sys/kern/vfs_subr.c
cvs rdiff -u -r1.26.10.1 -r1.26.10.2 src/sys/ufs/ufs/ufs_ihash.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.5 src/sys/kern/vfs_subr.c:1.357.4.6
--- src/sys/kern/vfs_subr.c:1.357.4.5	Tue Jul 21 00:31:58 2009
+++ src/sys/kern/vfs_subr.c	Sun Nov  8 22:49:05 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_subr.c,v 1.357.4.5 2009/07/21 00:31:58 snj Exp $	*/
+/*	$NetBSD: vfs_subr.c,v 1.357.4.6 2009/11/08 22:49:05 snj 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.5 2009/07/21 00:31:58 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.357.4.6 2009/11/08 22:49:05 snj Exp $");
 
 #include "opt_ddb.h"
 #include "opt_compat_netbsd.h"
@@ -370,6 +370,17 @@
 	vp->v_freelisthd = NULL;
 	mutex_exit(&vnode_free_list_lock);
 
+	if (vp->v_usecount != 0) {
+		/*
+		 * was referenced again before we got the interlock
+		 * Don't return to freelist - the holder of the last
+		 * reference will destroy it.
+		 */
+		vrelel(vp, 0); /* releases vp->v_interlock */
+		mutex_enter(&vnode_free_list_lock);
+		goto retry;
+	}
+
 	/*
 	 * The vnode is still associated with a file system, so we must
 	 * clean it out before reusing it.  We need to add a reference
@@ -1288,6 +1299,22 @@
 		vrelel(vp, 0);
 		return ENOENT;
 	}
+
+	if ((vp->v_iflag & VI_INACTNOW) != 0) {
+		/*
+		 * if it's being desactived, wait for it to complete.
+		 * Make sure to not return a clean vnode.
+		 */
+		 if ((flags & LK_NOWAIT) != 0) {
+			vrelel(vp, 0);
+			return EBUSY;
+		}
+		vwait(vp, VI_INACTNOW);
+		if ((vp->v_iflag & VI_CLEAN) != 0) {
+			vrelel(vp, 0);
+			return ENOENT;
+		}
+	}
 	if (flags & LK_TYPE_MASK) {
 		error = vn_lock(vp, flags | LK_INTERLOCK);
 		if (error != 0) {
@@ -1427,6 +1454,7 @@
 			if (++vrele_pending > (desiredvnodes >> 8))
 				cv_signal(&vrele_cv); 
 			mutex_exit(&vrele_lock);
+			cv_broadcast(&vp->v_cv);
 			mutex_exit(&vp->v_interlock);
 			return;
 		}
@@ -1451,6 +1479,7 @@
 		VOP_INACTIVE(vp, &recycle);
 		mutex_enter(&vp->v_interlock);
 		vp->v_iflag &= ~VI_INACTNOW;
+		cv_broadcast(&vp->v_cv);
 		if (!recycle) {
 			if (vtryrele(vp)) {
 				mutex_exit(&vp->v_interlock);

Index: src/sys/ufs/ufs/ufs_ihash.c
diff -u src/sys/ufs/ufs/ufs_ihash.c:1.26.10.1 src/sys/ufs/ufs/ufs_ihash.c:1.26.10.2
--- src/sys/ufs/ufs/ufs_ihash.c:1.26.10.1	Mon Sep 28 01:43:02 2009
+++ src/sys/ufs/ufs/ufs_ihash.c	Sun Nov  8 22:49:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_ihash.c,v 1.26.10.1 2009/09/28 01:43:02 snj Exp $	*/
+/*	$NetBSD: ufs_ihash.c,v 1.26.10.2 2009/11/08 22:49:06 snj Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_ihash.c,v 1.26.10.1 2009/09/28 01:43:02 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_ihash.c,v 1.26.10.2 2009/11/08 22:49:06 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -152,15 +152,6 @@
 				mutex_exit(&ufs_ihash_lock);
 				if (vget(vp, flags | LK_INTERLOCK))
 					goto loop;
-				if (VTOI(vp) != ip ||
-				    ip->i_number != inum || ip->i_dev != dev) {
-					/* lost race against vclean() */
-					if (vlockmgr(vp->v_vnlock, LK_RELEASE))
-						printf("can't release lock\n");
-					vrele(vp);
-					vp = NULL;
-					goto loop;
-				}
 			}
 			return (vp);
 		}

Reply via email to