Module Name: src Committed By: hannken Date: Thu Mar 30 09:16:53 UTC 2017
Modified Files: src/sys/kern: vfs_vnode.c src/sys/miscfs/genfs: genfs_vnops.c layer_extern.h layer_vfsops.c layer_vnops.c src/sys/miscfs/nullfs: null_vnops.c src/sys/miscfs/overlay: overlay_vnops.c src/sys/miscfs/umapfs: umap_vnops.c src/sys/sys: param.h vnode.h vnode_impl.h Log Message: Locking a layer vnode is racy as it may become reclaimed before calling the operation on the lower vnode. Replace vi_lock with a rw_obj and change layered file systems to share the lock with the lower vnode. Layered file systems now use genfs_lock()/_unlock/_islocked(). Welcome to 7.99.67 To generate a diff of this commit: cvs rdiff -u -r1.80 -r1.81 src/sys/kern/vfs_vnode.c cvs rdiff -u -r1.193 -r1.194 src/sys/miscfs/genfs/genfs_vnops.c cvs rdiff -u -r1.38 -r1.39 src/sys/miscfs/genfs/layer_extern.h cvs rdiff -u -r1.47 -r1.48 src/sys/miscfs/genfs/layer_vfsops.c cvs rdiff -u -r1.60 -r1.61 src/sys/miscfs/genfs/layer_vnops.c cvs rdiff -u -r1.40 -r1.41 src/sys/miscfs/nullfs/null_vnops.c cvs rdiff -u -r1.22 -r1.23 src/sys/miscfs/overlay/overlay_vnops.c cvs rdiff -u -r1.58 -r1.59 src/sys/miscfs/umapfs/umap_vnops.c cvs rdiff -u -r1.533 -r1.534 src/sys/sys/param.h cvs rdiff -u -r1.274 -r1.275 src/sys/sys/vnode.h cvs rdiff -u -r1.12 -r1.13 src/sys/sys/vnode_impl.h 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.80 src/sys/kern/vfs_vnode.c:1.81 --- src/sys/kern/vfs_vnode.c:1.80 Thu Mar 30 09:15:51 2017 +++ src/sys/kern/vfs_vnode.c Thu Mar 30 09:16:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_vnode.c,v 1.80 2017/03/30 09:15:51 hannken Exp $ */ +/* $NetBSD: vfs_vnode.c,v 1.81 2017/03/30 09:16:52 hannken Exp $ */ /*- * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. @@ -156,7 +156,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.80 2017/03/30 09:15:51 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.81 2017/03/30 09:16:52 hannken Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -416,6 +416,21 @@ vnis_marker(vnode_t *vp) } /* + * Set vnode to share another vnodes lock. + */ +void +vshare_lock(vnode_t *vp, vnode_t *src_vp) +{ + vnode_impl_t *vip = VNODE_TO_VIMPL(vp); + vnode_impl_t *src_vip = VNODE_TO_VIMPL(src_vp); + krwlock_t *oldlock = vip->vi_lock; + + rw_obj_hold(src_vip->vi_lock); + vip->vi_lock = src_vip->vi_lock; + rw_obj_free(oldlock); +} + +/* * Return the lru list this node should be on. */ static vnodelst_t * @@ -1066,7 +1081,7 @@ vcache_alloc(void) vip = pool_cache_get(vcache_pool, PR_WAITOK); memset(vip, 0, sizeof(*vip)); - rw_init(&vip->vi_lock); + vip->vi_lock = rw_obj_alloc(); /* SLIST_INIT(&vip->vi_hash); */ /* LIST_INIT(&vip->vi_nclist); */ /* LIST_INIT(&vip->vi_dnclist); */ @@ -1128,7 +1143,7 @@ vcache_free(vnode_impl_t *vip) if (vp->v_type == VBLK || vp->v_type == VCHR) spec_node_destroy(vp); - rw_destroy(&vip->vi_lock); + rw_obj_free(vip->vi_lock); uvm_obj_destroy(&vp->v_uobj, true); cv_destroy(&vp->v_cv); pool_cache_put(vcache_pool, vip); Index: src/sys/miscfs/genfs/genfs_vnops.c diff -u src/sys/miscfs/genfs/genfs_vnops.c:1.193 src/sys/miscfs/genfs/genfs_vnops.c:1.194 --- src/sys/miscfs/genfs/genfs_vnops.c:1.193 Wed Jan 11 09:08:59 2017 +++ src/sys/miscfs/genfs/genfs_vnops.c Thu Mar 30 09:16:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: genfs_vnops.c,v 1.193 2017/01/11 09:08:59 hannken Exp $ */ +/* $NetBSD: genfs_vnops.c,v 1.194 2017/03/30 09:16:52 hannken Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.193 2017/01/11 09:08:59 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.194 2017/03/30 09:16:52 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -295,7 +295,7 @@ genfs_deadlock(void *v) op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER); if (ISSET(flags, LK_NOWAIT)) { - if (! rw_tryenter(&vip->vi_lock, op)) + if (! rw_tryenter(vip->vi_lock, op)) return EBUSY; if (mutex_tryenter(vp->v_interlock)) { error = vdead_check(vp, VDEAD_NOWAIT); @@ -305,25 +305,25 @@ genfs_deadlock(void *v) } else error = EBUSY; if (error) - rw_exit(&vip->vi_lock); + rw_exit(vip->vi_lock); return error; } - rw_enter(&vip->vi_lock, op); + rw_enter(vip->vi_lock, op); mutex_enter(vp->v_interlock); error = vdead_check(vp, VDEAD_NOWAIT); if (error == EBUSY) { - rw_exit(&vip->vi_lock); + rw_exit(vip->vi_lock); error = vdead_check(vp, 0); KASSERT(error == ENOENT); mutex_exit(vp->v_interlock); - rw_enter(&vip->vi_lock, op); + rw_enter(vip->vi_lock, op); mutex_enter(vp->v_interlock); } KASSERT(error == ENOENT); mutex_exit(vp->v_interlock); if (! ISSET(flags, LK_RETRY)) { - rw_exit(&vip->vi_lock); + rw_exit(vip->vi_lock); return ENOENT; } return 0; @@ -341,7 +341,7 @@ genfs_deadunlock(void *v) vnode_t *vp = ap->a_vp; vnode_impl_t *vip = VNODE_TO_VIMPL(vp); - rw_exit(&vip->vi_lock); + rw_exit(vip->vi_lock); return 0; } @@ -367,7 +367,7 @@ genfs_lock(void *v) if (ISSET(flags, LK_NOWAIT)) { if (fstrans_start_nowait(mp, FSTRANS_SHARED)) return EBUSY; - if (! rw_tryenter(&vip->vi_lock, op)) { + if (! rw_tryenter(vip->vi_lock, op)) { fstrans_done(mp); return EBUSY; } @@ -377,18 +377,18 @@ genfs_lock(void *v) } else error = EBUSY; if (error) { - rw_exit(&vip->vi_lock); + rw_exit(vip->vi_lock); fstrans_done(mp); } return error; } fstrans_start(mp, FSTRANS_SHARED); - rw_enter(&vip->vi_lock, op); + rw_enter(vip->vi_lock, op); mutex_enter(vp->v_interlock); error = vdead_check(vp, VDEAD_NOWAIT); if (error) { - rw_exit(&vip->vi_lock); + rw_exit(vip->vi_lock); fstrans_done(mp); error = vdead_check(vp, 0); KASSERT(error == ENOENT); @@ -410,7 +410,7 @@ genfs_unlock(void *v) vnode_impl_t *vip = VNODE_TO_VIMPL(vp); struct mount *mp = vp->v_mount; - rw_exit(&vip->vi_lock); + rw_exit(vip->vi_lock); fstrans_done(mp); return 0; @@ -428,10 +428,10 @@ genfs_islocked(void *v) vnode_t *vp = ap->a_vp; vnode_impl_t *vip = VNODE_TO_VIMPL(vp); - if (rw_write_held(&vip->vi_lock)) + if (rw_write_held(vip->vi_lock)) return LK_EXCLUSIVE; - if (rw_read_held(&vip->vi_lock)) + if (rw_read_held(vip->vi_lock)) return LK_SHARED; return 0; Index: src/sys/miscfs/genfs/layer_extern.h diff -u src/sys/miscfs/genfs/layer_extern.h:1.38 src/sys/miscfs/genfs/layer_extern.h:1.39 --- src/sys/miscfs/genfs/layer_extern.h:1.38 Fri Feb 17 08:31:25 2017 +++ src/sys/miscfs/genfs/layer_extern.h Thu Mar 30 09:16:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: layer_extern.h,v 1.38 2017/02/17 08:31:25 hannken Exp $ */ +/* $NetBSD: layer_extern.h,v 1.39 2017/03/30 09:16:52 hannken Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -99,7 +99,6 @@ int layer_bypass(void *); int layer_getattr(void *); int layer_inactive(void *); int layer_reclaim(void *); -int layer_lock(void *); int layer_print(void *); int layer_bmap(void *); int layer_fsync(void *); @@ -114,5 +113,8 @@ int layer_revoke(void *); int layer_rmdir(void *); int layer_getpages(void *); int layer_putpages(void *); +#define layer_lock genfs_lock +#define layer_unlock genfs_unlock +#define layer_islocked genfs_islocked #endif /* _MISCFS_GENFS_LAYER_EXTERN_H_ */ Index: src/sys/miscfs/genfs/layer_vfsops.c diff -u src/sys/miscfs/genfs/layer_vfsops.c:1.47 src/sys/miscfs/genfs/layer_vfsops.c:1.48 --- src/sys/miscfs/genfs/layer_vfsops.c:1.47 Fri Feb 17 08:31:25 2017 +++ src/sys/miscfs/genfs/layer_vfsops.c Thu Mar 30 09:16:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: layer_vfsops.c,v 1.47 2017/02/17 08:31:25 hannken Exp $ */ +/* $NetBSD: layer_vfsops.c,v 1.48 2017/03/30 09:16:52 hannken Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -74,7 +74,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.47 2017/02/17 08:31:25 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.48 2017/03/30 09:16:52 hannken Exp $"); #include <sys/param.h> #include <sys/sysctl.h> @@ -223,6 +223,9 @@ layerfs_loadvnode(struct mount *mp, stru mutex_obj_hold(lowervp->v_interlock); uvm_obj_setlock(&vp->v_uobj, lowervp->v_interlock); + /* Share the lock with the lower node. */ + vshare_lock(vp, lowervp); + vp->v_tag = lmp->layerm_tag; vp->v_type = lowervp->v_type; vp->v_op = lmp->layerm_vnodeop_p; Index: src/sys/miscfs/genfs/layer_vnops.c diff -u src/sys/miscfs/genfs/layer_vnops.c:1.60 src/sys/miscfs/genfs/layer_vnops.c:1.61 --- src/sys/miscfs/genfs/layer_vnops.c:1.60 Fri Jan 27 10:47:13 2017 +++ src/sys/miscfs/genfs/layer_vnops.c Thu Mar 30 09:16:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: layer_vnops.c,v 1.60 2017/01/27 10:47:13 hannken Exp $ */ +/* $NetBSD: layer_vnops.c,v 1.61 2017/03/30 09:16:52 hannken Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -170,7 +170,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.60 2017/01/27 10:47:13 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.61 2017/03/30 09:16:52 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -743,48 +743,6 @@ layer_reclaim(void *v) return 0; } -int -layer_lock(void *v) -{ - struct vop_lock_args /* { - struct vnode *a_vp; - int a_flags; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - struct vnode *lowervp = LAYERVPTOLOWERVP(vp); - int flags = ap->a_flags; - int error; - - if (ISSET(flags, LK_NOWAIT)) { - error = VOP_LOCK(lowervp, flags); - if (error) - return error; - if (mutex_tryenter(vp->v_interlock)) { - error = vdead_check(vp, VDEAD_NOWAIT); - mutex_exit(vp->v_interlock); - } else - error = EBUSY; - if (error) - VOP_UNLOCK(lowervp); - return error; - } - - error = VOP_LOCK(lowervp, flags); - if (error) - return error; - - mutex_enter(vp->v_interlock); - error = vdead_check(vp, VDEAD_NOWAIT); - if (error) { - VOP_UNLOCK(lowervp); - error = vdead_check(vp, 0); - KASSERT(error == ENOENT); - } - mutex_exit(vp->v_interlock); - - return error; -} - /* * We just feed the returned vnode up to the caller - there's no need * to build a layer node on top of the node on which we're going to do Index: src/sys/miscfs/nullfs/null_vnops.c diff -u src/sys/miscfs/nullfs/null_vnops.c:1.40 src/sys/miscfs/nullfs/null_vnops.c:1.41 --- src/sys/miscfs/nullfs/null_vnops.c:1.40 Fri Jan 27 10:47:13 2017 +++ src/sys/miscfs/nullfs/null_vnops.c Thu Mar 30 09:16:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: null_vnops.c,v 1.40 2017/01/27 10:47:13 hannken Exp $ */ +/* $NetBSD: null_vnops.c,v 1.41 2017/03/30 09:16:52 hannken Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -80,7 +80,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: null_vnops.c,v 1.40 2017/01/27 10:47:13 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: null_vnops.c,v 1.41 2017/03/30 09:16:52 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -107,6 +107,8 @@ const struct vnodeopv_entry_desc null_vn { &vop_inactive_desc, layer_inactive }, { &vop_reclaim_desc, layer_reclaim }, { &vop_lock_desc, layer_lock }, + { &vop_unlock_desc, layer_unlock }, + { &vop_islocked_desc, layer_islocked }, { &vop_print_desc, layer_print }, { &vop_remove_desc, layer_remove }, { &vop_rename_desc, layer_rename }, Index: src/sys/miscfs/overlay/overlay_vnops.c diff -u src/sys/miscfs/overlay/overlay_vnops.c:1.22 src/sys/miscfs/overlay/overlay_vnops.c:1.23 --- src/sys/miscfs/overlay/overlay_vnops.c:1.22 Fri Jan 27 10:47:13 2017 +++ src/sys/miscfs/overlay/overlay_vnops.c Thu Mar 30 09:16:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: overlay_vnops.c,v 1.22 2017/01/27 10:47:13 hannken Exp $ */ +/* $NetBSD: overlay_vnops.c,v 1.23 2017/03/30 09:16:52 hannken Exp $ */ /* * Copyright (c) 1999, 2000 National Aeronautics & Space Administration @@ -67,7 +67,7 @@ * * Ancestors: * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92 - * $Id: overlay_vnops.c,v 1.22 2017/01/27 10:47:13 hannken Exp $ + * $Id: overlay_vnops.c,v 1.23 2017/03/30 09:16:52 hannken Exp $ * ...and... * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project */ @@ -126,7 +126,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: overlay_vnops.c,v 1.22 2017/01/27 10:47:13 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: overlay_vnops.c,v 1.23 2017/03/30 09:16:52 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -155,6 +155,8 @@ const struct vnodeopv_entry_desc overlay { &vop_inactive_desc, layer_inactive }, { &vop_reclaim_desc, layer_reclaim }, { &vop_lock_desc, layer_lock }, + { &vop_unlock_desc, layer_unlock }, + { &vop_islocked_desc, layer_islocked }, { &vop_print_desc, layer_print }, { &vop_remove_desc, layer_remove }, { &vop_rename_desc, layer_rename }, Index: src/sys/miscfs/umapfs/umap_vnops.c diff -u src/sys/miscfs/umapfs/umap_vnops.c:1.58 src/sys/miscfs/umapfs/umap_vnops.c:1.59 --- src/sys/miscfs/umapfs/umap_vnops.c:1.58 Fri Jan 27 10:47:13 2017 +++ src/sys/miscfs/umapfs/umap_vnops.c Thu Mar 30 09:16:53 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: umap_vnops.c,v 1.58 2017/01/27 10:47:13 hannken Exp $ */ +/* $NetBSD: umap_vnops.c,v 1.59 2017/03/30 09:16:53 hannken Exp $ */ /* * Copyright (c) 1992, 1993 @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: umap_vnops.c,v 1.58 2017/01/27 10:47:13 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: umap_vnops.c,v 1.59 2017/03/30 09:16:53 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -89,6 +89,8 @@ const struct vnodeopv_entry_desc umap_vn { &vop_inactive_desc, layer_inactive }, { &vop_reclaim_desc, layer_reclaim }, { &vop_lock_desc, layer_lock }, + { &vop_unlock_desc, layer_unlock }, + { &vop_islocked_desc, layer_islocked }, { &vop_open_desc, layer_open }, { &vop_close_desc, layer_close }, { &vop_setattr_desc, layer_setattr }, Index: src/sys/sys/param.h diff -u src/sys/sys/param.h:1.533 src/sys/sys/param.h:1.534 --- src/sys/sys/param.h:1.533 Tue Mar 14 09:04:16 2017 +++ src/sys/sys/param.h Thu Mar 30 09:16:53 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: param.h,v 1.533 2017/03/14 09:04:16 ozaki-r Exp $ */ +/* $NetBSD: param.h,v 1.534 2017/03/30 09:16:53 hannken Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1993 @@ -67,7 +67,7 @@ * 2.99.9 (299000900) */ -#define __NetBSD_Version__ 799006600 /* NetBSD 7.99.66 */ +#define __NetBSD_Version__ 799006700 /* NetBSD 7.99.67 */ #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \ (m) * 1000000) + (p) * 100) <= __NetBSD_Version__) Index: src/sys/sys/vnode.h diff -u src/sys/sys/vnode.h:1.274 src/sys/sys/vnode.h:1.275 --- src/sys/sys/vnode.h:1.274 Fri Feb 17 08:30:00 2017 +++ src/sys/sys/vnode.h Thu Mar 30 09:16:53 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vnode.h,v 1.274 2017/02/17 08:30:00 hannken Exp $ */ +/* $NetBSD: vnode.h,v 1.275 2017/03/30 09:16:53 hannken Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -516,6 +516,7 @@ bool vrecycle(struct vnode *); void vrele(struct vnode *); void vrele_async(struct vnode *); void vrele_flush(struct mount *); +void vshare_lock(vnode_t *, vnode_t *); int vtruncbuf(struct vnode *, daddr_t, bool, int); void vwakeup(struct buf *); int vdead_check(struct vnode *, int); Index: src/sys/sys/vnode_impl.h diff -u src/sys/sys/vnode_impl.h:1.12 src/sys/sys/vnode_impl.h:1.13 --- src/sys/sys/vnode_impl.h:1.12 Sat Mar 18 05:55:12 2017 +++ src/sys/sys/vnode_impl.h Thu Mar 30 09:16:53 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vnode_impl.h,v 1.12 2017/03/18 05:55:12 riastradh Exp $ */ +/* $NetBSD: vnode_impl.h,v 1.13 2017/03/30 09:16:53 hannken Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -76,7 +76,7 @@ struct vnode_impl { TAILQ_ENTRY(vnode_impl) vi_synclist; /* s: vnodes with dirty bufs */ TAILQ_ENTRY(vnode_impl) vi_mntvnodes; /* m: vnodes for mount point */ SLIST_ENTRY(vnode_impl) vi_hash; /* c: vnode cache list */ - krwlock_t vi_lock; /* -: lock for this vnode */ + krwlock_t *vi_lock; /* -: lock for this vnode */ struct vcache_key vi_key; /* c: vnode cache key */ }; typedef struct vnode_impl vnode_impl_t;