From 95135e627ddb5027ddb0f90bd0aad895b9637b74 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Wed, 4 Jun 2014 23:26:07 +0200
Subject: [PATCH 2/2] kernel: Add a number of missing crit_exit, lwkt_reltoken,
 rel_mplock, etc.

---
 sys/bus/firewire/firewire.c       | 1 +
 sys/dev/misc/snp/snp.c            | 4 +++-
 sys/dev/misc/sysvipc/sysvipc.c    | 4 +++-
 sys/dev/raid/aac/aac.c            | 5 +++--
 sys/dev/raid/dpt/dpt_pci.c        | 1 +
 sys/dev/raid/hpt27xx/osm_bsd.c    | 7 ++++---
 sys/dev/raid/mfi/mfi.c            | 4 +++-
 sys/dev/serial/cy/cy.c            | 5 ++++-
 sys/dev/serial/si/si.c            | 4 +++-
 sys/dev/serial/sio/sio.c          | 4 +++-
 sys/emulation/linux/linux_stats.c | 8 ++++++--
 sys/net/sppp/if_spppsubr.c        | 8 ++++++--
 sys/netinet/ip_input.c            | 1 +
 sys/netinet/sctp_output.c         | 6 +++++-
 sys/netproto/ipsec/key.c          | 4 +++-
 sys/netproto/ipsec/xform_ah.c     | 7 +++++--
 sys/vfs/hammer2/hammer2_vfsops.c  | 2 ++
 sys/vfs/nfs/nfs_vnops.c           | 8 ++++++--
 18 files changed, 62 insertions(+), 21 deletions(-)

diff --git a/sys/bus/firewire/firewire.c b/sys/bus/firewire/firewire.c
index 81139fa..02204fa 100644
--- a/sys/bus/firewire/firewire.c
+++ b/sys/bus/firewire/firewire.c
@@ -1884,6 +1884,7 @@ fw_rcv(struct fw_rcv_buf *rb)
 			rb->xfer = STAILQ_FIRST(&bind->xferlist);
 			if (rb->xfer == NULL) {
 				kprintf("Discard packet for this bind\n");
+				crit_exit();
 				goto err;
 			}
 			STAILQ_REMOVE_HEAD(&bind->xferlist, link);
diff --git a/sys/dev/misc/snp/snp.c b/sys/dev/misc/snp/snp.c
index 69fba20..1d83373 100644
--- a/sys/dev/misc/snp/snp.c
+++ b/sys/dev/misc/snp/snp.c
@@ -718,8 +718,10 @@ snp_modevent(module_t mod, int type, void *data)
 		}
 		break;
 	case MOD_UNLOAD:
-		if (!LIST_EMPTY(&snp_sclist))
+		if (!LIST_EMPTY(&snp_sclist)) {
+			lwkt_reltoken(&tty_token);
 			return (EBUSY);
+		}
 		ldisc_deregister(snooplinedisc);
 		devfs_clone_handler_del("snp");
 		dev_ops_remove_all(&snp_ops);
diff --git a/sys/dev/misc/sysvipc/sysvipc.c b/sys/dev/misc/sysvipc/sysvipc.c
index e5498b3..01378da 100644
--- a/sys/dev/misc/sysvipc/sysvipc.c
+++ b/sys/dev/misc/sysvipc/sysvipc.c
@@ -398,8 +398,10 @@ sysvipc_dev_ioctl(struct dev_ioctl_args *ap)
 		 * list of consumed requests.
 		 */
 		req = TAILQ_LAST( &sysv->req_list, _req_list);
-		if(!req)
+		if(!req) {
+			lockmgr(&sysv->req_mtx, LK_RELEASE);
 			return (EINVAL);
+		}
 		TAILQ_REMOVE(&sysv->req_list, req, req_link);
 		lockmgr(&sysv->req_mtx, LK_RELEASE);
 
diff --git a/sys/dev/raid/aac/aac.c b/sys/dev/raid/aac/aac.c
index cc47779..2997d33 100644
--- a/sys/dev/raid/aac/aac.c
+++ b/sys/dev/raid/aac/aac.c
@@ -2953,16 +2953,17 @@ aac_filter_read(struct knote *kn, long hint)
 {
 	struct aac_softc *sc;
 	struct aac_fib_context *ctx;
+	int ret = 0;
 
 	sc = (struct aac_softc *)kn->kn_hook;
 
 	lockmgr(&sc->aac_aifq_lock, LK_EXCLUSIVE);
 	for (ctx = sc->fibctx; ctx; ctx = ctx->next)
 		if (ctx->ctx_idx != sc->aifq_idx || ctx->ctx_wrap)
-			return(1);
+			ret = 1;
 	lockmgr(&sc->aac_aifq_lock, LK_RELEASE);
 
-	return (0);
+	return(ret);
 }
 
 static void
diff --git a/sys/dev/raid/dpt/dpt_pci.c b/sys/dev/raid/dpt/dpt_pci.c
index f0bc443..0c46373 100644
--- a/sys/dev/raid/dpt/dpt_pci.c
+++ b/sys/dev/raid/dpt/dpt_pci.c
@@ -153,6 +153,7 @@ dpt_pci_attach (device_t dev)
 	if (dpt_init(dpt) != 0) {
 		dpt_free(dpt);
 		error = ENXIO;
+		crit_exit();
 		goto bad;
 	}
 
diff --git a/sys/dev/raid/hpt27xx/osm_bsd.c b/sys/dev/raid/hpt27xx/osm_bsd.c
index 0f0d75f..ce88981 100644
--- a/sys/dev/raid/hpt27xx/osm_bsd.c
+++ b/sys/dev/raid/hpt27xx/osm_bsd.c
@@ -1340,10 +1340,11 @@ static int	hpt_rescan_bus(void)
 
 	ldm_for_each_vbus(vbus, vbus_ext) {
 		if (xpt_create_path(&path, xpt_periph, cam_sim_path(vbus_ext->sim),
-			CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
+			CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+			rel_mplock();
 			return(EIO);
-		if ((ccb = kmalloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
-			return(ENOMEM);
+		}
+		ccb = kmalloc(sizeof(union ccb), M_TEMP, M_WAITOK);
 		bzero(ccb, sizeof(union ccb));
 		xpt_setup_ccb(&ccb->ccb_h, path, 5);
 		ccb->ccb_h.func_code = XPT_SCAN_BUS;
diff --git a/sys/dev/raid/mfi/mfi.c b/sys/dev/raid/mfi/mfi.c
index 18f5bf2..e906272 100644
--- a/sys/dev/raid/mfi/mfi.c
+++ b/sys/dev/raid/mfi/mfi.c
@@ -905,8 +905,10 @@ mfi_comms_init(struct mfi_softc *sc)
 	uint32_t context = 0;
 
 	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
-	if ((cm = mfi_dequeue_free(sc)) == NULL)
+	if ((cm = mfi_dequeue_free(sc)) == NULL) {
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 		return (EBUSY);
+	}
 
 	/* Zero out the MFI frame */
 	context = cm->cm_frame->header.context;
diff --git a/sys/dev/serial/cy/cy.c b/sys/dev/serial/cy/cy.c
index 574733d..95465fb 100644
--- a/sys/dev/serial/cy/cy.c
+++ b/sys/dev/serial/cy/cy.c
@@ -896,6 +896,7 @@ siowrite(struct dev_write_args *ap)
 	int		mynor;
 	struct tty	*tp;
 	int		unit;
+	int		ret;
 
 	mynor = minor(dev);
 	if (mynor & CONTROL_MASK)
@@ -917,10 +918,12 @@ siowrite(struct dev_write_args *ap)
 	 * CR & LF chars.  Hardly worth the effort, given that high-throughput
 	 * sessions are raw anyhow.
 	 */
+	ret = 0;
 #else
-	return ((*linesw[tp->t_line].l_write)(tp, uio, ap->a_ioflag));
+	ret = (*linesw[tp->t_line].l_write)(tp, uio, ap->a_ioflag);
 #endif
 	lwkt_reltoken(&tty_token);
+	return(ret);
 }
 
 static void
diff --git a/sys/dev/serial/si/si.c b/sys/dev/serial/si/si.c
index 48ed1ff..cc21700 100644
--- a/sys/dev/serial/si/si.c
+++ b/sys/dev/serial/si/si.c
@@ -1001,8 +1001,10 @@ siioctl(struct dev_ioctl_args *ap)
 		switch (cmd) {
 		case TIOCSETA:
 			error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
-			if (error != 0)
+			if (error != 0) {
+				lwkt_reltoken(&tty_token);
 				return (error);
+			}
 			*ct = *(struct termios *)data;
 			lwkt_reltoken(&tty_token);
 			return (0);
diff --git a/sys/dev/serial/sio/sio.c b/sys/dev/serial/sio/sio.c
index 3782711..d61aa0a 100644
--- a/sys/dev/serial/sio/sio.c
+++ b/sys/dev/serial/sio/sio.c
@@ -2040,8 +2040,10 @@ sioioctl(struct dev_ioctl_args *ap)
 		switch (ap->a_cmd) {
 		case TIOCSETA:
 			error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
-			if (error != 0)
+			if (error != 0) {
+				lwkt_reltoken(&tty_token);
 				return (error);
+			}
 			*ct = *(struct termios *)data;
 			lwkt_reltoken(&tty_token);
 			return (0);
diff --git a/sys/emulation/linux/linux_stats.c b/sys/emulation/linux/linux_stats.c
index 58bc685..754057b 100644
--- a/sys/emulation/linux/linux_stats.c
+++ b/sys/emulation/linux/linux_stats.c
@@ -311,10 +311,14 @@ sys_linux_fstatfs(struct linux_fstatfs_args *args)
 		kprintf(ARGS(fstatfs, "%d, *"), args->fd);
 #endif
 	get_mplock();
-	if ((error = kern_fstatfs(args->fd, &statfs)) != 0)
+	if ((error = kern_fstatfs(args->fd, &statfs)) != 0) {
+		rel_mplock();
 		return (error);
-	if ((error = holdvnode(p->p_fd, args->fd, &fp)) != 0)
+	}
+	if ((error = holdvnode(p->p_fd, args->fd, &fp)) != 0) {
+		rel_mplock();
 		return (error);
+	}
 	error = vn_get_namelen((struct vnode *)fp->f_data, &namelen);
 	rel_mplock();
 	fdrop(fp);
diff --git a/sys/net/sppp/if_spppsubr.c b/sys/net/sppp/if_spppsubr.c
index 4d2693a..b412bc8 100644
--- a/sys/net/sppp/if_spppsubr.c
+++ b/sys/net/sppp/if_spppsubr.c
@@ -1150,15 +1150,19 @@ sppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data)
 #define ifr_mtu ifr_metric
 #endif
 	case SIOCSIFMTU:
-		if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru)
+		if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) {
+			crit_exit();
 			return (EINVAL);
+		}
 		ifp->if_mtu = ifr->ifr_mtu;
 		break;
 #endif
 #ifdef SLIOCSETMTU
 	case SLIOCSETMTU:
-		if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru)
+		if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) {
+			crit_exit();
 			return (EINVAL);
+		}
 		ifp->if_mtu = *(short*)data;
 		break;
 #endif
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 8682e19..ae30b42 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -924,6 +924,7 @@ ours:
 			/* XXX error stat??? */
 			error = EINVAL;
 DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
+			crit_exit();
 			goto bad;
 		}
 		crit_exit();
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index d690300..177599d 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -9544,8 +9544,10 @@ sctp_copy_it_in(struct sctp_inpcb *inp,
 	/* lock the socket buf */
 	SOCKBUF_LOCK(&so->so_snd);
 	error = ssb_lock(&so->so_snd, SBLOCKWAIT(flags));
-	if (error)
+	if (error) {
+		crit_exit();
 		goto out_locked;
+	}
 
 	/* will it ever fit ? */
 	if (sndlen > so->so_snd.ssb_hiwat) {
@@ -9582,6 +9584,7 @@ sctp_copy_it_in(struct sctp_inpcb *inp,
 			if (flags & (MSG_FNONBLOCKING|MSG_DONTWAIT)) {
 				/* Non-blocking io in place */
 				error = EWOULDBLOCK;
+				crit_exit();
 				goto release;
 			}
 			inp->sctp_tcb_at_block = (void *)stcb;
@@ -9599,6 +9602,7 @@ sctp_copy_it_in(struct sctp_inpcb *inp,
 				/* Should I really unlock ? */
 				SCTP_INP_RUNLOCK(inp);
 				error = EFAULT;
+				crit_exit();
 				goto out_locked;
 			}
 			SCTP_TCB_LOCK(stcb);
diff --git a/sys/netproto/ipsec/key.c b/sys/netproto/ipsec/key.c
index a6c9039..a7135ae 100644
--- a/sys/netproto/ipsec/key.c
+++ b/sys/netproto/ipsec/key.c
@@ -2459,7 +2459,9 @@ key_spdexpire(struct secpolicy *sp)
 	mtod(result, struct sadb_msg *)->sadb_msg_len =
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
-	return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
+	error = key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
+	crit_exit();
+	return error;
 
  fail:
 	if (result)
diff --git a/sys/netproto/ipsec/xform_ah.c b/sys/netproto/ipsec/xform_ah.c
index f92e7ab..512211a 100644
--- a/sys/netproto/ipsec/xform_ah.c
+++ b/sys/netproto/ipsec/xform_ah.c
@@ -770,8 +770,11 @@ ah_input_cb(struct cryptop *crp)
 		if (sav->tdb_cryptoid != 0)
 			sav->tdb_cryptoid = crp->crp_sid;
 
-		if (crp->crp_etype == EAGAIN)
-			return crypto_dispatch(crp);
+		if (crp->crp_etype == EAGAIN) {
+			error = crypto_dispatch(crp);
+			crit_exit();
+			return(error);
+		}
 
 		ahstat.ahs_noxform++;
 		DPRINTF(("ah_input_cb: crypto error %d\n", crp->crp_etype));
diff --git a/sys/vfs/hammer2/hammer2_vfsops.c b/sys/vfs/hammer2/hammer2_vfsops.c
index fde2052..c2fdb42 100644
--- a/sys/vfs/hammer2/hammer2_vfsops.c
+++ b/sys/vfs/hammer2/hammer2_vfsops.c
@@ -578,6 +578,7 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
 			++hmp->pmp_count;
 			hammer2_vfs_unmount_hmp1(mp, hmp);
 			hammer2_vfs_unmount_hmp2(mp, hmp);
+			lockmgr(&hammer2_mntlk, LK_RELEASE);
 			hammer2_vfs_unmount(mp, MNT_FORCE);
 			return error;
 		}
@@ -623,6 +624,7 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
 			++hmp->pmp_count;
 			hammer2_vfs_unmount_hmp1(mp, hmp);
 			hammer2_vfs_unmount_hmp2(mp, hmp);
+			lockmgr(&hammer2_mntlk, LK_RELEASE);
 			hammer2_vfs_unmount(mp, MNT_FORCE);
 			return EINVAL;
 		}
diff --git a/sys/vfs/nfs/nfs_vnops.c b/sys/vfs/nfs/nfs_vnops.c
index 688d28e..64f891c 100644
--- a/sys/vfs/nfs/nfs_vnops.c
+++ b/sys/vfs/nfs/nfs_vnops.c
@@ -541,8 +541,10 @@ nfs_open(struct vop_open_args *ap)
 		np->n_attrstamp = 0;
 		if (vp->v_type == VDIR) {
 			error = nfs_vinvalbuf(vp, V_SAVE, 1);
-			if (error == EINTR)
+			if (error == EINTR) {
+				lwkt_reltoken(&nmp->nm_token);
 				return (error);
+			}
 			nfs_invaldir(vp);
 		}
 	}
@@ -810,8 +812,10 @@ again:
 		 */
 		if (np->n_flag & NRMODIFIED)
 			error = nfs_vinvalbuf(vp, V_SAVE, 1);
-		if (error == EINTR)
+		if (error == EINTR) {
+			lwkt_reltoken(&nmp->nm_token);
 			return (error);
+		}
 		if (error == 0) {
 			if (vap->va_mtime.tv_sec != VNOVAL) {
 				np->n_mtime = vap->va_mtime.tv_sec;
-- 
1.9.3

