Module Name: src Committed By: riz Date: Thu Nov 22 18:51:14 UTC 2012
Modified Files: src/sys/kern [netbsd-6-0]: vfs_vnode.c vfs_vnops.c Log Message: Pull up following revision(s) (requested by hannken in ticket #692): sys/kern/vfs_vnode.c: revision 1.17 sys/kern/vfs_vnops.c: revision 1.186 Bring back Manuel Bouyers patch to resolve races between vget() and vrelel() resulting in vget() returning dead vnodes. It is impossible to resolve these races in vn_lock(). Needs pullup to NetBSD-6. To generate a diff of this commit: cvs rdiff -u -r1.15 -r1.15.8.1 src/sys/kern/vfs_vnode.c cvs rdiff -u -r1.183.8.1 -r1.183.8.1.4.1 src/sys/kern/vfs_vnops.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_vnode.c diff -u src/sys/kern/vfs_vnode.c:1.15 src/sys/kern/vfs_vnode.c:1.15.8.1 --- src/sys/kern/vfs_vnode.c:1.15 Tue Dec 20 16:49:37 2011 +++ src/sys/kern/vfs_vnode.c Thu Nov 22 18:51:14 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_vnode.c,v 1.15 2011/12/20 16:49:37 hannken Exp $ */ +/* $NetBSD: vfs_vnode.c,v 1.15.8.1 2012/11/22 18:51:14 riz Exp $ */ /*- * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. @@ -120,7 +120,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.15 2011/12/20 16:49:37 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.15.8.1 2012/11/22 18:51:14 riz Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -555,6 +555,22 @@ vget(vnode_t *vp, int flags) 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; + } + } + /* * Ok, we got it in good shape. Just locking left. */ @@ -665,8 +681,12 @@ retry: /* 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); mutex_exit(vp->v_interlock); error = vn_lock(vp, LK_EXCLUSIVE); if (error != 0) { @@ -674,6 +694,18 @@ retry: vnpanic(vp, "%s: unable to lock %p", __func__, vp); } + 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); + 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) { /* @@ -709,6 +741,7 @@ retry: if (++vrele_pending > (desiredvnodes >> 8)) cv_signal(&vrele_cv); mutex_exit(&vrele_lock); + cv_broadcast(&vp->v_cv); mutex_exit(vp->v_interlock); return; } @@ -726,6 +759,7 @@ retry: 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/kern/vfs_vnops.c diff -u src/sys/kern/vfs_vnops.c:1.183.8.1 src/sys/kern/vfs_vnops.c:1.183.8.1.4.1 --- src/sys/kern/vfs_vnops.c:1.183.8.1 Thu Apr 12 17:15:23 2012 +++ src/sys/kern/vfs_vnops.c Thu Nov 22 18:51:14 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_vnops.c,v 1.183.8.1 2012/04/12 17:15:23 riz Exp $ */ +/* $NetBSD: vfs_vnops.c,v 1.183.8.1.4.1 2012/11/22 18:51:14 riz Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.183.8.1 2012/04/12 17:15:23 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.183.8.1.4.1 2012/11/22 18:51:14 riz Exp $"); #include "veriexec.h" @@ -805,15 +805,6 @@ vn_lock(struct vnode *vp, int flags) } else { mutex_exit(vp->v_interlock); error = VOP_LOCK(vp, (flags & ~LK_RETRY)); - if (error == 0 && (flags & LK_RETRY) == 0) { - mutex_enter(vp->v_interlock); - if ((vp->v_iflag & VI_CLEAN)) { - mutex_exit(vp->v_interlock); - VOP_UNLOCK(vp); - return ENOENT; - } - mutex_exit(vp->v_interlock); - } if (error == 0 || error == EDEADLK || error == EBUSY) return (error); }