Module Name: src Committed By: snj Date: Fri Aug 25 05:46:47 UTC 2017
Modified Files: src/sys/kern [netbsd-8]: vfs_mount.c vfs_vnode.c src/sys/miscfs/deadfs [netbsd-8]: dead_vfsops.c src/sys/sys [netbsd-8]: vnode_impl.h Log Message: Pull up following revision(s) (requested by hannken in ticket #227): sys/sys/vnode_impl.h: revision 1.16 sys/kern/vfs_vnode.c: revision 1.97 sys/kern/vfs_vnode.c: revision 1.98 sys/kern/vfs_mount.c: revision 1.67 sys/miscfs/deadfs/dead_vfsops.c: revision 1.8 No need to cache anonymous device vnodes, they will never be looked up. Set key to (dead_rootmount, 0, NULL) and add assertions. -- Change forced unmount to revert open device vnodes to anonymous devices. To generate a diff of this commit: cvs rdiff -u -r1.65.2.1 -r1.65.2.2 src/sys/kern/vfs_mount.c cvs rdiff -u -r1.93.2.1 -r1.93.2.2 src/sys/kern/vfs_vnode.c cvs rdiff -u -r1.7 -r1.7.10.1 src/sys/miscfs/deadfs/dead_vfsops.c cvs rdiff -u -r1.13.6.1 -r1.13.6.2 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_mount.c diff -u src/sys/kern/vfs_mount.c:1.65.2.1 src/sys/kern/vfs_mount.c:1.65.2.2 --- src/sys/kern/vfs_mount.c:1.65.2.1 Sun Jun 4 20:35:01 2017 +++ src/sys/kern/vfs_mount.c Fri Aug 25 05:46:46 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_mount.c,v 1.65.2.1 2017/06/04 20:35:01 bouyer Exp $ */ +/* $NetBSD: vfs_mount.c,v 1.65.2.2 2017/08/25 05:46:46 snj Exp $ */ /*- * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.65.2.1 2017/06/04 20:35:01 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.65.2.2 2017/08/25 05:46:46 snj Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -558,9 +558,16 @@ vflush_one(vnode_t *vp, vnode_t *skipvp, return 0; /* * If FORCECLOSE is set, forcibly close the vnode. + * For block or character devices, revert to an + * anonymous device. For all other files, just + * kill them. */ if (flags & FORCECLOSE) { - vgone(vp); + if (vp->v_usecount > 1 && + (vp->v_type == VBLK || vp->v_type == VCHR)) + vcache_make_anon(vp); + else + vgone(vp); return 0; } vrele(vp); Index: src/sys/kern/vfs_vnode.c diff -u src/sys/kern/vfs_vnode.c:1.93.2.1 src/sys/kern/vfs_vnode.c:1.93.2.2 --- src/sys/kern/vfs_vnode.c:1.93.2.1 Sun Jun 4 20:35:01 2017 +++ src/sys/kern/vfs_vnode.c Fri Aug 25 05:46:46 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_vnode.c,v 1.93.2.1 2017/06/04 20:35:01 bouyer Exp $ */ +/* $NetBSD: vfs_vnode.c,v 1.93.2.2 2017/08/25 05:46:46 snj 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.93.2.1 2017/06/04 20:35:01 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.93.2.2 2017/08/25 05:46:46 snj Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -225,6 +225,7 @@ static void vnpanic(vnode_t *, const ch /* Routines having to do with the management of the vnode table. */ extern struct mount *dead_rootmount; extern int (**dead_vnodeop_p)(void *); +extern int (**spec_vnodeop_p)(void *); extern struct vfsops dead_vfsops; /* Vnode state operations and diagnostics. */ @@ -1028,6 +1029,8 @@ vcache_hash(const struct vcache_key *key { uint32_t hash = HASH32_BUF_INIT; + KASSERT(key->vk_key_len > 0); + hash = hash32_buf(&key->vk_mount, sizeof(struct mount *), hash); hash = hash32_buf(key->vk_key, key->vk_key_len, hash); return hash; @@ -1381,23 +1384,29 @@ vcache_new(struct mount *mp, struct vnod KASSERT(*vpp == NULL); return error; } - KASSERT(vip->vi_key.vk_key != NULL); KASSERT(vp->v_op != NULL); - hash = vcache_hash(&vip->vi_key); + KASSERT((vip->vi_key.vk_key_len == 0) == (mp == dead_rootmount)); + if (vip->vi_key.vk_key_len > 0) { + KASSERT(vip->vi_key.vk_key != NULL); + hash = vcache_hash(&vip->vi_key); - /* Wait for previous instance to be reclaimed, then insert new node. */ - mutex_enter(&vcache_lock); - while ((ovip = vcache_hash_lookup(&vip->vi_key, hash))) { - ovp = VIMPL_TO_VNODE(ovip); - mutex_enter(ovp->v_interlock); - mutex_exit(&vcache_lock); - error = vcache_vget(ovp); - KASSERT(error == ENOENT); + /* + * Wait for previous instance to be reclaimed, + * then insert new node. + */ mutex_enter(&vcache_lock); + while ((ovip = vcache_hash_lookup(&vip->vi_key, hash))) { + ovp = VIMPL_TO_VNODE(ovip); + mutex_enter(ovp->v_interlock); + mutex_exit(&vcache_lock); + error = vcache_vget(ovp); + KASSERT(error == ENOENT); + mutex_enter(&vcache_lock); + } + SLIST_INSERT_HEAD(&vcache_hashtab[hash & vcache_hashmask], + vip, vi_hash); + mutex_exit(&vcache_lock); } - SLIST_INSERT_HEAD(&vcache_hashtab[hash & vcache_hashmask], - vip, vi_hash); - mutex_exit(&vcache_lock); vfs_insmntque(vp, mp); if ((mp->mnt_iflag & IMNT_MPSAFE) != 0) vp->v_vflag |= VV_MPSAFE; @@ -1556,10 +1565,12 @@ vcache_reclaim(vnode_t *vp) } else { temp_key = temp_buf; } - mutex_enter(&vcache_lock); - memcpy(temp_key, vip->vi_key.vk_key, temp_key_len); - vip->vi_key.vk_key = temp_key; - mutex_exit(&vcache_lock); + if (vip->vi_key.vk_key_len > 0) { + mutex_enter(&vcache_lock); + memcpy(temp_key, vip->vi_key.vk_key, temp_key_len); + vip->vi_key.vk_key = temp_key; + mutex_exit(&vcache_lock); + } fstrans_start(mp); @@ -1604,13 +1615,15 @@ vcache_reclaim(vnode_t *vp) /* Purge name cache. */ cache_purge(vp); + if (vip->vi_key.vk_key_len > 0) { /* Remove from vnode cache. */ - hash = vcache_hash(&vip->vi_key); - mutex_enter(&vcache_lock); - KASSERT(vip == vcache_hash_lookup(&vip->vi_key, hash)); - SLIST_REMOVE(&vcache_hashtab[hash & vcache_hashmask], - vip, vnode_impl, vi_hash); - mutex_exit(&vcache_lock); + hash = vcache_hash(&vip->vi_key); + mutex_enter(&vcache_lock); + KASSERT(vip == vcache_hash_lookup(&vip->vi_key, hash)); + SLIST_REMOVE(&vcache_hashtab[hash & vcache_hashmask], + vip, vnode_impl, vi_hash); + mutex_exit(&vcache_lock); + } if (temp_key != temp_buf) kmem_free(temp_key, temp_key_len); @@ -1638,6 +1651,72 @@ vcache_reclaim(vnode_t *vp) } /* + * Disassociate the underlying file system from an open device vnode + * and make it anonymous. + * + * Vnode unlocked on entry, drops a reference to the vnode. + */ +void +vcache_make_anon(vnode_t *vp) +{ + vnode_impl_t *vip = VNODE_TO_VIMPL(vp); + uint32_t hash; + bool recycle; + + KASSERT(vp->v_type == VBLK || vp->v_type == VCHR); + KASSERT((vp->v_mount->mnt_iflag & IMNT_HAS_TRANS) == 0 || + fstrans_is_owner(vp->v_mount)); + VSTATE_ASSERT_UNLOCKED(vp, VS_ACTIVE); + + /* Remove from vnode cache. */ + hash = vcache_hash(&vip->vi_key); + mutex_enter(&vcache_lock); + KASSERT(vip == vcache_hash_lookup(&vip->vi_key, hash)); + SLIST_REMOVE(&vcache_hashtab[hash & vcache_hashmask], + vip, vnode_impl, vi_hash); + vip->vi_key.vk_mount = dead_rootmount; + vip->vi_key.vk_key_len = 0; + vip->vi_key.vk_key = NULL; + mutex_exit(&vcache_lock); + + /* + * Disassociate the underlying file system from the vnode. + * VOP_INACTIVE leaves the vnode locked; VOP_RECLAIM unlocks + * the vnode, and may destroy the vnode so that VOP_UNLOCK + * would no longer function. + */ + if (vn_lock(vp, LK_EXCLUSIVE)) { + vnpanic(vp, "%s: cannot lock", __func__); + } + VOP_INACTIVE(vp, &recycle); + KASSERT((vp->v_vflag & VV_LOCKSWORK) == 0 || + VOP_ISLOCKED(vp) == LK_EXCLUSIVE); + if (VOP_RECLAIM(vp)) { + vnpanic(vp, "%s: cannot reclaim", __func__); + } + + /* Purge name cache. */ + cache_purge(vp); + + /* Done with purge, change operations vector. */ + mutex_enter(vp->v_interlock); + vp->v_op = spec_vnodeop_p; + vp->v_vflag |= VV_MPSAFE; + vp->v_vflag &= ~VV_LOCKSWORK; + mutex_exit(vp->v_interlock); + + /* + * Move to dead mount. Must be after changing the operations + * vector as vnode operations enter the mount before using the + * operations vector. See sys/kern/vnode_if.c. + */ + vfs_ref(dead_rootmount); + vfs_insmntque(vp, dead_rootmount); + + vrele(vp); +} + +/* * Update outstanding I/O count and do wakeup if requested. */ void Index: src/sys/miscfs/deadfs/dead_vfsops.c diff -u src/sys/miscfs/deadfs/dead_vfsops.c:1.7 src/sys/miscfs/deadfs/dead_vfsops.c:1.7.10.1 --- src/sys/miscfs/deadfs/dead_vfsops.c:1.7 Wed Jul 1 08:13:53 2015 +++ src/sys/miscfs/deadfs/dead_vfsops.c Fri Aug 25 05:46:46 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: dead_vfsops.c,v 1.7 2015/07/01 08:13:53 hannken Exp $ */ +/* $NetBSD: dead_vfsops.c,v 1.7.10.1 2017/08/25 05:46:46 snj Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dead_vfsops.c,v 1.7 2015/07/01 08:13:53 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dead_vfsops.c,v 1.7.10.1 2017/08/25 05:46:46 snj Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -108,8 +108,8 @@ dead_newvnode(struct mount *mp, struct v uvm_vnp_setsize(vp, 0); spec_node_init(vp, vap->va_rdev); - *key_len = sizeof(vp->v_interlock); - *new_key = &vp->v_interlock; + *key_len = 0; + *new_key = NULL; return 0; } Index: src/sys/sys/vnode_impl.h diff -u src/sys/sys/vnode_impl.h:1.13.6.1 src/sys/sys/vnode_impl.h:1.13.6.2 --- src/sys/sys/vnode_impl.h:1.13.6.1 Sun Jun 4 20:35:01 2017 +++ src/sys/sys/vnode_impl.h Fri Aug 25 05:46:46 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vnode_impl.h,v 1.13.6.1 2017/06/04 20:35:01 bouyer Exp $ */ +/* $NetBSD: vnode_impl.h,v 1.13.6.2 2017/08/25 05:46:46 snj Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -119,6 +119,7 @@ vnode_t * vnalloc_marker(struct mount *); void vnfree_marker(vnode_t *); bool vnis_marker(vnode_t *); +void vcache_make_anon(vnode_t *); int vcache_vget(vnode_t *); int vcache_tryvget(vnode_t *); int vfs_drainvnodes(void);