Index: sys/ufs/lfs/lfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_vnops.c,v
retrieving revision 1.309
diff -p -u -r1.309 lfs_vnops.c
--- sys/ufs/lfs/lfs_vnops.c	1 Apr 2017 14:43:00 -0000	1.309
+++ sys/ufs/lfs/lfs_vnops.c	1 Apr 2017 18:02:22 -0000
@@ -407,6 +407,7 @@ lfs_makeinode(struct vattr *vap, struct 
 	if (error)
 		goto bad;
 	*vpp = tvp;
+	KASSERT(VOP_ISLOCKED(*vpp) == LK_EXCLUSIVE);
 	return (0);
 
  bad:
@@ -438,17 +439,20 @@ lfs_fsync(void *v)
 		off_t offhi;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
-	int error, wait;
+	int wait;
 	struct inode *ip = VTOI(vp);
 	struct lfs *fs = ip->i_lfs;
+	int error = 0;
+
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
 
 	/* If we're mounted read-only, don't try to sync. */
 	if (fs->lfs_ronly)
-		return 0;
+		goto out;
 
 	/* If a removed vnode is being cleaned, no need to sync here. */
 	if ((ap->a_flags & FSYNC_RECLAIM) != 0 && ip->i_mode == 0)
-		return 0;
+		goto out;
 
 	/*
 	 * Trickle sync simply adds this vnode to the pager list, as if
@@ -465,7 +469,7 @@ lfs_fsync(void *v)
 			wakeup(&lfs_writer_daemon);
 			mutex_exit(&lfs_lock);
 		}
-		return 0;
+		goto out;
 	}
 
 	/*
@@ -491,7 +495,7 @@ lfs_fsync(void *v)
 		}
 	} while (error == EAGAIN);
 	if (error)
-		return error;
+		goto out;
 
 	if ((ap->a_flags & FSYNC_DATAONLY) == 0)
 		error = lfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0);
@@ -504,6 +508,8 @@ lfs_fsync(void *v)
 	if (wait && !VPISEMPTY(vp))
 		LFS_SET_UINO(ip, IN_MODIFIED);
 
+out:
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
 	return error;
 }
 
@@ -517,6 +523,8 @@ lfs_inactive(void *v)
 		struct vnode *a_vp;
 	} */ *ap = v;
 
+	KASSERT(VOP_ISLOCKED(ap->a_vp) == LK_EXCLUSIVE);
+
 	lfs_unmark_vnode(ap->a_vp);
 
 	/*
@@ -552,8 +560,8 @@ lfs_set_dirop(struct vnode *dvp, struct 
 	struct lfs *fs;
 	int error;
 
-	KASSERT(VOP_ISLOCKED(dvp));
-	KASSERT(vp == NULL || VOP_ISLOCKED(vp));
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+	KASSERT(vp == NULL || VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
 
 	fs = VTOI(dvp)->i_lfs;
 
@@ -701,6 +709,7 @@ lfs_symlink(void *v)
 	dvp = ap->a_dvp;
 	vpp = ap->a_vpp;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
 	KASSERT(vpp != NULL);
 	KASSERT(*vpp == NULL);
 	KASSERT(ap->a_vap->va_type == VLNK);
@@ -723,6 +732,7 @@ lfs_symlink(void *v)
 	if (error) {
 		goto out;
 	}
+	KASSERT(VOP_ISLOCKED(*vpp) == LK_EXCLUSIVE);
 
 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
 	ip = VTOI(*vpp);
@@ -787,9 +797,10 @@ lfs_mknod(void *v)
 	vpp = ap->a_vpp;
 	vap = ap->a_vap;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
 	KASSERT(vpp != NULL);
 	KASSERT(*vpp == NULL);
-	
+
 	/* XXX should handle this material another way */
 	ulr = &VTOI(dvp)->i_crap;
 	ULFS_CHECK_CRAPCOUNTER(VTOI(dvp));
@@ -816,6 +827,7 @@ lfs_mknod(void *v)
 		*vpp = NULL;
 		return (error);
 	}
+	KASSERT(VOP_ISLOCKED(*vpp) == LK_EXCLUSIVE);
 
 	VN_KNOTE(dvp, NOTE_WRITE);
 	ip = VTOI(*vpp);
@@ -864,6 +876,7 @@ lfs_create(void *v)
 	vpp = ap->a_vpp;
 	vap = ap->a_vap;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
 	KASSERT(vpp != NULL);
 	KASSERT(*vpp == NULL);
 
@@ -885,6 +898,7 @@ lfs_create(void *v)
 	if (error) {
 		goto out;
 	}
+	KASSERT(VOP_ISLOCKED(*vpp) == LK_EXCLUSIVE);
 	VN_KNOTE(dvp, NOTE_WRITE);
 	VOP_UNLOCK(*vpp);
 
@@ -927,6 +941,8 @@ lfs_mkdir(void *v)
 	cnp = ap->a_cnp;
 	vap = ap->a_vap;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	dp = VTOI(dvp);
 	ip = NULL;
 
@@ -1078,6 +1094,10 @@ lfs_remove(void *v)
 
 	dvp = ap->a_dvp;
 	vp = ap->a_vp;
+
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	ip = VTOI(vp);
 	if ((error = lfs_set_dirop(dvp, vp)) != 0) {
 		if (dvp == vp)
@@ -1118,6 +1138,10 @@ lfs_rmdir(void *v)
 	int error;
 
 	vp = ap->a_vp;
+
+	KASSERT(VOP_ISLOCKED(ap->a_dvp) == LK_EXCLUSIVE);
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	ip = VTOI(vp);
 	if ((error = lfs_set_dirop(ap->a_dvp, ap->a_vp)) != 0) {
 		if (ap->a_dvp == vp)
@@ -1158,6 +1182,8 @@ lfs_link(void *v)
 
 	dvp = ap->a_dvp;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	fs = VFSTOULFS(dvp->v_mount)->um_lfs;
 	ASSERT_NO_SEGLOCK(fs);
 	if (fs->lfs_ronly) {
@@ -1188,9 +1214,14 @@ lfs_getattr(void *v)
 		kauth_cred_t a_cred;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
-	struct inode *ip = VTOI(vp);
+	struct inode *ip;
 	struct vattr *vap = ap->a_vap;
-	struct lfs *fs = ip->i_lfs;
+	struct lfs *fs;
+
+	KASSERT(VOP_ISLOCKED(vp));
+
+	ip = VTOI(vp);
+	fs = ip->i_lfs;
 
 	/*
 	 * Copy from inode table
@@ -1246,6 +1277,7 @@ lfs_setattr(void *v)
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
 	lfs_check(vp, LFS_UNUSED_LBN, 0);
 	return ulfs_setattr(v);
 }
@@ -1297,8 +1329,13 @@ lfs_close(void *v)
 		kauth_cred_t a_cred;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
-	struct inode *ip = VTOI(vp);
-	struct lfs *fs = ip->i_lfs;
+	struct inode *ip;
+	struct lfs *fs;
+
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
+	ip = VTOI(vp);
+	fs = ip->i_lfs;
 
 	if ((ip->i_number == ULFS_ROOTINO || ip->i_number == LFS_IFILE_INUM) &&
 	    fs->lfs_stoplwp == curlwp) {
@@ -1335,6 +1372,9 @@ lfsspec_close(void *v)
 	struct inode	*ip;
 
 	vp = ap->a_vp;
+
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	ip = VTOI(vp);
 	if (vp->v_usecount > 1) {
 		LFS_ITIMES(ip, NULL, NULL, NULL);
@@ -1359,6 +1399,9 @@ lfsfifo_close(void *v)
 	struct inode	*ip;
 
 	vp = ap->a_vp;
+
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	ip = VTOI(vp);
 	if (ap->a_vp->v_usecount > 1) {
 		LFS_ITIMES(ip, NULL, NULL, NULL);
@@ -1377,10 +1420,13 @@ lfs_reclaim(void *v)
 		struct vnode *a_vp;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
-	struct inode *ip = VTOI(vp);
-	struct lfs *fs = ip->i_lfs;
+	struct inode *ip;
+	struct lfs *fs;
 	int error;
 
+	ip = VTOI(vp);
+	fs = ip->i_lfs;
+
 	/*
 	 * The inode must be freed and updated before being removed
 	 * from its hash chain.  Other threads trying to gain a hold
@@ -2194,9 +2240,14 @@ lfs_openextattr(void *v)
 		kauth_cred_t a_cred;
 		struct proc *a_p;
 	} */ *ap = v;
-	struct inode *ip = VTOI(ap->a_vp);
-	struct ulfsmount *ump = ip->i_ump;
-	//struct lfs *fs = ip->i_lfs;
+	struct vnode *vp = ap->a_vp;
+	struct inode *ip;
+	struct ulfsmount *ump;
+
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
+	ip = VTOI(vp);
+	ump = ip->i_ump;
 
 	/* Not supported for ULFS1 file systems. */
 	if (ump->um_fstype == ULFS1)
@@ -2215,9 +2266,14 @@ lfs_closeextattr(void *v)
 		kauth_cred_t a_cred;
 		struct proc *a_p;
 	} */ *ap = v;
-	struct inode *ip = VTOI(ap->a_vp);
-	struct ulfsmount *ump = ip->i_ump;
-	//struct lfs *fs = ip->i_lfs;
+	struct vnode *vp = ap->a_vp;
+	struct inode *ip;
+	struct ulfsmount *ump;
+
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
+	ip = VTOI(ap->a_vp);
+	ump = ip->i_ump;
 
 	/* Not supported for ULFS1 file systems. */
 	if (ump->um_fstype == ULFS1)
@@ -2240,11 +2296,15 @@ lfs_getextattr(void *v)
 		struct proc *a_p;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
-	struct inode *ip = VTOI(vp);
-	struct ulfsmount *ump = ip->i_ump;
-	//struct lfs *fs = ip->i_lfs;
+	struct inode *ip;
+	struct ulfsmount *ump;
 	int error;
 
+	KASSERT(VOP_ISLOCKED(vp));
+
+	ip = VTOI(vp);
+	ump = ip->i_ump;
+
 	if (ump->um_fstype == ULFS1) {
 #ifdef LFS_EXTATTR
 		error = ulfs_getextattr(ap);
@@ -2270,11 +2330,15 @@ lfs_setextattr(void *v)
 		struct proc *a_p;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
-	struct inode *ip = VTOI(vp);
-	struct ulfsmount *ump = ip->i_ump;
-	//struct lfs *fs = ip->i_lfs;
+	struct inode *ip;
+	struct ulfsmount *ump;
 	int error;
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
+	ip = VTOI(vp);
+	ump = ip->i_ump;
+
 	if (ump->um_fstype == ULFS1) {
 #ifdef LFS_EXTATTR
 		error = ulfs_setextattr(ap);
@@ -2300,11 +2364,15 @@ lfs_listextattr(void *v)
 		struct proc *a_p;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
-	struct inode *ip = VTOI(vp);
-	struct ulfsmount *ump = ip->i_ump;
-	//struct lfs *fs = ip->i_lfs;
+	struct inode *ip;
+	struct ulfsmount *ump;
 	int error;
 
+	KASSERT(VOP_ISLOCKED(vp));
+
+	ip = VTOI(vp);
+	ump = ip->i_ump;
+
 	if (ump->um_fstype == ULFS1) {
 #ifdef LFS_EXTATTR
 		error = ulfs_listextattr(ap);
@@ -2328,11 +2396,15 @@ lfs_deleteextattr(void *v)
 		struct proc *a_p;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
-	struct inode *ip = VTOI(vp);
-	struct ulfsmount *ump = ip->i_ump;
-	//struct fs *fs = ip->i_lfs;
+	struct inode *ip;
+	struct ulfsmount *ump;
 	int error;
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
+	ip = VTOI(vp);
+	ump = ip->i_ump;
+
 	if (ump->um_fstype == ULFS1) {
 #ifdef LFS_EXTATTR
 		error = ulfs_deleteextattr(ap);
Index: sys/ufs/lfs/ulfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/ulfs_vnops.c,v
retrieving revision 1.46
diff -p -u -r1.46 ulfs_vnops.c
--- sys/ufs/lfs/ulfs_vnops.c	30 Mar 2017 09:10:08 -0000	1.46
+++ sys/ufs/lfs/ulfs_vnops.c	1 Apr 2017 18:02:22 -0000
@@ -128,6 +128,8 @@ ulfs_open(void *v)
 		kauth_cred_t	a_cred;
 	} */ *ap = v;
 
+	KASSERT(VOP_ISLOCKED(ap->a_vp) == LK_EXCLUSIVE);
+
 	/*
 	 * Files marked append-only must be opened for appending.
 	 */
@@ -208,9 +210,12 @@ ulfs_access(void *v)
 	int		error;
 
 	vp = ap->a_vp;
-	ip = VTOI(vp);
 	mode = ap->a_mode;
 
+	KASSERT(VOP_ISLOCKED(vp));
+
+	ip = VTOI(vp);
+
 	error = ulfs_check_possible(vp, ip, mode, ap->a_cred);
 	if (error)
 		return error;
@@ -243,13 +248,16 @@ ulfs_setattr(void *v)
 
 	vap = ap->a_vap;
 	vp = ap->a_vp;
-	ip = VTOI(vp);
-	fs = ip->i_lfs;
 	cred = ap->a_cred;
 	l = curlwp;
 	action = KAUTH_VNODE_WRITE_FLAGS;
 	changing_sysflags = false;
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
+	ip = VTOI(vp);
+	fs = ip->i_lfs;
+
 	/*
 	 * Check for unsettable attributes.
 	 */
@@ -411,6 +419,8 @@ ulfs_chmod(struct vnode *vp, int mode, k
 	struct inode	*ip;
 	int		error;
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	ip = VTOI(vp);
 
 	error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
@@ -440,6 +450,9 @@ ulfs_chown(struct vnode *vp, uid_t uid, 
 	gid_t		ogid;
 	int64_t		change;
 #endif
+
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	ip = VTOI(vp);
 	error = 0;
 
@@ -497,10 +510,14 @@ ulfs_remove(void *v)
 	int		error;
 	struct ulfs_lookup_results *ulr;
 
-	vp = ap->a_vp;
 	dvp = ap->a_dvp;
+	vp = ap->a_vp;
+
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+	KASSERT(dvp->v_mount == vp->v_mount);
+
 	ip = VTOI(vp);
-	KASSERT(dvp->v_mount == vp->v_mount); /* XXX Not stable without lock. */
 
 	/* XXX should handle this material another way */
 	ulr = &VTOI(dvp)->i_crap;
@@ -541,9 +558,9 @@ ulfs_link(void *v)
 	int error;
 	struct ulfs_lookup_results *ulr;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
 	KASSERT(dvp != vp);
 	KASSERT(vp->v_type != VDIR);
-	KASSERT(dvp->v_mount == vp->v_mount); /* XXX Not stable without lock. */
 
 	/* XXX should handle this material another way */
 	ulr = &VTOI(dvp)->i_crap;
@@ -554,6 +571,11 @@ ulfs_link(void *v)
 		VOP_ABORTOP(dvp, cnp);
 		goto out2;
 	}
+	if (vp->v_mount != dvp->v_mount) {
+		error = ENOENT;
+		VOP_ABORTOP(dvp, cnp);
+		goto out2;
+	}
 	ip = VTOI(vp);
 	if ((nlink_t)ip->i_nlink >= LINK_MAX) {
 		VOP_ABORTOP(dvp, cnp);
@@ -604,6 +626,8 @@ ulfs_whiteout(void *v)
 	struct lfs *fs = ump->um_lfs;
 	struct ulfs_lookup_results *ulr;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	/* XXX should handle this material another way */
 	ulr = &VTOI(dvp)->i_crap;
 	ULFS_CHECK_CRAPCOUNTER(VTOI(dvp));
@@ -654,11 +678,15 @@ ulfs_rmdir(void *v)
 	int			error;
 	struct ulfs_lookup_results *ulr;
 
-	vp = ap->a_vp;
 	dvp = ap->a_dvp;
+	vp = ap->a_vp;
 	cnp = ap->a_cnp;
-	ip = VTOI(vp);
+
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	dp = VTOI(dvp);
+	ip = VTOI(vp);
 
 	/* XXX should handle this material another way */
 	ulr = &dp->i_crap;
@@ -759,6 +787,9 @@ ulfs_readdir(void *v)
 	size_t		skipbytes;
 	struct ulfsmount *ump = VFSTOULFS(vp->v_mount);
 	struct lfs *fs = ump->um_lfs;
+
+	KASSERT(VOP_ISLOCKED(vp));
+
 	uio = ap->a_uio;
 	count = uio->uio_resid;
 	rcount = count - ((uio->uio_offset + count) & (fs->um_dirblksiz - 1));
@@ -884,6 +915,8 @@ ulfs_readlink(void *v)
 	struct lfs *fs = ump->um_lfs;
 	int		isize;
 
+	KASSERT(VOP_ISLOCKED(vp));
+
 	/*
 	 * The test against um_maxsymlinklen is off by one; it should
 	 * theoretically be <=, not <. However, it cannot be changed
@@ -941,6 +974,8 @@ ulfsspec_read(void *v)
 		kauth_cred_t	a_cred;
 	} */ *ap = v;
 
+	KASSERT(VOP_ISLOCKED(ap->a_vp));
+
 	/*
 	 * Set access flag.
 	 */
@@ -962,6 +997,8 @@ ulfsspec_write(void *v)
 		kauth_cred_t	a_cred;
 	} */ *ap = v;
 
+	KASSERT(VOP_ISLOCKED(ap->a_vp) == LK_EXCLUSIVE);
+
 	/*
 	 * Set update and change flags.
 	 */
@@ -983,6 +1020,8 @@ ulfsfifo_read(void *v)
 		kauth_cred_t	a_cred;
 	} */ *ap = v;
 
+	KASSERT(VOP_ISLOCKED(ap->a_vp));
+
 	/*
 	 * Set access flag.
 	 */
@@ -1003,6 +1042,8 @@ ulfsfifo_write(void *v)
 		kauth_cred_t	a_cred;
 	} */ *ap = v;
 
+	KASSERT(VOP_ISLOCKED(ap->a_vp) == LK_EXCLUSIVE);
+
 	/*
 	 * Set update and change flags.
 	 */
@@ -1141,6 +1182,8 @@ ulfs_gop_alloc(struct vnode *vp, off_t o
         int error, delta, bshift, bsize;
         UVMHIST_FUNC("ulfs_gop_alloc"); UVMHIST_CALLED(ubchist);
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
         error = 0;
         bshift = vp->v_mount->mnt_fs_bshift;
         bsize = 1 << bshift;