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

Reply via email to