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); }