Module Name:    src
Committed By:   bouyer
Date:           Sun Jun  4 20:35:02 UTC 2017

Modified Files:
        src/share/man/man9 [netbsd-8]: fstrans.9
        src/sys/kern [netbsd-8]: vfs_mount.c vfs_subr.c vfs_trans.c vfs_vnode.c
            vnode_if.c vnode_if.sh vnode_if.src
        src/sys/miscfs/genfs [netbsd-8]: genfs_io.c genfs_vnops.c
            layer_extern.h layer_vfsops.c layer_vnops.c
        src/sys/miscfs/nullfs [netbsd-8]: null_vnops.c
        src/sys/miscfs/overlay [netbsd-8]: overlay_vnops.c
        src/sys/miscfs/umapfs [netbsd-8]: umap_vnops.c
        src/sys/rump/include/rump [netbsd-8]: rumpvnode_if.h
        src/sys/rump/librump/rumpkern [netbsd-8]: emul.c
        src/sys/rump/librump/rumpvfs [netbsd-8]: rumpvnode_if.c
        src/sys/sys [netbsd-8]: fstrans.h vnode.h vnode_if.h vnode_impl.h
        src/sys/ufs/lfs [netbsd-8]: lfs_pages.c

Log Message:
pullup the following revisions, requested by hannken in ticket #2:
        src/share/man/man9/fstrans.9                    1.25
        src/sys/kern/vfs_mount.c                        1.66
        src/sys/kern/vfs_subr.c                         1.468
        src/sys/kern/vfs_trans.c                        1.46
        src/sys/kern/vfs_vnode.c                        1.94, 1.95, 1.96
        src/sys/kern/vnode_if.c                         1.105, 1.106
        src/sys/kern/vnode_if.sh                        1.65, 1.66
        src/sys/kern/vnode_if.src                       1.76
        src/sys/miscfs/genfs/genfs_io.c                 1.69
        src/sys/miscfs/genfs/genfs_vnops.c              1.196, 1.197
        src/sys/miscfs/genfs/layer_extern.h             1.40
        src/sys/miscfs/genfs/layer_vfsops.c             1.51
        src/sys/miscfs/genfs/layer_vnops.c              1.67
        src/sys/miscfs/nullfs/null_vnops.c              1.42
        src/sys/miscfs/overlay/overlay_vnops.c          1.24
        src/sys/miscfs/umapfs/umap_vnops.c              1.60
        src/sys/rump/include/rump/rumpvnode_if.h        1.29, 1.30
        src/sys/rump/librump/rumpkern/emul.c            1.182
        src/sys/rump/librump/rumpvfs/rumpvnode_if.c     1.29, 1.30
        src/sys/sys/fstrans.h                           1.11
        src/sys/sys/vnode.h                             1.278
        src/sys/sys/vnode_if.h                          1.100, 1.101
        src/sys/sys/vnode_impl.h                        1.14, 1.15
        src/sys/ufs/lfs/lfs_pages.c                     1.12

Vnode state, lock and fstrans cleanup:
- Rename vnode state "VS_ACTIVE" to "VS_LOADED" and add synthetic
  state "VS_ACTIVE" to assert a loaded vnode with usecount > 0.

- Redo FSTRANS in vnode_if.c and use it for VOP_LOCK and VOP_UNLOCK.

- Cleanup the genfs lock operations.

- Make "struct vnode_impl" member "vi_lock" a krwlock_t again.

- Remove the lock type argument from fstrans_start and
  fstrans_start_nowait,
  remove now unused FSTRANS state "FSTRANS_SUSPENDING".


To generate a diff of this commit:
cvs rdiff -u -r1.24 -r1.24.2.1 src/share/man/man9/fstrans.9
cvs rdiff -u -r1.65 -r1.65.2.1 src/sys/kern/vfs_mount.c
cvs rdiff -u -r1.467 -r1.467.2.1 src/sys/kern/vfs_subr.c
cvs rdiff -u -r1.45 -r1.45.2.1 src/sys/kern/vfs_trans.c
cvs rdiff -u -r1.93 -r1.93.2.1 src/sys/kern/vfs_vnode.c
cvs rdiff -u -r1.104 -r1.104.2.1 src/sys/kern/vnode_if.c
cvs rdiff -u -r1.64 -r1.64.4.1 src/sys/kern/vnode_if.sh
cvs rdiff -u -r1.75 -r1.75.2.1 src/sys/kern/vnode_if.src
cvs rdiff -u -r1.68 -r1.68.6.1 src/sys/miscfs/genfs/genfs_io.c
cvs rdiff -u -r1.195 -r1.195.4.1 src/sys/miscfs/genfs/genfs_vnops.c
cvs rdiff -u -r1.39 -r1.39.6.1 src/sys/miscfs/genfs/layer_extern.h
cvs rdiff -u -r1.50 -r1.50.2.1 src/sys/miscfs/genfs/layer_vfsops.c
cvs rdiff -u -r1.66 -r1.66.2.1 src/sys/miscfs/genfs/layer_vnops.c
cvs rdiff -u -r1.41 -r1.41.6.1 src/sys/miscfs/nullfs/null_vnops.c
cvs rdiff -u -r1.23 -r1.23.6.1 src/sys/miscfs/overlay/overlay_vnops.c
cvs rdiff -u -r1.59 -r1.59.6.1 src/sys/miscfs/umapfs/umap_vnops.c
cvs rdiff -u -r1.28 -r1.28.2.1 src/sys/rump/include/rump/rumpvnode_if.h
cvs rdiff -u -r1.181 -r1.181.6.1 src/sys/rump/librump/rumpkern/emul.c
cvs rdiff -u -r1.28 -r1.28.2.1 src/sys/rump/librump/rumpvfs/rumpvnode_if.c
cvs rdiff -u -r1.10 -r1.10.60.1 src/sys/sys/fstrans.h
cvs rdiff -u -r1.277 -r1.277.4.1 src/sys/sys/vnode.h
cvs rdiff -u -r1.99 -r1.99.2.1 src/sys/sys/vnode_if.h
cvs rdiff -u -r1.13 -r1.13.6.1 src/sys/sys/vnode_impl.h
cvs rdiff -u -r1.11 -r1.11.6.1 src/sys/ufs/lfs/lfs_pages.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man9/fstrans.9
diff -u src/share/man/man9/fstrans.9:1.24 src/share/man/man9/fstrans.9:1.24.2.1
--- src/share/man/man9/fstrans.9:1.24	Mon May 29 08:03:13 2017
+++ src/share/man/man9/fstrans.9	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-.\"     $NetBSD: fstrans.9,v 1.24 2017/05/29 08:03:13 wiz Exp $
+.\"     $NetBSD: fstrans.9,v 1.24.2.1 2017/06/04 20:35:01 bouyer Exp $
 .\"
 .\" Copyright (c) 2007 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd May 29, 2017
+.Dd June 4, 2017
 .Dt FSTRANS 9
 .Os
 .Sh NAME
@@ -46,9 +46,9 @@
 .In sys/mount.h
 .In sys/fstrans.h
 .Ft void
-.Fn fstrans_start "struct mount *mp" "enum fstrans_lock_type lock_type"
+.Fn fstrans_start "struct mount *mp"
 .Ft int
-.Fn fstrans_start_nowait "struct mount *mp" "enum fstrans_lock_type lock_type"
+.Fn fstrans_start_nowait "struct mount *mp"
 .Ft void
 .Fn fstrans_done "struct mount *mp"
 .Ft int
@@ -81,17 +81,6 @@ in a
 transaction, which is blocked by suspending the file system and while
 it is suspended.
 .Pp
-Operations needed to sync the file system to its backing store must be
-bracketed by
-.Fn fstrans_start
-and
-.Fn fstrans_done
-in a
-.Em lazy
-transaction, which is allowed while suspending the file system in order
-to sync it to its backing store, but blocked while the file system is
-suspended.
-.Pp
 Transactions are per-thread and nestable: if a thread is already in a
 transaction, it can enter another transaction without blocking.
 Each
@@ -108,12 +97,8 @@ to:
 .Bl -dash
 .It
 enter the
-.Dv FSTRANS_SUSPENDING
-to suspend all normal operations but allow syncing,
-.It
-enter the
 .Dv FSTRANS_SUSPENDED
-state to suspend all operations once synced, and
+state to suspend all operations, and
 .It
 restore to the
 .Dv FSTRANS_NORMAL
@@ -140,24 +125,14 @@ The copy-on-write callback must be dises
 when the file system is done with it.
 .Sh FUNCTIONS
 .Bl -tag -width abcd
-.It Fn fstrans_start "mp" "lock_type"
-Enter a transaction of type
-.Fa lock_type
-on the file system
+.It Fn fstrans_start "mp"
+Enter a transaction on the file system
 .Fa mp
 in the current thread.
 If the file system is in a state that blocks such transactions, wait
 until it changes state to one that does not.
-.Bl -tag -width FSTRANS_SHARED
-.It Dv FSTRANS_SHARED
-If the file system is suspending or suspended, wait until it is
-resumed.
-Intended for normal file system operations.
-.It Dv FSTRANS_LAZY
+.Pp
 If the file system is suspended, wait until it is resumed.
-Intended for operations needed to sync the file system to its backing
-store in order to suspend it.
-.El
 .Pp
 However, if the current thread is already in a transaction on
 .Fa mp ,
@@ -166,14 +141,12 @@ will enter a nested transaction and retu
 waiting.
 .Pp
 May sleep.
-.It Fn fstrans_start_nowait "mp" "lock_type"
+.It Fn fstrans_start_nowait "mp"
 Like
 .Fn fstrans_start ,
 but return
 .Dv EBUSY
-immediately if
-.Fa lock_type
-transactions are blocked in its current state.
+immediately if transactions are blocked in its current state.
 .Pp
 May sleep nevertheless on internal locks.
 .It Fn fstrans_done "mp"
@@ -192,15 +165,9 @@ to
 and wait for all transactions not allowed in
 .Fa new_state
 to complete.
-.Bl -tag -width FSTRANS_SUSPENDING
+.Bl -tag -width FSTRANS_SUSPENDED
 .It Dv FSTRANS_NORMAL
 Allow all transactions.
-.It Dv FSTRANS_SUSPENDING
-Block
-.Dv FSTRANS_SHARED
-transactions but allow
-.Dv FSTRANS_LAZY
-transactions.
 .It Dv FSTRANS_SUSPENDED
 Block all transactions.
 .El
@@ -277,12 +244,6 @@ xxx_suspendctl(struct mount *mp, int cmd
 
 	switch (cmd) {
 	case SUSPEND_SUSPEND:
-		error = fstrans_setstate(mp, FSTRANS_SUSPENDING);
-		if (error)
-			return error;
-
-		/* Sync file system state to disk. */
-
 		return fstrans_setstate(mp, FSTRANS_SUSPENDED);
 
 	case SUSPEND_RESUME:
@@ -303,7 +264,7 @@ xxx_create(void *v)
 	struct mount *mp = ap-\*[Gt]a_dvp-\*[Gt]v_mount;
 	int error;
 
-	fstrans_start(mp, FSTRANS_SHARED);
+	fstrans_start(mp);
 
 	/* Actually create the node. */
 

Index: src/sys/kern/vfs_mount.c
diff -u src/sys/kern/vfs_mount.c:1.65 src/sys/kern/vfs_mount.c:1.65.2.1
--- src/sys/kern/vfs_mount.c:1.65	Thu Jun  1 02:45:13 2017
+++ src/sys/kern/vfs_mount.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_mount.c,v 1.65 2017/06/01 02:45:13 chs Exp $	*/
+/*	$NetBSD: vfs_mount.c,v 1.65.2.1 2017/06/04 20:35:01 bouyer 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 2017/06/01 02:45:13 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.65.2.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -319,9 +319,9 @@ _vfs_busy(struct mount *mp, bool wait)
 	KASSERT(mp->mnt_refcnt > 0);
 
 	if (wait) {
-		fstrans_start(mp, FSTRANS_SHARED);
+		fstrans_start(mp);
 	} else {
-		if (fstrans_start_nowait(mp, FSTRANS_SHARED))
+		if (fstrans_start_nowait(mp))
 			return EBUSY;
 	}
 	if (__predict_false((mp->mnt_iflag & IMNT_GONE) != 0)) {

Index: src/sys/kern/vfs_subr.c
diff -u src/sys/kern/vfs_subr.c:1.467 src/sys/kern/vfs_subr.c:1.467.2.1
--- src/sys/kern/vfs_subr.c:1.467	Fri May 26 14:34:19 2017
+++ src/sys/kern/vfs_subr.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_subr.c,v 1.467 2017/05/26 14:34:19 riastradh Exp $	*/
+/*	$NetBSD: vfs_subr.c,v 1.467.2.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.467 2017/05/26 14:34:19 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.467.2.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -1055,12 +1055,14 @@ vstate_name(enum vnode_state state)
 {
 
 	switch (state) {
+	case VS_ACTIVE:
+		return "ACTIVE";
 	case VS_MARKER:
 		return "MARKER";
 	case VS_LOADING:
 		return "LOADING";
-	case VS_ACTIVE:
-		return "ACTIVE";
+	case VS_LOADED:
+		return "LOADED";
 	case VS_BLOCKED:
 		return "BLOCKED";
 	case VS_RECLAIMING:

Index: src/sys/kern/vfs_trans.c
diff -u src/sys/kern/vfs_trans.c:1.45 src/sys/kern/vfs_trans.c:1.45.2.1
--- src/sys/kern/vfs_trans.c:1.45	Sun May  7 08:24:20 2017
+++ src/sys/kern/vfs_trans.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_trans.c,v 1.45 2017/05/07 08:24:20 hannken Exp $	*/
+/*	$NetBSD: vfs_trans.c,v 1.45.2.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_trans.c,v 1.45 2017/05/07 08:24:20 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_trans.c,v 1.45.2.1 2017/06/04 20:35:01 bouyer Exp $");
 
 /*
  * File system transaction operations.
@@ -48,12 +48,16 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_trans.c,
 #include <sys/mount.h>
 #include <sys/pserialize.h>
 #include <sys/vnode.h>
-#define _FSTRANS_API_PRIVATE
 #include <sys/fstrans.h>
 #include <sys/proc.h>
 
 #include <miscfs/specfs/specdev.h>
 
+enum fstrans_lock_type {
+	FSTRANS_SHARED,			/* Granted while not suspending */
+	FSTRANS_EXCL			/* Internal: exclusive lock */
+};
+
 struct fscow_handler {
 	LIST_ENTRY(fscow_handler) ch_list;
 	int (*ch_func)(void *, struct buf *, bool);
@@ -89,6 +93,7 @@ static inline struct mount *fstrans_norm
 static void fstrans_lwp_dtor(void *);
 static void fstrans_mount_dtor(struct mount *);
 static struct fstrans_lwp_info *fstrans_get_lwp_info(struct mount *, bool);
+static inline int _fstrans_start(struct mount *, enum fstrans_lock_type, int);
 static bool grant_lock(const enum fstrans_state, const enum fstrans_lock_type);
 static bool state_change_done(const struct mount *);
 static bool cow_state_change_done(const struct mount *);
@@ -314,8 +319,6 @@ grant_lock(const enum fstrans_state stat
 		return true;
 	if (type == FSTRANS_EXCL)
 		return true;
-	if  (state == FSTRANS_SUSPENDING && type == FSTRANS_LAZY)
-		return true;
 
 	return false;
 }
@@ -324,7 +327,7 @@ grant_lock(const enum fstrans_state stat
  * Start a transaction.  If this thread already has a transaction on this
  * file system increment the reference counter.
  */
-int
+static inline int
 _fstrans_start(struct mount *mp, enum fstrans_lock_type lock_type, int wait)
 {
 	int s;
@@ -380,6 +383,22 @@ _fstrans_start(struct mount *mp, enum fs
 	return 0;
 }
 
+void
+fstrans_start(struct mount *mp)
+{
+	int error __diagused;
+
+	error = _fstrans_start(mp, FSTRANS_SHARED, 1);
+	KASSERT(error == 0);
+}
+
+int
+fstrans_start_nowait(struct mount *mp)
+{
+
+	return _fstrans_start(mp, FSTRANS_SHARED, 0);
+}
+
 /*
  * Finish a transaction.
  */
@@ -502,7 +521,7 @@ fstrans_setstate(struct mount *mp, enum 
 
 	if (old_state != new_state) {
 		if (old_state == FSTRANS_NORMAL)
-			fstrans_start(mp, FSTRANS_EXCL);
+			_fstrans_start(mp, FSTRANS_EXCL, 1);
 		if (new_state == FSTRANS_NORMAL)
 			fstrans_done(mp);
 	}
@@ -805,9 +824,6 @@ fstrans_print_lwp(struct proc *p, struct
 			printf(" -");
 		} else {
 			switch (fli->fli_lock_type) {
-			case FSTRANS_LAZY:
-				printf(" lazy");
-				break;
 			case FSTRANS_SHARED:
 				printf(" shared");
 				break;
@@ -842,9 +858,6 @@ fstrans_print_mount(struct mount *mp, in
 	case FSTRANS_NORMAL:
 		printf("state normal\n");
 		break;
-	case FSTRANS_SUSPENDING:
-		printf("state suspending\n");
-		break;
 	case FSTRANS_SUSPENDED:
 		printf("state suspended\n");
 		break;

Index: src/sys/kern/vfs_vnode.c
diff -u src/sys/kern/vfs_vnode.c:1.93 src/sys/kern/vfs_vnode.c:1.93.2.1
--- src/sys/kern/vfs_vnode.c:1.93	Sun May 28 16:39:41 2017
+++ src/sys/kern/vfs_vnode.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_vnode.c,v 1.93 2017/05/28 16:39:41 hannken Exp $	*/
+/*	$NetBSD: vfs_vnode.c,v 1.93.2.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
  *			will never change its state.
  *	- LOADING	Vnode is associating underlying file system and not
  *			yet ready to use.
- *	- ACTIVE	Vnode has associated underlying file system and is
+ *	- LOADED	Vnode has associated underlying file system and is
  *			ready to use.
  *	- BLOCKED	Vnode is active but cannot get new references.
  *	- RECLAIMING	Vnode is disassociating from the underlying file
@@ -109,19 +109,19 @@
  *			and is dead.
  *
  *	Valid state changes are:
- *	LOADING -> ACTIVE
+ *	LOADING -> LOADED
  *			Vnode has been initialised in vcache_get() or
  *			vcache_new() and is ready to use.
- *	ACTIVE -> RECLAIMING
+ *	LOADED -> RECLAIMING
  *			Vnode starts disassociation from underlying file
  *			system in vcache_reclaim().
  *	RECLAIMING -> RECLAIMED
  *			Vnode finished disassociation from underlying file
  *			system in vcache_reclaim().
- *	ACTIVE -> BLOCKED
+ *	LOADED -> BLOCKED
  *			Either vcache_rekey*() is changing the vnode key or
  *			vrelel() is about to call VOP_INACTIVE().
- *	BLOCKED -> ACTIVE
+ *	BLOCKED -> LOADED
  *			The block condition is over.
  *	LOADING -> RECLAIMED
  *			Either vcache_get() or vcache_new() failed to
@@ -156,7 +156,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.93 2017/05/28 16:39:41 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.93.2.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -231,26 +231,30 @@ extern struct vfsops	dead_vfsops;
 
 #if defined(DIAGNOSTIC)
 
+#define VSTATE_VALID(state) \
+	((state) != VS_ACTIVE && (state) != VS_MARKER)
 #define VSTATE_GET(vp) \
 	vstate_assert_get((vp), __func__, __LINE__)
 #define VSTATE_CHANGE(vp, from, to) \
 	vstate_assert_change((vp), (from), (to), __func__, __LINE__)
 #define VSTATE_WAIT_STABLE(vp) \
 	vstate_assert_wait_stable((vp), __func__, __LINE__)
-#define VSTATE_ASSERT(vp, state) \
-	vstate_assert((vp), (state), __func__, __LINE__)
 
-static void
-vstate_assert(vnode_t *vp, enum vnode_state state, const char *func, int line)
+void
+_vstate_assert(vnode_t *vp, enum vnode_state state, const char *func, int line)
 {
 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
 
 	KASSERTMSG(mutex_owned(vp->v_interlock), "at %s:%d", func, line);
 
-	if (__predict_true(vip->vi_state == state))
+	if (state == VS_ACTIVE && vp->v_usecount > 0 &&
+	    (vip->vi_state == VS_LOADED || vip->vi_state == VS_BLOCKED))
 		return;
-	vnpanic(vp, "state is %s, expected %s at %s:%d",
-	    vstate_name(vip->vi_state), vstate_name(state), func, line);
+	if (vip->vi_state == state)
+		return;
+	vnpanic(vp, "state is %s, usecount %d, expected %s at %s:%d",
+	    vstate_name(vip->vi_state), vp->v_usecount,
+	    vstate_name(state), func, line);
 }
 
 static enum vnode_state
@@ -259,7 +263,7 @@ vstate_assert_get(vnode_t *vp, const cha
 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
 
 	KASSERTMSG(mutex_owned(vp->v_interlock), "at %s:%d", func, line);
-	if (vip->vi_state == VS_MARKER)
+	if (! VSTATE_VALID(vip->vi_state))
 		vnpanic(vp, "state is %s at %s:%d",
 		    vstate_name(vip->vi_state), func, line);
 
@@ -272,14 +276,14 @@ vstate_assert_wait_stable(vnode_t *vp, c
 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
 
 	KASSERTMSG(mutex_owned(vp->v_interlock), "at %s:%d", func, line);
-	if (vip->vi_state == VS_MARKER)
+	if (! VSTATE_VALID(vip->vi_state))
 		vnpanic(vp, "state is %s at %s:%d",
 		    vstate_name(vip->vi_state), func, line);
 
-	while (vip->vi_state != VS_ACTIVE && vip->vi_state != VS_RECLAIMED)
+	while (vip->vi_state != VS_LOADED && vip->vi_state != VS_RECLAIMED)
 		cv_wait(&vp->v_cv, vp->v_interlock);
 
-	if (vip->vi_state == VS_MARKER)
+	if (! VSTATE_VALID(vip->vi_state))
 		vnpanic(vp, "state is %s at %s:%d",
 		    vstate_name(vip->vi_state), func, line);
 }
@@ -294,10 +298,10 @@ vstate_assert_change(vnode_t *vp, enum v
 	if (from == VS_LOADING)
 		KASSERTMSG(mutex_owned(&vcache_lock), "at %s:%d", func, line);
 
-	if (from == VS_MARKER)
+	if (! VSTATE_VALID(from))
 		vnpanic(vp, "from is %s at %s:%d",
 		    vstate_name(from), func, line);
-	if (to == VS_MARKER)
+	if (! VSTATE_VALID(to))
 		vnpanic(vp, "to is %s at %s:%d",
 		    vstate_name(to), func, line);
 	if (vip->vi_state != from)
@@ -311,7 +315,7 @@ vstate_assert_change(vnode_t *vp, enum v
 	vip->vi_state = to;
 	if (from == VS_LOADING)
 		cv_broadcast(&vcache_cv);
-	if (to == VS_ACTIVE || to == VS_RECLAIMED)
+	if (to == VS_LOADED || to == VS_RECLAIMED)
 		cv_broadcast(&vp->v_cv);
 }
 
@@ -323,14 +327,18 @@ vstate_assert_change(vnode_t *vp, enum v
 	vstate_change((vp), (from), (to))
 #define VSTATE_WAIT_STABLE(vp) \
 	vstate_wait_stable((vp))
-#define VSTATE_ASSERT(vp, state)
+void
+_vstate_assert(vnode_t *vp, enum vnode_state state, const char *func, int line)
+{
+
+}
 
 static void
 vstate_wait_stable(vnode_t *vp)
 {
 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
 
-	while (vip->vi_state != VS_ACTIVE && vip->vi_state != VS_RECLAIMED)
+	while (vip->vi_state != VS_LOADED && vip->vi_state != VS_RECLAIMED)
 		cv_wait(&vp->v_cv, vp->v_interlock);
 }
 
@@ -342,7 +350,7 @@ vstate_change(vnode_t *vp, enum vnode_st
 	vip->vi_state = to;
 	if (from == VS_LOADING)
 		cv_broadcast(&vcache_cv);
-	if (to == VS_ACTIVE || to == VS_RECLAIMED)
+	if (to == VS_LOADED || to == VS_RECLAIMED)
 		cv_broadcast(&vp->v_cv);
 }
 
@@ -416,21 +424,6 @@ 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 *
@@ -528,12 +521,12 @@ vdrain_remove(vnode_t *vp)
 	if (!mutex_tryenter(vp->v_interlock))
 		return;
 	/* Probe usecount and state. */
-	if (vp->v_usecount > 0 || VSTATE_GET(vp) != VS_ACTIVE) {
+	if (vp->v_usecount > 0 || VSTATE_GET(vp) != VS_LOADED) {
 		mutex_exit(vp->v_interlock);
 		return;
 	}
 	mp = vp->v_mount;
-	if (fstrans_start_nowait(mp, FSTRANS_SHARED) != 0) {
+	if (fstrans_start_nowait(mp) != 0) {
 		mutex_exit(vp->v_interlock);
 		return;
 	}
@@ -563,7 +556,7 @@ vdrain_vrele(vnode_t *vp)
 	KASSERT(mutex_owned(&vdrain_lock));
 
 	mp = vp->v_mount;
-	if (fstrans_start_nowait(mp, FSTRANS_SHARED) != 0)
+	if (fstrans_start_nowait(mp) != 0)
 		return;
 
 	/*
@@ -752,7 +745,7 @@ vrelel(vnode_t *vp, int flags)
 	if (VSTATE_GET(vp) == VS_RECLAIMED) {
 		VOP_UNLOCK(vp);
 	} else {
-		VSTATE_CHANGE(vp, VS_ACTIVE, VS_BLOCKED);
+		VSTATE_CHANGE(vp, VS_LOADED, VS_BLOCKED);
 		mutex_exit(vp->v_interlock);
 
 		/*
@@ -768,7 +761,7 @@ vrelel(vnode_t *vp, int flags)
 		if (!recycle)
 			VOP_UNLOCK(vp);
 		mutex_enter(vp->v_interlock);
-		VSTATE_CHANGE(vp, VS_BLOCKED, VS_ACTIVE);
+		VSTATE_CHANGE(vp, VS_BLOCKED, VS_LOADED);
 		if (!recycle) {
 			if (vtryrele(vp)) {
 				mutex_exit(vp->v_interlock);
@@ -791,7 +784,7 @@ vrelel(vnode_t *vp, int flags)
 		 * otherwise just free it.
 		 */
 		if (recycle) {
-			VSTATE_ASSERT(vp, VS_ACTIVE);
+			VSTATE_ASSERT(vp, VS_LOADED);
 			/* vcache_reclaim drops the lock. */
 			vcache_reclaim(vp);
 		}
@@ -910,14 +903,14 @@ vrecycle(vnode_t *vp)
 	}
 
 	/* If the vnode is already clean we're done. */
-	if (VSTATE_GET(vp) != VS_ACTIVE) {
+	if (VSTATE_GET(vp) != VS_LOADED) {
 		VSTATE_ASSERT(vp, VS_RECLAIMED);
 		vrelel(vp, 0);
 		return true;
 	}
 
 	/* Prevent further references until the vnode is locked. */
-	VSTATE_CHANGE(vp, VS_ACTIVE, VS_BLOCKED);
+	VSTATE_CHANGE(vp, VS_LOADED, VS_BLOCKED);
 	mutex_exit(vp->v_interlock);
 
 	/*
@@ -929,7 +922,7 @@ vrecycle(vnode_t *vp)
 	error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOWAIT);
 
 	mutex_enter(vp->v_interlock);
-	VSTATE_CHANGE(vp, VS_BLOCKED, VS_ACTIVE);
+	VSTATE_CHANGE(vp, VS_BLOCKED, VS_LOADED);
 
 	if (error) {
 		mutex_exit(vp->v_interlock);
@@ -1024,7 +1017,7 @@ vgone(vnode_t *vp)
 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	mutex_enter(vp->v_interlock);
 	VSTATE_WAIT_STABLE(vp);
-	if (VSTATE_GET(vp) == VS_ACTIVE)
+	if (VSTATE_GET(vp) == VS_LOADED)
 		vcache_reclaim(vp);
 	VSTATE_ASSERT(vp, VS_RECLAIMED);
 	vrelel(vp, 0);
@@ -1115,7 +1108,7 @@ vcache_alloc(void)
 	vip = pool_cache_get(vcache_pool, PR_WAITOK);
 	memset(vip, 0, sizeof(*vip));
 
-	vip->vi_lock = rw_obj_alloc();
+	rw_init(&vip->vi_lock);
 	/* SLIST_INIT(&vip->vi_hash); */
 	/* LIST_INIT(&vip->vi_nclist); */
 	/* LIST_INIT(&vip->vi_dnclist); */
@@ -1177,7 +1170,7 @@ vcache_free(vnode_impl_t *vip)
 	if (vp->v_type == VBLK || vp->v_type == VCHR)
 		spec_node_destroy(vp);
 
-	rw_obj_free(vip->vi_lock);
+	rw_destroy(&vip->vi_lock);
 	uvm_obj_destroy(&vp->v_uobj, true);
 	cv_destroy(&vp->v_cv);
 	pool_cache_put(vcache_pool, vip);
@@ -1199,7 +1192,7 @@ vcache_tryvget(vnode_t *vp)
 
 	if (__predict_false(VSTATE_GET(vp) == VS_RECLAIMED))
 		error = ENOENT;
-	else if (__predict_false(VSTATE_GET(vp) != VS_ACTIVE))
+	else if (__predict_false(VSTATE_GET(vp) != VS_LOADED))
 		error = EBUSY;
 	else if (vp->v_usecount == 0)
 		vp->v_usecount = 1;
@@ -1237,7 +1230,7 @@ vcache_vget(vnode_t *vp)
 			mutex_exit(vp->v_interlock);
 		return ENOENT;
 	}
-	VSTATE_ASSERT(vp, VS_ACTIVE);
+	VSTATE_ASSERT(vp, VS_LOADED);
 	if (vp->v_usecount == 0)
 		vp->v_usecount = 1;
 	else
@@ -1349,7 +1342,7 @@ again:
 	mutex_enter(&vcache_lock);
 	new_vip->vi_key.vk_key = new_key;
 	mutex_enter(vp->v_interlock);
-	VSTATE_CHANGE(vp, VS_LOADING, VS_ACTIVE);
+	VSTATE_CHANGE(vp, VS_LOADING, VS_LOADED);
 	mutex_exit(vp->v_interlock);
 	mutex_exit(&vcache_lock);
 	*vpp = vp;
@@ -1414,7 +1407,7 @@ vcache_new(struct mount *mp, struct vnod
 	/* Finished loading, finalize node. */
 	mutex_enter(&vcache_lock);
 	mutex_enter(vp->v_interlock);
-	VSTATE_CHANGE(vp, VS_LOADING, VS_ACTIVE);
+	VSTATE_CHANGE(vp, VS_LOADING, VS_LOADED);
 	mutex_exit(&vcache_lock);
 	mutex_exit(vp->v_interlock);
 	*vpp = vp;
@@ -1549,7 +1542,7 @@ vcache_reclaim(vnode_t *vp)
 	 * Prevent the vnode from being recycled or brought into use
 	 * while we clean it out.
 	 */
-	VSTATE_CHANGE(vp, VS_ACTIVE, VS_RECLAIMING);
+	VSTATE_CHANGE(vp, VS_LOADED, VS_RECLAIMING);
 	if (vp->v_iflag & VI_EXECMAP) {
 		atomic_add_int(&uvmexp.execpages, -vp->v_uobj.uo_npages);
 		atomic_add_int(&uvmexp.filepages, vp->v_uobj.uo_npages);
@@ -1568,7 +1561,7 @@ vcache_reclaim(vnode_t *vp)
 	vip->vi_key.vk_key = temp_key;
 	mutex_exit(&vcache_lock);
 
-	fstrans_start(mp, FSTRANS_SHARED);
+	fstrans_start(mp);
 
 	/*
 	 * Clean out any cached data associated with the vnode.

Index: src/sys/kern/vnode_if.c
diff -u src/sys/kern/vnode_if.c:1.104 src/sys/kern/vnode_if.c:1.104.2.1
--- src/sys/kern/vnode_if.c:1.104	Fri May 26 14:21:54 2017
+++ src/sys/kern/vnode_if.c	Sun Jun  4 20:35:01 2017
@@ -1,13 +1,13 @@
-/*	$NetBSD: vnode_if.c,v 1.104 2017/05/26 14:21:54 riastradh Exp $	*/
+/*	$NetBSD: vnode_if.c,v 1.104.2.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*
  * Warning: DO NOT EDIT! This file is automatically generated!
  * (Modifications made here may easily be lost!)
  *
  * Created from the file:
- *	NetBSD: vnode_if.src,v 1.75 2017/05/26 14:21:00 riastradh Exp
+ *	NetBSD: vnode_if.src,v 1.76 2017/06/04 07:59:17 hannken Exp
  * by the script:
- *	NetBSD: vnode_if.sh,v 1.64 2017/04/16 17:18:28 riastradh Exp
+ *	NetBSD: vnode_if.sh,v 1.66 2017/06/04 08:03:26 hannken Exp
  */
 
 /*
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v 1.104 2017/05/26 14:21:54 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v 1.104.2.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/mount.h>
@@ -49,6 +49,57 @@ __KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v
 #include <sys/lock.h>
 #include <sys/fstrans.h>
 
+enum fst_op { FST_NO, FST_YES, FST_TRY };
+
+static inline int
+vop_pre(vnode_t *vp, struct mount **mp, bool *mpsafe, enum fst_op op)
+{
+	int error;
+
+	*mpsafe = (vp->v_vflag & VV_MPSAFE);
+
+	if (!*mpsafe) {
+		KERNEL_LOCK(1, curlwp);
+	}
+
+	if (op == FST_YES || op == FST_TRY) {
+		for (;;) {
+			*mp = vp->v_mount;
+			if (op == FST_TRY) {
+				error = fstrans_start_nowait(*mp);
+				if (error) {
+					if (!*mpsafe) {
+						KERNEL_UNLOCK_ONE(curlwp);
+					}
+					return error;
+				}
+			} else {
+				fstrans_start(*mp);
+			}
+			if (__predict_true(*mp == vp->v_mount))
+				break;
+			fstrans_done(*mp);
+		}
+	} else {
+		*mp = vp->v_mount;
+	}
+
+	return 0;
+}
+
+static inline void
+vop_post(vnode_t *vp, struct mount *mp, bool mpsafe, enum fst_op op)
+{
+
+	if (op == FST_YES) {
+		fstrans_done(mp);
+	}
+
+	if (!mpsafe) {
+		KERNEL_UNLOCK_ONE(curlwp);
+	}
+}
+
 const struct vnodeop_desc vop_default_desc = {
 	0,
 	"default",
@@ -80,16 +131,15 @@ VOP_BWRITE(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_bwrite_args a;
-	struct mount *mp = vp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_bwrite);
 	a.a_vp = vp;
 	a.a_bp = bp;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_bwrite), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -114,14 +164,16 @@ VOP_LOOKUP(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_lookup_v2_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_lookup);
 	a.a_dvp = dvp;
 	a.a_vpp = vpp;
 	a.a_cnp = cnp;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_lookup), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_NO);
 #ifdef DIAGNOSTIC
 	if (error == 0)
 		KASSERT((*vpp)->v_size != VSIZENOTSET
@@ -152,15 +204,17 @@ VOP_CREATE(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_create_v3_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_create);
 	a.a_dvp = dvp;
 	a.a_vpp = vpp;
 	a.a_cnp = cnp;
 	a.a_vap = vap;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_create), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_NO);
 #ifdef DIAGNOSTIC
 	if (error == 0)
 		KASSERT((*vpp)->v_size != VSIZENOTSET
@@ -191,15 +245,17 @@ VOP_MKNOD(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_mknod_v3_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_mknod);
 	a.a_dvp = dvp;
 	a.a_vpp = vpp;
 	a.a_cnp = cnp;
 	a.a_vap = vap;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_mknod), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_NO);
 #ifdef DIAGNOSTIC
 	if (error == 0)
 		KASSERT((*vpp)->v_size != VSIZENOTSET
@@ -229,14 +285,16 @@ VOP_OPEN(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_open_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_open);
 	a.a_vp = vp;
 	a.a_mode = mode;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_open), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -261,14 +319,16 @@ VOP_CLOSE(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_close_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_close);
 	a.a_vp = vp;
 	a.a_fflag = fflag;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_close), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -293,14 +353,16 @@ VOP_ACCESS(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_access_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_access);
 	a.a_vp = vp;
 	a.a_mode = mode;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_access), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -325,14 +387,16 @@ VOP_GETATTR(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_getattr_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_getattr);
 	a.a_vp = vp;
 	a.a_vap = vap;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_getattr), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -357,14 +421,16 @@ VOP_SETATTR(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_setattr_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_setattr);
 	a.a_vp = vp;
 	a.a_vap = vap;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_setattr), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -390,15 +456,17 @@ VOP_READ(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_read_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_read);
 	a.a_vp = vp;
 	a.a_uio = uio;
 	a.a_ioflag = ioflag;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_read), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -424,15 +492,17 @@ VOP_WRITE(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_write_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_write);
 	a.a_vp = vp;
 	a.a_uio = uio;
 	a.a_ioflag = ioflag;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_write), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -457,14 +527,16 @@ VOP_FALLOCATE(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_fallocate_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_fallocate);
 	a.a_vp = vp;
 	a.a_pos = pos;
 	a.a_len = len;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_fallocate), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -489,14 +561,16 @@ VOP_FDISCARD(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_fdiscard_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_fdiscard);
 	a.a_vp = vp;
 	a.a_pos = pos;
 	a.a_len = len;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_fdiscard), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -523,16 +597,18 @@ VOP_IOCTL(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_ioctl_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_ioctl);
 	a.a_vp = vp;
 	a.a_command = command;
 	a.a_data = data;
 	a.a_fflag = fflag;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_ioctl), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -559,16 +635,18 @@ VOP_FCNTL(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_fcntl_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_fcntl);
 	a.a_vp = vp;
 	a.a_command = command;
 	a.a_data = data;
 	a.a_fflag = fflag;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_fcntl), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -592,16 +670,15 @@ VOP_POLL(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_poll_args a;
-	struct mount *mp = vp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_poll);
 	a.a_vp = vp;
 	a.a_events = events;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_poll), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -625,16 +702,15 @@ VOP_KQFILTER(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_kqfilter_args a;
-	struct mount *mp = vp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_kqfilter);
 	a.a_vp = vp;
 	a.a_kn = kn;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_kqfilter), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -658,13 +734,15 @@ VOP_REVOKE(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_revoke_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_revoke);
 	a.a_vp = vp;
 	a.a_flags = flags;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_revoke), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -689,17 +767,16 @@ VOP_MMAP(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_mmap_args a;
-	struct mount *mp = vp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_mmap);
 	a.a_vp = vp;
 	a.a_prot = prot;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_mmap), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -726,16 +803,18 @@ VOP_FSYNC(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_fsync_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_fsync);
 	a.a_vp = vp;
 	a.a_cred = cred;
 	a.a_flags = flags;
 	a.a_offlo = offlo;
 	a.a_offhi = offhi;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_fsync), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -761,18 +840,17 @@ VOP_SEEK(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_seek_args a;
-	struct mount *mp = vp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_seek);
 	a.a_vp = vp;
 	a.a_oldoff = oldoff;
 	a.a_newoff = newoff;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_seek), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -798,14 +876,16 @@ VOP_REMOVE(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_remove_v2_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_remove);
 	a.a_dvp = dvp;
 	a.a_vp = vp;
 	a.a_cnp = cnp;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_remove), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -831,14 +911,16 @@ VOP_LINK(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_link_v2_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_link);
 	a.a_dvp = dvp;
 	a.a_vp = vp;
 	a.a_cnp = cnp;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_link), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -869,7 +951,7 @@ VOP_RENAME(struct vnode *fdvp,
 	int error;
 	bool mpsafe;
 	struct vop_rename_args a;
-	struct mount *mp = fdvp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_rename);
 	a.a_fdvp = fdvp;
 	a.a_fvp = fvp;
@@ -877,12 +959,11 @@ VOP_RENAME(struct vnode *fdvp,
 	a.a_tdvp = tdvp;
 	a.a_tvp = tvp;
 	a.a_tcnp = tcnp;
-	mpsafe = (fdvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(fdvp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(fdvp, VOFFSET(vop_rename), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(fdvp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -908,15 +989,17 @@ VOP_MKDIR(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_mkdir_v3_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_mkdir);
 	a.a_dvp = dvp;
 	a.a_vpp = vpp;
 	a.a_cnp = cnp;
 	a.a_vap = vap;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_mkdir), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_NO);
 #ifdef DIAGNOSTIC
 	if (error == 0)
 		KASSERT((*vpp)->v_size != VSIZENOTSET
@@ -947,14 +1030,16 @@ VOP_RMDIR(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_rmdir_v2_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_rmdir);
 	a.a_dvp = dvp;
 	a.a_vp = vp;
 	a.a_cnp = cnp;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_rmdir), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -981,16 +1066,18 @@ VOP_SYMLINK(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_symlink_v3_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_symlink);
 	a.a_dvp = dvp;
 	a.a_vpp = vpp;
 	a.a_cnp = cnp;
 	a.a_vap = vap;
 	a.a_target = target;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_symlink), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_NO);
 #ifdef DIAGNOSTIC
 	if (error == 0)
 		KASSERT((*vpp)->v_size != VSIZENOTSET
@@ -1023,6 +1110,7 @@ VOP_READDIR(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_readdir_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_readdir);
 	a.a_vp = vp;
 	a.a_uio = uio;
@@ -1030,10 +1118,11 @@ VOP_READDIR(struct vnode *vp,
 	a.a_eofflag = eofflag;
 	a.a_cookies = cookies;
 	a.a_ncookies = ncookies;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_readdir), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1058,14 +1147,16 @@ VOP_READLINK(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_readlink_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_readlink);
 	a.a_vp = vp;
 	a.a_uio = uio;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_readlink), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1089,16 +1180,15 @@ VOP_ABORTOP(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_abortop_args a;
-	struct mount *mp = dvp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_abortop);
 	a.a_dvp = dvp;
 	a.a_cnp = cnp;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(dvp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_abortop), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -1122,13 +1212,15 @@ VOP_INACTIVE(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_inactive_v2_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_inactive);
 	a.a_vp = vp;
 	a.a_recycle = recycle;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_inactive), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1151,12 +1243,14 @@ VOP_RECLAIM(struct vnode *vp)
 	int error;
 	bool mpsafe;
 	struct vop_reclaim_v2_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_reclaim);
 	a.a_vp = vp;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_reclaim), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1180,13 +1274,15 @@ VOP_LOCK(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_lock_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_lock);
 	a.a_vp = vp;
 	a.a_flags = flags;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, (flags & LK_NOWAIT ? FST_TRY : FST_YES));
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_lock), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, (error ? FST_YES : FST_NO));
 	return error;
 }
 
@@ -1209,12 +1305,14 @@ VOP_UNLOCK(struct vnode *vp)
 	int error;
 	bool mpsafe;
 	struct vop_unlock_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_unlock);
 	a.a_vp = vp;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_unlock), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -1241,19 +1339,18 @@ VOP_BMAP(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_bmap_args a;
-	struct mount *mp = vp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_bmap);
 	a.a_vp = vp;
 	a.a_bn = bn;
 	a.a_vpp = vpp;
 	a.a_bnp = bnp;
 	a.a_runp = runp;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_bmap), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -1277,16 +1374,15 @@ VOP_STRATEGY(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_strategy_args a;
-	struct mount *mp = vp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_strategy);
 	a.a_vp = vp;
 	a.a_bp = bp;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_strategy), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -1309,15 +1405,14 @@ VOP_PRINT(struct vnode *vp)
 	int error;
 	bool mpsafe;
 	struct vop_print_args a;
-	struct mount *mp = vp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_print);
 	a.a_vp = vp;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_print), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -1340,12 +1435,14 @@ VOP_ISLOCKED(struct vnode *vp)
 	int error;
 	bool mpsafe;
 	struct vop_islocked_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_islocked);
 	a.a_vp = vp;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_islocked), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1370,14 +1467,16 @@ VOP_PATHCONF(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_pathconf_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_pathconf);
 	a.a_vp = vp;
 	a.a_name = name;
 	a.a_retval = retval;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_pathconf), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1404,19 +1503,18 @@ VOP_ADVLOCK(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_advlock_args a;
-	struct mount *mp = vp->v_mount;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_advlock);
 	a.a_vp = vp;
 	a.a_id = id;
 	a.a_op = op;
 	a.a_fl = fl;
 	a.a_flags = flags;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
-	fstrans_start(mp, FSTRANS_SHARED);
+	error = vop_pre(vp, &mp, &mpsafe, FST_YES);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_advlock), &a));
-	fstrans_done(mp);
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_YES);
 	return error;
 }
 
@@ -1441,14 +1539,16 @@ VOP_WHITEOUT(struct vnode *dvp,
 	int error;
 	bool mpsafe;
 	struct vop_whiteout_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_whiteout);
 	a.a_dvp = dvp;
 	a.a_cnp = cnp;
 	a.a_flags = flags;
-	mpsafe = (dvp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(dvp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(dvp, VOFFSET(vop_whiteout), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(dvp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1478,6 +1578,7 @@ VOP_GETPAGES(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_getpages_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_getpages);
 	a.a_vp = vp;
 	a.a_offset = offset;
@@ -1487,10 +1588,11 @@ VOP_GETPAGES(struct vnode *vp,
 	a.a_access_type = access_type;
 	a.a_advice = advice;
 	a.a_flags = flags;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_getpages), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1516,15 +1618,17 @@ VOP_PUTPAGES(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_putpages_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_putpages);
 	a.a_vp = vp;
 	a.a_offlo = offlo;
 	a.a_offhi = offhi;
 	a.a_flags = flags;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_putpages), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1549,14 +1653,16 @@ VOP_CLOSEEXTATTR(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_closeextattr_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_closeextattr);
 	a.a_vp = vp;
 	a.a_commit = commit;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_closeextattr), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1584,6 +1690,7 @@ VOP_GETEXTATTR(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_getextattr_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_getextattr);
 	a.a_vp = vp;
 	a.a_attrnamespace = attrnamespace;
@@ -1591,10 +1698,11 @@ VOP_GETEXTATTR(struct vnode *vp,
 	a.a_uio = uio;
 	a.a_size = size;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_getextattr), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1622,6 +1730,7 @@ VOP_LISTEXTATTR(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_listextattr_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_listextattr);
 	a.a_vp = vp;
 	a.a_attrnamespace = attrnamespace;
@@ -1629,10 +1738,11 @@ VOP_LISTEXTATTR(struct vnode *vp,
 	a.a_size = size;
 	a.a_flag = flag;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_listextattr), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1656,13 +1766,15 @@ VOP_OPENEXTATTR(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_openextattr_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_openextattr);
 	a.a_vp = vp;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_openextattr), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1688,15 +1800,17 @@ VOP_DELETEEXTATTR(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_deleteextattr_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_deleteextattr);
 	a.a_vp = vp;
 	a.a_attrnamespace = attrnamespace;
 	a.a_name = name;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_deleteextattr), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 
@@ -1723,16 +1837,18 @@ VOP_SETEXTATTR(struct vnode *vp,
 	int error;
 	bool mpsafe;
 	struct vop_setextattr_args a;
+	struct mount *mp;
 	a.a_desc = VDESC(vop_setextattr);
 	a.a_vp = vp;
 	a.a_attrnamespace = attrnamespace;
 	a.a_name = name;
 	a.a_uio = uio;
 	a.a_cred = cred;
-	mpsafe = (vp->v_vflag & VV_MPSAFE);
-	if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
+	error = vop_pre(vp, &mp, &mpsafe, FST_NO);
+	if (error)
+		return error;
 	error = (VCALL(vp, VOFFSET(vop_setextattr), &a));
-	if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
+	vop_post(vp, mp, mpsafe, FST_NO);
 	return error;
 }
 

Index: src/sys/kern/vnode_if.sh
diff -u src/sys/kern/vnode_if.sh:1.64 src/sys/kern/vnode_if.sh:1.64.4.1
--- src/sys/kern/vnode_if.sh:1.64	Sun Apr 16 17:18:28 2017
+++ src/sys/kern/vnode_if.sh	Sun Jun  4 20:35:01 2017
@@ -29,7 +29,7 @@ copyright="\
  * SUCH DAMAGE.
  */
 "
-SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.64 2017/04/16 17:18:28 riastradh Exp $'
+SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.64.4.1 2017/06/04 20:35:01 bouyer Exp $'
 
 # Script to produce VFS front-end sugar.
 #
@@ -100,7 +100,7 @@ awk_parser='
 	args_name=$1;
 	argc=0;
 	willmake=-1;
-	fstrans=0;
+	fstrans="";
 	next;
 }
 # Last line of description
@@ -113,11 +113,9 @@ awk_parser='
 	if ($1 == "VERSION") {
 		args_name=args_name "_v" $2;
 		next;
-	} else if ($1 == "FSTRANS=YES") {
-		fstrans = 1;
-		next;
-	} else if ($1 == "FSTRANS=NO") {
-		fstrans = -1;
+	} else if ($1 ~ "^FSTRANS=") {
+		fstrans = $1;
+		sub("FSTRANS=", "", fstrans);
 		next;
 	}
 
@@ -147,8 +145,12 @@ awk_parser='
 		willmake=argc;
 		i++;
 	}
-	if (argc == 0 && fstrans == 0 && lockstate[0] != 1)
-		fstrans = 1;
+	if (argc == 0 && fstrans == "") {
+		if (lockstate[0] == 1)
+			fstrans = "NO";
+		else
+			fstrans = "YES";
+	}
 
 	# XXX: replace non-portable types for rump.  We should really
 	# nuke the types from the kernel, but that is a battle for
@@ -316,6 +318,57 @@ echo '
 
 if [ -z "${rump}" ] ; then
 	echo "
+enum fst_op { FST_NO, FST_YES, FST_TRY };
+
+static inline int
+vop_pre(vnode_t *vp, struct mount **mp, bool *mpsafe, enum fst_op op)
+{
+	int error;
+
+	*mpsafe = (vp->v_vflag & VV_MPSAFE);
+
+	if (!*mpsafe) {
+		KERNEL_LOCK(1, curlwp);
+	}
+
+	if (op == FST_YES || op == FST_TRY) {
+		for (;;) {
+			*mp = vp->v_mount;
+			if (op == FST_TRY) {
+				error = fstrans_start_nowait(*mp);
+				if (error) {
+					if (!*mpsafe) {
+						KERNEL_UNLOCK_ONE(curlwp);
+					}
+					return error;
+				}
+			} else {
+				fstrans_start(*mp);
+			}
+			if (__predict_true(*mp == vp->v_mount))
+				break;
+			fstrans_done(*mp);
+		}
+	} else {
+		*mp = vp->v_mount;
+	}
+
+	return 0;
+}
+
+static inline void
+vop_post(vnode_t *vp, struct mount *mp, bool mpsafe, enum fst_op op)
+{
+
+	if (op == FST_YES) {
+		fstrans_done(mp);
+	}
+
+	if (!mpsafe) {
+		KERNEL_UNLOCK_ONE(curlwp);
+	}
+}
+
 const struct vnodeop_desc vop_default_desc = {"
 echo '	0,
 	"default",
@@ -402,8 +455,7 @@ function bodyrump() {
 function bodynorm() {
 	printf("{\n\tint error;\n\tbool mpsafe;\n\tstruct %s_args a;\n",
 		args_name);
-	if (fstrans == 1)
-		printf("\tstruct mount *mp = %s->v_mount;\n", argname[0]);
+	printf("\tstruct mount *mp;\n");
 	if (lockdebug) {
 		printf("#ifdef VNODE_LOCKDEBUG\n");
 		for (i=0; i<argc; i++) {
@@ -425,15 +477,27 @@ function bodynorm() {
 			printf("#endif\n");
 		}
 	}
-	printf("\tmpsafe = (%s->v_vflag & VV_MPSAFE);\n", argname[0]);
-	printf("\tif (!mpsafe) { KERNEL_LOCK(1, curlwp); }\n");
-	if (fstrans == 1)
-		printf("\tfstrans_start(mp, FSTRANS_SHARED);\n");
+	if (fstrans == "LOCK")
+		printf("\terror = vop_pre(%s, &mp, &mpsafe, %s);\n",
+			argname[0], "(flags & LK_NOWAIT ? FST_TRY : FST_YES)");
+	else if (fstrans == "UNLOCK")
+		printf("\terror = vop_pre(%s, &mp, &mpsafe, FST_%s);\n",
+			argname[0], "NO");
+	else
+		printf("\terror = vop_pre(%s, &mp, &mpsafe, FST_%s);\n",
+			argname[0], fstrans);
+	printf("\tif (error)\n\t\treturn error;\n");
 	printf("\terror = (VCALL(%s, VOFFSET(%s), &a));\n",
 		argname[0], name);
-	if (fstrans == 1)
-		printf("\tfstrans_done(mp);\n");
-	printf("\tif (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }\n");
+	if (fstrans == "LOCK")
+		printf("\tvop_post(%s, mp, mpsafe, %s);\n",
+			argname[0], "(error ? FST_YES : FST_NO)");
+	else if (fstrans == "UNLOCK")
+		printf("\tvop_post(%s, mp, mpsafe, FST_%s);\n",
+			argname[0], "YES");
+	else
+		printf("\tvop_post(%s, mp, mpsafe, FST_%s);\n",
+			argname[0], fstrans);
 	if (willmake != -1) {
 		printf("#ifdef DIAGNOSTIC\n");
 		printf("\tif (error == 0)\n"				\

Index: src/sys/kern/vnode_if.src
diff -u src/sys/kern/vnode_if.src:1.75 src/sys/kern/vnode_if.src:1.75.2.1
--- src/sys/kern/vnode_if.src:1.75	Fri May 26 14:21:00 2017
+++ src/sys/kern/vnode_if.src	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: vnode_if.src,v 1.75 2017/05/26 14:21:00 riastradh Exp $
+#	$NetBSD: vnode_if.src,v 1.75.2.1 2017/06/04 20:35:01 bouyer Exp $
 #
 # Copyright (c) 1992, 1993
 #	The Regents of the University of California.  All rights reserved.
@@ -407,7 +407,7 @@ vop_reclaim {
 #% lock               vp      U L U
 #
 vop_lock {
-	FSTRANS=NO
+	FSTRANS=LOCK
 	IN LOCKED=NO struct vnode *vp;
 	IN int flags;
 };
@@ -416,7 +416,7 @@ vop_lock {
 #% unlock     vp      L U L
 #
 vop_unlock {
-	FSTRANS=NO
+	FSTRANS=UNLOCK
 	IN LOCKED=YES struct vnode *vp;
 };
 

Index: src/sys/miscfs/genfs/genfs_io.c
diff -u src/sys/miscfs/genfs/genfs_io.c:1.68 src/sys/miscfs/genfs/genfs_io.c:1.68.6.1
--- src/sys/miscfs/genfs/genfs_io.c:1.68	Sat Apr  1 23:34:17 2017
+++ src/sys/miscfs/genfs/genfs_io.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: genfs_io.c,v 1.68 2017/04/01 23:34:17 dholland Exp $	*/
+/*	$NetBSD: genfs_io.c,v 1.68.6.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.68 2017/04/01 23:34:17 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.68.6.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -293,7 +293,7 @@ startover:
 
 	if (trans_mount == NULL) {
 		trans_mount = vp->v_mount;
-		fstrans_start(trans_mount, FSTRANS_SHARED);
+		fstrans_start(trans_mount);
 		/*
 		 * check if this vnode is still valid.
 		 */
@@ -891,7 +891,7 @@ retry:
 		if (pagedaemon) {
 			/* Pagedaemon must not sleep here. */
 			trans_mp = vp->v_mount;
-			error = fstrans_start_nowait(trans_mp, FSTRANS_SHARED);
+			error = fstrans_start_nowait(trans_mp);
 			if (error) {
 				mutex_exit(slock);
 				return error;
@@ -904,7 +904,7 @@ retry:
 			 */
 			mutex_exit(slock);
 			trans_mp = vp->v_mount;
-			fstrans_start(trans_mp, FSTRANS_SHARED);
+			fstrans_start(trans_mp);
 			if (vp->v_mount != trans_mp) {
 				fstrans_done(trans_mp);
 				trans_mp = NULL;

Index: src/sys/miscfs/genfs/genfs_vnops.c
diff -u src/sys/miscfs/genfs/genfs_vnops.c:1.195 src/sys/miscfs/genfs/genfs_vnops.c:1.195.4.1
--- src/sys/miscfs/genfs/genfs_vnops.c:1.195	Tue Apr 11 14:29:32 2017
+++ src/sys/miscfs/genfs/genfs_vnops.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: genfs_vnops.c,v 1.195 2017/04/11 14:29:32 riastradh Exp $	*/
+/*	$NetBSD: genfs_vnops.c,v 1.195.4.1 2017/06/04 20:35:01 bouyer 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.195 2017/04/11 14:29:32 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.195.4.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -288,41 +288,18 @@ genfs_deadlock(void *v)
 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
 	int flags = ap->a_flags;
 	krw_t op;
-	int error;
+
+	if (! ISSET(flags, LK_RETRY))
+		return ENOENT;
 
 	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);
-			if (error == ENOENT && ISSET(flags, LK_RETRY))
-				error = 0;
-			mutex_exit(vp->v_interlock);
-		} else
-			error = EBUSY;
-		if (error)
-			rw_exit(vip->vi_lock);
-		return error;
-	}
-
-	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);
-		error = vdead_check(vp, 0);
-		KASSERT(error == ENOENT);
-		mutex_exit(vp->v_interlock);
-		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);
-		return ENOENT;
+	} else {
+		rw_enter(&vip->vi_lock, op);
 	}
+	VSTATE_ASSERT_UNLOCKED(vp, VS_RECLAIMED);
 	return 0;
 }
 
@@ -338,7 +315,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;
 }
@@ -355,43 +332,18 @@ genfs_lock(void *v)
 	} */ *ap = v;
 	vnode_t *vp = ap->a_vp;
 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
-	struct mount *mp = vp->v_mount;
 	int flags = ap->a_flags;
 	krw_t op;
-	int error;
 
 	op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
 	if (ISSET(flags, LK_NOWAIT)) {
-		if (fstrans_start_nowait(mp, FSTRANS_SHARED))
-			return EBUSY;
-		if (! rw_tryenter(vip->vi_lock, op)) {
-			fstrans_done(mp);
+		if (! rw_tryenter(&vip->vi_lock, op))
 			return EBUSY;
-		}
-		if (mutex_tryenter(vp->v_interlock)) {
-			error = vdead_check(vp, VDEAD_NOWAIT);
-			mutex_exit(vp->v_interlock);
-		} else
-			error = EBUSY;
-		if (error) {
-			rw_exit(vip->vi_lock);
-			fstrans_done(mp);
-		}
-		return error;
+	} else {
+		rw_enter(&vip->vi_lock, op);
 	}
-
-	fstrans_start(mp, FSTRANS_SHARED);
-	rw_enter(vip->vi_lock, op);
-	mutex_enter(vp->v_interlock);
-	error = vdead_check(vp, VDEAD_NOWAIT);
-	if (error) {
-		rw_exit(vip->vi_lock);
-		fstrans_done(mp);
-		error = vdead_check(vp, 0);
-		KASSERT(error == ENOENT);
-	}
-	mutex_exit(vp->v_interlock);
-	return error;
+	VSTATE_ASSERT_UNLOCKED(vp, VS_ACTIVE);
+	return 0;
 }
 
 /*
@@ -405,10 +357,8 @@ genfs_unlock(void *v)
 	} */ *ap = v;
 	vnode_t *vp = ap->a_vp;
 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
-	struct mount *mp = vp->v_mount;
 
-	rw_exit(vip->vi_lock);
-	fstrans_done(mp);
+	rw_exit(&vip->vi_lock);
 
 	return 0;
 }
@@ -425,10 +375,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.39 src/sys/miscfs/genfs/layer_extern.h:1.39.6.1
--- src/sys/miscfs/genfs/layer_extern.h:1.39	Thu Mar 30 09:16:52 2017
+++ src/sys/miscfs/genfs/layer_extern.h	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: layer_extern.h,v 1.39 2017/03/30 09:16:52 hannken Exp $	*/
+/*	$NetBSD: layer_extern.h,v 1.39.6.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1999 National Aeronautics & Space Administration
@@ -113,8 +113,5 @@ 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.50 src/sys/miscfs/genfs/layer_vfsops.c:1.50.2.1
--- src/sys/miscfs/genfs/layer_vfsops.c:1.50	Thu Jun  1 02:45:13 2017
+++ src/sys/miscfs/genfs/layer_vfsops.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: layer_vfsops.c,v 1.50 2017/06/01 02:45:13 chs Exp $	*/
+/*	$NetBSD: layer_vfsops.c,v 1.50.2.1 2017/06/04 20:35:01 bouyer 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.50 2017/06/01 02:45:13 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.50.2.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/sysctl.h>
@@ -218,9 +218,6 @@ 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.66 src/sys/miscfs/genfs/layer_vnops.c:1.66.2.1
--- src/sys/miscfs/genfs/layer_vnops.c:1.66	Fri May 26 14:21:01 2017
+++ src/sys/miscfs/genfs/layer_vnops.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: layer_vnops.c,v 1.66 2017/05/26 14:21:01 riastradh Exp $	*/
+/*	$NetBSD: layer_vnops.c,v 1.66.2.1 2017/06/04 20:35:01 bouyer 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.66 2017/05/26 14:21:01 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.66.2.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -806,7 +806,7 @@ layer_getpages(void *v)
 
 	/* Just pass the request on to the underlying layer. */
 	mutex_exit(vp->v_interlock);
-	fstrans_start(mp, FSTRANS_SHARED);
+	fstrans_start(mp);
 	mutex_enter(vp->v_interlock);
 	if (mp == vp->v_mount) {
 		/* Will release the interlock. */

Index: src/sys/miscfs/nullfs/null_vnops.c
diff -u src/sys/miscfs/nullfs/null_vnops.c:1.41 src/sys/miscfs/nullfs/null_vnops.c:1.41.6.1
--- src/sys/miscfs/nullfs/null_vnops.c:1.41	Thu Mar 30 09:16:52 2017
+++ src/sys/miscfs/nullfs/null_vnops.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: null_vnops.c,v 1.41 2017/03/30 09:16:52 hannken Exp $	*/
+/*	$NetBSD: null_vnops.c,v 1.41.6.1 2017/06/04 20:35:01 bouyer 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.41 2017/03/30 09:16:52 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: null_vnops.c,v 1.41.6.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -106,9 +106,6 @@ const struct vnodeopv_entry_desc null_vn
 	{ &vop_fsync_desc,	layer_fsync },
 	{ &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.23 src/sys/miscfs/overlay/overlay_vnops.c:1.23.6.1
--- src/sys/miscfs/overlay/overlay_vnops.c:1.23	Thu Mar 30 09:16:52 2017
+++ src/sys/miscfs/overlay/overlay_vnops.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: overlay_vnops.c,v 1.23 2017/03/30 09:16:52 hannken Exp $	*/
+/*	$NetBSD: overlay_vnops.c,v 1.23.6.1 2017/06/04 20:35:01 bouyer 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.23 2017/03/30 09:16:52 hannken Exp $
+ *	$Id: overlay_vnops.c,v 1.23.6.1 2017/06/04 20:35:01 bouyer 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.23 2017/03/30 09:16:52 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: overlay_vnops.c,v 1.23.6.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -154,9 +154,6 @@ const struct vnodeopv_entry_desc overlay
 	{ &vop_fsync_desc,    layer_fsync },
 	{ &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.59 src/sys/miscfs/umapfs/umap_vnops.c:1.59.6.1
--- src/sys/miscfs/umapfs/umap_vnops.c:1.59	Thu Mar 30 09:16:53 2017
+++ src/sys/miscfs/umapfs/umap_vnops.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: umap_vnops.c,v 1.59 2017/03/30 09:16:53 hannken Exp $	*/
+/*	$NetBSD: umap_vnops.c,v 1.59.6.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umap_vnops.c,v 1.59 2017/03/30 09:16:53 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umap_vnops.c,v 1.59.6.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -88,9 +88,6 @@ const struct vnodeopv_entry_desc umap_vn
 	{ &vop_fsync_desc,	layer_fsync },
 	{ &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/rump/include/rump/rumpvnode_if.h
diff -u src/sys/rump/include/rump/rumpvnode_if.h:1.28 src/sys/rump/include/rump/rumpvnode_if.h:1.28.2.1
--- src/sys/rump/include/rump/rumpvnode_if.h:1.28	Fri May 26 14:21:54 2017
+++ src/sys/rump/include/rump/rumpvnode_if.h	Sun Jun  4 20:35:01 2017
@@ -1,13 +1,13 @@
-/*	$NetBSD: rumpvnode_if.h,v 1.28 2017/05/26 14:21:54 riastradh Exp $	*/
+/*	$NetBSD: rumpvnode_if.h,v 1.28.2.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*
  * Warning: DO NOT EDIT! This file is automatically generated!
  * (Modifications made here may easily be lost!)
  *
  * Created from the file:
- *	NetBSD: vnode_if.src,v 1.75 2017/05/26 14:21:00 riastradh Exp
+ *	NetBSD: vnode_if.src,v 1.76 2017/06/04 07:59:17 hannken Exp
  * by the script:
- *	NetBSD: vnode_if.sh,v 1.64 2017/04/16 17:18:28 riastradh Exp
+ *	NetBSD: vnode_if.sh,v 1.66 2017/06/04 08:03:26 hannken Exp
  */
 
 /*

Index: src/sys/rump/librump/rumpkern/emul.c
diff -u src/sys/rump/librump/rumpkern/emul.c:1.181 src/sys/rump/librump/rumpkern/emul.c:1.181.6.1
--- src/sys/rump/librump/rumpkern/emul.c:1.181	Wed Feb 22 11:20:59 2017
+++ src/sys/rump/librump/rumpkern/emul.c	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: emul.c,v 1.181 2017/02/22 11:20:59 hannken Exp $	*/
+/*	$NetBSD: emul.c,v 1.181.6.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*
  * Copyright (c) 2007-2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.181 2017/02/22 11:20:59 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.181.6.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/cprng.h>
@@ -243,14 +243,22 @@ __strong_alias(_delay,rump_delay);
 
 /* Weak aliases for fstrans to be used unless librumpvfs is present. */
 
-int rump__fstrans_start(struct mount *, enum fstrans_lock_type, int);
+void rump_fstrans_start(struct mount *);
+void
+rump_fstrans_start(struct mount *mp)
+{
+
+}
+__weak_alias(fstrans_start,rump_fstrans_start);
+
+int rump_fstrans_start_nowait(struct mount *);
 int
-rump__fstrans_start(struct mount *mp, enum fstrans_lock_type lock, int wait)
+rump_fstrans_start_nowait(struct mount *mp)
 {
 
 	return 0;
 }
-__weak_alias(_fstrans_start,rump__fstrans_start);
+__weak_alias(fstrans_start_nowait,rump_fstrans_start_nowait);
 
 void rump_fstrans_done(struct mount *);
 void

Index: src/sys/rump/librump/rumpvfs/rumpvnode_if.c
diff -u src/sys/rump/librump/rumpvfs/rumpvnode_if.c:1.28 src/sys/rump/librump/rumpvfs/rumpvnode_if.c:1.28.2.1
--- src/sys/rump/librump/rumpvfs/rumpvnode_if.c:1.28	Fri May 26 14:21:54 2017
+++ src/sys/rump/librump/rumpvfs/rumpvnode_if.c	Sun Jun  4 20:35:01 2017
@@ -1,13 +1,13 @@
-/*	$NetBSD: rumpvnode_if.c,v 1.28 2017/05/26 14:21:54 riastradh Exp $	*/
+/*	$NetBSD: rumpvnode_if.c,v 1.28.2.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*
  * Warning: DO NOT EDIT! This file is automatically generated!
  * (Modifications made here may easily be lost!)
  *
  * Created from the file:
- *	NetBSD: vnode_if.src,v 1.75 2017/05/26 14:21:00 riastradh Exp
+ *	NetBSD: vnode_if.src,v 1.76 2017/06/04 07:59:17 hannken Exp
  * by the script:
- *	NetBSD: vnode_if.sh,v 1.64 2017/04/16 17:18:28 riastradh Exp
+ *	NetBSD: vnode_if.sh,v 1.66 2017/06/04 08:03:26 hannken Exp
  */
 
 /*
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rumpvnode_if.c,v 1.28 2017/05/26 14:21:54 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rumpvnode_if.c,v 1.28.2.1 2017/06/04 20:35:01 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/mount.h>

Index: src/sys/sys/fstrans.h
diff -u src/sys/sys/fstrans.h:1.10 src/sys/sys/fstrans.h:1.10.60.1
--- src/sys/sys/fstrans.h:1.10	Fri Nov  7 00:15:42 2008
+++ src/sys/sys/fstrans.h	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: fstrans.h,v 1.10 2008/11/07 00:15:42 joerg Exp $	*/
+/*	$NetBSD: fstrans.h,v 1.10.60.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -41,25 +41,14 @@
 #define SUSPEND_SUSPEND	0x0001		/* VFS_SUSPENDCTL: suspend */
 #define SUSPEND_RESUME	0x0002		/* VFS_SUSPENDCTL: resume */
 
-enum fstrans_lock_type {
-	FSTRANS_LAZY = 1,		/* Granted while not suspended */
-	FSTRANS_SHARED = 2		/* Granted while not suspending */
-#ifdef _FSTRANS_API_PRIVATE
-	,
-	FSTRANS_EXCL = 3		/* Internal: exclusive lock */
-#endif /* _FSTRANS_API_PRIVATE */
-};
-
 enum fstrans_state {
 	FSTRANS_NORMAL,
-	FSTRANS_SUSPENDING,
 	FSTRANS_SUSPENDED
 };
 
 void	fstrans_init(void);
-#define fstrans_start(mp, t)		_fstrans_start((mp), (t), 1)
-#define fstrans_start_nowait(mp, t)	_fstrans_start((mp), (t), 0)
-int	_fstrans_start(struct mount *, enum fstrans_lock_type, int);
+void	fstrans_start(struct mount *);
+int	fstrans_start_nowait(struct mount *);
 void	fstrans_done(struct mount *);
 int	fstrans_is_owner(struct mount *);
 int	fstrans_mount(struct mount *);

Index: src/sys/sys/vnode.h
diff -u src/sys/sys/vnode.h:1.277 src/sys/sys/vnode.h:1.277.4.1
--- src/sys/sys/vnode.h:1.277	Tue Apr 11 14:29:32 2017
+++ src/sys/sys/vnode.h	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: vnode.h,v 1.277 2017/04/11 14:29:32 riastradh Exp $	*/
+/*	$NetBSD: vnode.h,v 1.277.4.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -512,7 +512,6 @@ 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_if.h
diff -u src/sys/sys/vnode_if.h:1.99 src/sys/sys/vnode_if.h:1.99.2.1
--- src/sys/sys/vnode_if.h:1.99	Fri May 26 14:21:55 2017
+++ src/sys/sys/vnode_if.h	Sun Jun  4 20:35:01 2017
@@ -1,13 +1,13 @@
-/*	$NetBSD: vnode_if.h,v 1.99 2017/05/26 14:21:55 riastradh Exp $	*/
+/*	$NetBSD: vnode_if.h,v 1.99.2.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*
  * Warning: DO NOT EDIT! This file is automatically generated!
  * (Modifications made here may easily be lost!)
  *
  * Created from the file:
- *	NetBSD: vnode_if.src,v 1.75 2017/05/26 14:21:00 riastradh Exp
+ *	NetBSD: vnode_if.src,v 1.76 2017/06/04 07:59:17 hannken Exp
  * by the script:
- *	NetBSD: vnode_if.sh,v 1.64 2017/04/16 17:18:28 riastradh Exp
+ *	NetBSD: vnode_if.sh,v 1.66 2017/06/04 08:03:26 hannken Exp
  */
 
 /*

Index: src/sys/sys/vnode_impl.h
diff -u src/sys/sys/vnode_impl.h:1.13 src/sys/sys/vnode_impl.h:1.13.6.1
--- src/sys/sys/vnode_impl.h:1.13	Thu Mar 30 09:16:53 2017
+++ src/sys/sys/vnode_impl.h	Sun Jun  4 20:35:01 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: vnode_impl.h,v 1.13 2017/03/30 09:16:53 hannken Exp $	*/
+/*	$NetBSD: vnode_impl.h,v 1.13.6.1 2017/06/04 20:35:01 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -37,9 +37,10 @@
 struct namecache;
 
 enum vnode_state {
+	VS_ACTIVE,	/* Assert only, fs node attached and usecount > 0. */
 	VS_MARKER,	/* Stable, used as marker. Will not change. */
 	VS_LOADING,	/* Intermediate, initialising the fs node. */
-	VS_ACTIVE,	/* Stable, valid fs node attached. */
+	VS_LOADED,	/* Stable, valid fs node attached. */
 	VS_BLOCKED,	/* Intermediate, active, no new references allowed. */
 	VS_RECLAIMING,	/* Intermediate, detaching the fs node. */
 	VS_RECLAIMED	/* Stable, no fs node attached. */
@@ -76,7 +77,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;
@@ -85,6 +86,31 @@ typedef struct vnode_impl vnode_impl_t;
 #define VNODE_TO_VIMPL(vp)	container_of((vp), struct vnode_impl, vi_vnode)
 
 /*
+ * Vnode state assertion.
+ */
+void _vstate_assert(vnode_t *, enum vnode_state, const char *, int );
+
+#if defined(DIAGNOSTIC) 
+
+#define VSTATE_ASSERT(vp, state) \
+	do { \
+		_vstate_assert((vp), (state), __func__, __LINE__); \
+	} while (/*CONSTCOND*/ 0)
+#define VSTATE_ASSERT_UNLOCKED(vp, state) \
+	do { \
+		mutex_enter((vp)->v_interlock); \
+		_vstate_assert((vp), (state), __func__, __LINE__); \
+		mutex_exit((vp)->v_interlock); \
+	} while (/*CONSTCOND*/ 0)
+
+#else /* defined(DIAGNOSTIC) */
+
+#define VSTATE_ASSERT(vp, state)
+#define VSTATE_ASSERT_UNLOCKED(vp, state)
+
+#endif /* defined(DIAGNOSTIC) */
+
+/*
  * Vnode manipulation functions.
  */
 const char *

Index: src/sys/ufs/lfs/lfs_pages.c
diff -u src/sys/ufs/lfs/lfs_pages.c:1.11 src/sys/ufs/lfs/lfs_pages.c:1.11.6.1
--- src/sys/ufs/lfs/lfs_pages.c:1.11	Sat Apr  1 17:34:21 2017
+++ src/sys/ufs/lfs/lfs_pages.c	Sun Jun  4 20:35:02 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_pages.c,v 1.11 2017/04/01 17:34:21 maya Exp $	*/
+/*	$NetBSD: lfs_pages.c,v 1.11.6.1 2017/06/04 20:35:02 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_pages.c,v 1.11 2017/04/01 17:34:21 maya Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_pages.c,v 1.11.6.1 2017/06/04 20:35:02 bouyer Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -596,7 +596,7 @@ retry:
 		if (pagedaemon) {
 			/* Pagedaemon must not sleep here. */
 			trans_mp = vp->v_mount;
-			error = fstrans_start_nowait(trans_mp, FSTRANS_SHARED);
+			error = fstrans_start_nowait(trans_mp);
 			if (error) {
 				mutex_exit(vp->v_interlock);
 				return error;
@@ -609,7 +609,7 @@ retry:
 			 */
 			mutex_exit(vp->v_interlock);
 			trans_mp = vp->v_mount;
-			fstrans_start(trans_mp, FSTRANS_SHARED);
+			fstrans_start(trans_mp);
 			if (vp->v_mount != trans_mp) {
 				fstrans_done(trans_mp);
 				trans_mp = NULL;

Reply via email to