
Property changes on: sys
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/powerpc/include/atomic.h
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/powerpc/include/atomic.h:r180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/conf
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/conf:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/nlm
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/nlm:r180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/kern
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/kern:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365

Index: sys/kern/subr_witness.c
===================================================================
--- sys/kern/subr_witness.c	(revision 181343)
+++ sys/kern/subr_witness.c	(working copy)
@@ -313,7 +313,7 @@
 	/*
 	 * Multicast - protocol locks before interface locks, after UDP locks.
 	 */
-	{ "udpinp", &lock_class_mtx_sleep },
+	{ "udpinp", &lock_class_rw },
 	{ "in_multi_mtx", &lock_class_mtx_sleep },
 	{ "igmp_mtx", &lock_class_mtx_sleep },
 	{ "if_addr_mtx", &lock_class_mtx_sleep },
@@ -327,15 +327,15 @@
 	/*
 	 * UDP/IP
 	 */
-	{ "udp", &lock_class_mtx_sleep },
-	{ "udpinp", &lock_class_mtx_sleep },
+	{ "udp", &lock_class_rw },
+	{ "udpinp", &lock_class_rw },
 	{ "so_snd", &lock_class_mtx_sleep },
 	{ NULL, NULL },
 	/*
 	 * TCP/IP
 	 */
-	{ "tcp", &lock_class_mtx_sleep },
-	{ "tcpinp", &lock_class_mtx_sleep },
+	{ "tcp", &lock_class_rw },
+	{ "tcpinp", &lock_class_rw },
 	{ "so_snd", &lock_class_mtx_sleep },
 	{ NULL, NULL },
 	/*

Property changes on: sys/cam/scsi
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/cam/scsi:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/boot/forth/support.4th
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/boot/forth/support.4th:r180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365

Index: sys/netinet/tcp_input.c
===================================================================
--- sys/netinet/tcp_input.c	(revision 181343)
+++ sys/netinet/tcp_input.c	(working copy)
@@ -477,7 +477,7 @@
 		rstreason = BANDLIM_RST_CLOSEDPORT;
 		goto dropwithreset;
 	}
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 
 #ifdef IPSEC
 #ifdef INET6
@@ -534,7 +534,7 @@
 	}
 
 #ifdef MAC
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 	if (mac_check_inpcb_deliver(inp, m))
 		goto dropunlock;
 #endif
@@ -632,9 +632,9 @@
 			 * Unlock the listen socket, lock the newly
 			 * created socket and update the tp variable.
 			 */
-			INP_UNLOCK(inp);	/* listen socket */
+			INP_WUNLOCK(inp);	/* listen socket */
 			inp = sotoinpcb(so);
-			INP_LOCK(inp);		/* new connection */
+			INP_WLOCK(inp);		/* new connection */
 			tp = intotcpcb(inp);
 			KASSERT(tp->t_state == TCPS_SYN_RECEIVED,
 			    ("%s: ", __func__));
@@ -854,7 +854,7 @@
 dropunlock:
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
 	if (inp != NULL)
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 drop:
 	INP_INFO_UNLOCK_ASSERT(&tcbinfo);
@@ -887,7 +887,7 @@
 	thflags = th->th_flags;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	KASSERT(tp->t_state > TCPS_LISTEN, ("%s: TCPS_LISTEN",
 	    __func__));
 	KASSERT(tp->t_state != TCPS_TIME_WAIT, ("%s: TCPS_TIME_WAIT",
@@ -1331,7 +1331,7 @@
 
 		KASSERT(headlocked, ("%s: trimthenstep6: head not locked",
 		    __func__));
-		INP_LOCK_ASSERT(tp->t_inpcb);
+		INP_WLOCK_ASSERT(tp->t_inpcb);
 
 		/*
 		 * Advance th->th_seq to correspond to first data byte.
@@ -1939,7 +1939,7 @@
 process_ACK:
 		KASSERT(headlocked, ("%s: process_ACK: head not locked",
 		    __func__));
-		INP_LOCK_ASSERT(tp->t_inpcb);
+		INP_WLOCK_ASSERT(tp->t_inpcb);
 
 		acked = th->th_ack - tp->snd_una;
 		tcpstat.tcps_rcvackpack++;
@@ -2122,7 +2122,7 @@
 
 step6:
 	KASSERT(headlocked, ("%s: step6: head not locked", __func__));
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	/*
 	 * Update window information.
@@ -2208,7 +2208,7 @@
 	}
 dodata:							/* XXX */
 	KASSERT(headlocked, ("%s: dodata: head not locked", __func__));
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	/*
 	 * Process the segment text, merging it into the TCP sequencing queue,
@@ -2351,12 +2351,12 @@
 	KASSERT(headlocked == 0, ("%s: check_delack: head locked",
 	    __func__));
 	INP_INFO_UNLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	if (tp->t_flags & TF_DELACK) {
 		tp->t_flags &= ~TF_DELACK;
 		tcp_timer_activate(tp, TT_DELACK, tcp_delacktime);
 	}
-	INP_UNLOCK(tp->t_inpcb);
+	INP_WUNLOCK(tp->t_inpcb);
 	return;
 
 dropafterack:
@@ -2391,7 +2391,7 @@
 	INP_INFO_WUNLOCK(&tcbinfo);
 	tp->t_flags |= TF_ACKNOW;
 	(void) tcp_output(tp);
-	INP_UNLOCK(tp->t_inpcb);
+	INP_WUNLOCK(tp->t_inpcb);
 	m_freem(m);
 	return;
 
@@ -2401,7 +2401,7 @@
 	tcp_dropwithreset(m, th, tp, tlen, rstreason);
 
 	if (tp != NULL)
-		INP_UNLOCK(tp->t_inpcb);
+		INP_WUNLOCK(tp->t_inpcb);
 	if (headlocked)
 		INP_INFO_WUNLOCK(&tcbinfo);
 	return;
@@ -2416,7 +2416,7 @@
 			  &tcp_savetcp, 0);
 #endif
 	if (tp != NULL)
-		INP_UNLOCK(tp->t_inpcb);
+		INP_WUNLOCK(tp->t_inpcb);
 	if (headlocked)
 		INP_INFO_WUNLOCK(&tcbinfo);
 	m_freem(m);
@@ -2438,7 +2438,7 @@
 #endif
 
 	if (tp != NULL) {
-		INP_LOCK_ASSERT(tp->t_inpcb);
+		INP_WLOCK_ASSERT(tp->t_inpcb);
 	}
 
 	/* Don't bother if destination was broadcast/multicast. */
@@ -2590,7 +2590,7 @@
 			char *cp = mtod(m, caddr_t) + cnt;
 			struct tcpcb *tp = sototcpcb(so);
 
-			INP_LOCK_ASSERT(tp->t_inpcb);
+			INP_WLOCK_ASSERT(tp->t_inpcb);
 
 			tp->t_iobc = *cp;
 			tp->t_oobflags |= TCPOOB_HAVEDATA;
@@ -2617,7 +2617,7 @@
 {
 	int delta;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	tcpstat.tcps_rttupdated++;
 	tp->t_rttupdated++;
@@ -2737,7 +2737,7 @@
 	const size_t min_protoh = sizeof(struct tcpiphdr);
 #endif
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	/* Initialize. */
 #ifdef INET6
@@ -3007,7 +3007,7 @@
 	tcp_seq onxt = tp->snd_nxt;
 	u_long  ocwnd = tp->snd_cwnd;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	tcp_timer_activate(tp, TT_REXMT, 0);
 	tp->t_rtttime = 0;
Index: sys/netinet/tcp_subr.c
===================================================================
--- sys/netinet/tcp_subr.c	(revision 181343)
+++ sys/netinet/tcp_subr.c	(working copy)
@@ -332,7 +332,7 @@
 {
 	struct tcphdr *th = (struct tcphdr *)tcp_ptr;
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 #ifdef INET6
 	if ((inp->inp_vflag & INP_IPV6) != 0) {
@@ -434,7 +434,7 @@
 	if (tp != NULL) {
 		inp = tp->t_inpcb;
 		KASSERT(inp != NULL, ("tcp control block w/o inpcb"));
-		INP_LOCK_ASSERT(inp);
+		INP_WLOCK_ASSERT(inp);
 	} else
 		inp = NULL;
 
@@ -525,7 +525,7 @@
 		 * Packet is associated with a socket, so allow the
 		 * label of the response to reflect the socket label.
 		 */
-		INP_LOCK_ASSERT(inp);
+		INP_WLOCK_ASSERT(inp);
 		mac_create_mbuf_from_inpcb(inp, m);
 	} else {
 		/*
@@ -648,7 +648,7 @@
 	struct socket *so = tp->t_inpcb->inp_socket;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	if (TCPS_HAVERCVDSYN(tp->t_state)) {
 		tp->t_state = TCPS_CLOSED;
@@ -672,7 +672,7 @@
 	int isipv6 = (inp->inp_vflag & INP_IPV6) != 0;
 #endif /* INET6 */
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	/*
 	 * Make sure that all of our timers are stopped before we
@@ -770,7 +770,7 @@
 	struct socket *so;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	/* Notify any offload devices of listener close */
 	if (tp->t_state == TCPS_LISTEN)
@@ -784,7 +784,7 @@
 		KASSERT(so->so_state & SS_PROTOREF,
 		    ("tcp_close: !SS_PROTOREF"));
 		inp->inp_vflag &= ~INP_SOCKREF;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		ACCEPT_LOCK();
 		SOCK_LOCK(so);
 		so->so_state &= ~SS_PROTOREF;
@@ -815,7 +815,7 @@
 		LIST_FOREACH(inpb, tcbinfo.ipi_listhead, inp_list) {
 			if (inpb->inp_vflag & INP_TIMEWAIT)
 				continue;
-			INP_LOCK(inpb);
+			INP_WLOCK(inpb);
 			if ((tcpb = intotcpcb(inpb)) != NULL) {
 				while ((te = LIST_FIRST(&tcpb->t_segq))
 			            != NULL) {
@@ -827,7 +827,7 @@
 				}
 				tcp_clean_sackreport(tcpb);
 			}
-			INP_UNLOCK(inpb);
+			INP_WUNLOCK(inpb);
 		}
 		INP_INFO_RUNLOCK(&tcbinfo);
 	}
@@ -847,7 +847,7 @@
 	struct tcpcb *tp;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if ((inp->inp_vflag & INP_TIMEWAIT) ||
 	    (inp->inp_vflag & INP_DROPPED))
@@ -942,7 +942,7 @@
 	INP_INFO_RLOCK(&tcbinfo);
 	for (inp = LIST_FIRST(tcbinfo.ipi_listhead), i = 0; inp != NULL && i
 	    < n; inp = LIST_NEXT(inp, inp_list)) {
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		if (inp->inp_gencnt <= gencnt) {
 			/*
 			 * XXX: This use of cr_cansee(), introduced with
@@ -961,7 +961,7 @@
 			if (error == 0)
 				inp_list[i++] = inp;
 		}
-		INP_UNLOCK(inp);
+		INP_RUNLOCK(inp);
 	}
 	INP_INFO_RUNLOCK(&tcbinfo);
 	n = i;
@@ -969,7 +969,7 @@
 	error = 0;
 	for (i = 0; i < n; i++) {
 		inp = inp_list[i];
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		if (inp->inp_gencnt <= gencnt) {
 			struct xtcpcb xt;
 			void *inp_ppcb;
@@ -993,10 +993,10 @@
 				xt.xt_socket.xso_protocol = IPPROTO_TCP;
 			}
 			xt.xt_inp.inp_gencnt = inp->inp_gencnt;
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			error = SYSCTL_OUT(req, &xt, sizeof xt);
 		} else
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 	
 	}
 	if (!error) {
@@ -1038,23 +1038,21 @@
 	INP_INFO_RLOCK(&tcbinfo);
 	inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
 	    addrs[0].sin_addr, addrs[0].sin_port, 0, NULL);
-	if (inp == NULL) {
+	if (inp != NULL) {
+		INP_RLOCK(inp);
+		INP_INFO_RUNLOCK(&tcbinfo);
+		if (inp->inp_socket == NULL)
+			error = ENOENT;
+		if (error == 0)
+			error = cr_canseesocket(req->td->td_ucred,
+			    inp->inp_socket);
+		if (error == 0)
+			cru2x(inp->inp_socket->so_cred, &xuc);
+		INP_RUNLOCK(inp);
+	} else {
+		INP_INFO_RUNLOCK(&tcbinfo);
 		error = ENOENT;
-		goto outunlocked;
 	}
-	INP_LOCK(inp);
-	if (inp->inp_socket == NULL) {
-		error = ENOENT;
-		goto out;
-	}
-	error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
-	if (error)
-		goto out;
-	cru2x(inp->inp_socket->so_cred, &xuc);
-out:
-	INP_UNLOCK(inp);
-outunlocked:
-	INP_INFO_RUNLOCK(&tcbinfo);
 	if (error == 0)
 		error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 	return (error);
@@ -1102,23 +1100,21 @@
 		inp = in6_pcblookup_hash(&tcbinfo,
 			&addrs[1].sin6_addr, addrs[1].sin6_port,
 			&addrs[0].sin6_addr, addrs[0].sin6_port, 0, NULL);
-	if (inp == NULL) {
+	if (inp != NULL) {
+		INP_RLOCK(inp);
+		INP_INFO_RUNLOCK(&tcbinfo);
+		if (inp->inp_socket == NULL)
+			error = ENOENT;
+		if (error == 0)
+			error = cr_canseesocket(req->td->td_ucred,
+			    inp->inp_socket);
+		if (error == 0)
+			cru2x(inp->inp_socket->so_cred, &xuc);
+		INP_RUNLOCK(inp);
+	} else {
+		INP_INFO_RUNLOCK(&tcbinfo);
 		error = ENOENT;
-		goto outunlocked;
 	}
-	INP_LOCK(inp);
-	if (inp->inp_socket == NULL) {
-		error = ENOENT;
-		goto out;
-	}
-	error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
-	if (error)
-		goto out;
-	cru2x(inp->inp_socket->so_cred, &xuc);
-out:
-	INP_UNLOCK(inp);
-outunlocked:
-	INP_INFO_RUNLOCK(&tcbinfo);
 	if (error == 0)
 		error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 	return (error);
@@ -1181,7 +1177,7 @@
 		inp = in_pcblookup_hash(&tcbinfo, faddr, th->th_dport,
 		    ip->ip_src, th->th_sport, 0, NULL);
 		if (inp != NULL)  {
-			INP_LOCK(inp);
+			INP_WLOCK(inp);
 			if (!(inp->inp_vflag & INP_TIMEWAIT) &&
 			    !(inp->inp_vflag & INP_DROPPED) &&
 			    !(inp->inp_socket == NULL)) {
@@ -1232,7 +1228,7 @@
 				}
 			}
 			if (inp != NULL)
-				INP_UNLOCK(inp);
+				INP_WUNLOCK(inp);
 		} else {
 			inc.inc_fport = th->th_dport;
 			inc.inc_lport = th->th_sport;
@@ -1383,7 +1379,7 @@
 	u_int32_t md5_buffer[4];
 	tcp_seq new_isn;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	ISN_LOCK();
 	/* Seed if this is the first use, reseed if requested. */
@@ -1454,7 +1450,7 @@
 	struct tcpcb *tp;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if ((inp->inp_vflag & INP_TIMEWAIT) ||
 	    (inp->inp_vflag & INP_DROPPED))
@@ -1489,7 +1485,7 @@
 	int isipv6;
 #endif /* INET6 */
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 	if ((inp->inp_vflag & INP_TIMEWAIT) ||
 	    (inp->inp_vflag & INP_DROPPED))
 		return (inp);
@@ -1754,7 +1750,7 @@
 	u_long bwnd;
 	int save_ticks;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	/*
 	 * If inflight_enable is disabled in the middle of a tcp connection,
@@ -2047,7 +2043,7 @@
 		break;
 	}
 	if (inp != NULL) {
-		INP_LOCK(inp);
+		INP_WLOCK(inp);
 		if (inp->inp_vflag & INP_TIMEWAIT) {
 			/*
 			 * XXXRW: There currently exists a state where an
@@ -2059,15 +2055,15 @@
 			if (tw != NULL)
 				tcp_twclose(tw, 0);
 			else
-				INP_UNLOCK(inp);
+				INP_WUNLOCK(inp);
 		} else if (!(inp->inp_vflag & INP_DROPPED) &&
 			   !(inp->inp_socket->so_options & SO_ACCEPTCONN)) {
 			tp = intotcpcb(inp);
 			tp = tcp_drop(tp, ECONNABORTED);
 			if (tp != NULL)
-				INP_UNLOCK(inp);
+				INP_WUNLOCK(inp);
 		} else
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 	} else
 		error = ESRCH;
 	INP_INFO_WUNLOCK(&tcbinfo);
Index: sys/netinet/raw_ip.c
===================================================================
--- sys/netinet/raw_ip.c	(revision 181343)
+++ sys/netinet/raw_ip.c	(working copy)
@@ -148,14 +148,13 @@
 		NULL, EVENTHANDLER_PRI_ANY);
 }
 
-static struct	sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
-
 static int
-rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n)
+rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
+    struct sockaddr_in *ripsrc)
 {
 	int policyfail = 0;
 
-	INP_LOCK_ASSERT(last);
+	INP_RLOCK_ASSERT(last);
 
 #ifdef IPSEC
 	/* check AH/ESP integrity. */
@@ -180,7 +179,7 @@
 			ip_savecontrol(last, &opts, ip, n);
 		SOCKBUF_LOCK(&so->so_rcv);
 		if (sbappendaddr_locked(&so->so_rcv,
-		    (struct sockaddr *)&ripsrc, n, opts) == 0) {
+		    (struct sockaddr *)ripsrc, n, opts) == 0) {
 			/* should notify about lost packet */
 			m_freem(n);
 			if (opts)
@@ -204,15 +203,19 @@
 	struct ip *ip = mtod(m, struct ip *);
 	int proto = ip->ip_p;
 	struct inpcb *inp, *last;
+	struct sockaddr_in ripsrc;
 
-	INP_INFO_RLOCK(&ripcbinfo);
+	bzero(&ripsrc, sizeof(ripsrc));
+	ripsrc.sin_len = sizeof(ripsrc);
+	ripsrc.sin_family = AF_INET;
 	ripsrc.sin_addr = ip->ip_src;
 	last = NULL;
+	INP_INFO_RLOCK(&ripcbinfo);
 	LIST_FOREACH(inp, &ripcb, inp_list) {
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		if (inp->inp_ip_p && inp->inp_ip_p != proto) {
 	docontinue:
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			continue;
 		}
 #ifdef INET6
@@ -234,16 +237,16 @@
 
 			n = m_copy(m, 0, (int)M_COPYALL);
 			if (n != NULL)
-				(void) rip_append(last, ip, n);
+				(void) rip_append(last, ip, n, &ripsrc);
 			/* XXX count dropped packet */
-			INP_UNLOCK(last);
+			INP_RUNLOCK(last);
 		}
 		last = inp;
 	}
 	if (last != NULL) {
-		if (rip_append(last, ip, m) != 0)
+		if (rip_append(last, ip, m, &ripsrc) != 0)
 			ipstat.ips_delivered--;
-		INP_UNLOCK(last);
+		INP_RUNLOCK(last);
 	} else {
 		m_freem(m);
 		ipstat.ips_noproto++;
@@ -278,7 +281,7 @@
 		if (m == NULL)
 			return(ENOBUFS);
 
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		ip = mtod(m, struct ip *);
 		ip->ip_tos = inp->inp_ip_tos;
 		if (inp->inp_flags & INP_DONTFRAG)
@@ -299,12 +302,12 @@
 			m_freem(m);
 			return(EMSGSIZE);
 		}
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		ip = mtod(m, struct ip *);
 		if (jailed(inp->inp_socket->so_cred)) {
 			if (ip->ip_src.s_addr !=
 			    htonl(prison_getip(inp->inp_socket->so_cred))) {
-				INP_UNLOCK(inp);
+				INP_RUNLOCK(inp);
 				m_freem(m);
 				return (EPERM);
 			}
@@ -315,7 +318,7 @@
 		     && inp->inp_options)
 		    || (ip->ip_len > m->m_pkthdr.len)
 		    || (ip->ip_len < (ip->ip_hl << 2))) {
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			m_freem(m);
 			return EINVAL;
 		}
@@ -335,7 +338,7 @@
 
 	error = ip_output(m, inp->inp_options, NULL, flags,
 	    inp->inp_moptions, inp);
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 	return error;
 }
 
@@ -602,7 +605,7 @@
 	inp->inp_vflag |= INP_IPV4;
 	inp->inp_ip_p = proto;
 	inp->inp_ip_ttl = ip_defttl;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return 0;
 }
 
@@ -617,7 +620,7 @@
 	    ("rip_detach: not closed"));
 
 	INP_INFO_WLOCK(&ripcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (so == ip_mrouter && ip_mrouter_done)
 		ip_mrouter_done();
 	if (ip_rsvp_force_done)
@@ -633,7 +636,7 @@
 rip_dodisconnect(struct socket *so, struct inpcb *inp)
 {
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	inp->inp_faddr.s_addr = INADDR_ANY;
 	SOCK_LOCK(so);
@@ -650,9 +653,9 @@
 	KASSERT(inp != NULL, ("rip_abort: inp == NULL"));
 
 	INP_INFO_WLOCK(&ripcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	rip_dodisconnect(so, inp);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&ripcbinfo);
 }
 
@@ -665,9 +668,9 @@
 	KASSERT(inp != NULL, ("rip_close: inp == NULL"));
 
 	INP_INFO_WLOCK(&ripcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	rip_dodisconnect(so, inp);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&ripcbinfo);
 }
 
@@ -682,9 +685,9 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("rip_disconnect: inp == NULL"));
 	INP_INFO_WLOCK(&ripcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	rip_dodisconnect(so, inp);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&ripcbinfo);
 	return (0);
 }
@@ -715,9 +718,9 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("rip_bind: inp == NULL"));
 	INP_INFO_WLOCK(&ripcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	inp->inp_laddr = addr->sin_addr;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&ripcbinfo);
 	return 0;
 }
@@ -738,10 +741,10 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("rip_connect: inp == NULL"));
 	INP_INFO_WLOCK(&ripcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	inp->inp_faddr = addr->sin_addr;
 	soisconnected(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&ripcbinfo);
 	return 0;
 }
@@ -753,9 +756,9 @@
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("rip_shutdown: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	socantsendmore(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return 0;
 }
 
@@ -828,17 +831,17 @@
 	inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
 	if (inp_list == 0)
 		return ENOMEM;
-	
+
 	INP_INFO_RLOCK(&ripcbinfo);
 	for (inp = LIST_FIRST(ripcbinfo.ipi_listhead), i = 0; inp && i < n;
 	     inp = LIST_NEXT(inp, inp_list)) {
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		if (inp->inp_gencnt <= gencnt &&
 		    cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0) {
 			/* XXX held references? */
 			inp_list[i++] = inp;
 		}
-		INP_UNLOCK(inp);
+		INP_RUNLOCK(inp);
 	}
 	INP_INFO_RUNLOCK(&ripcbinfo);
 	n = i;
@@ -846,7 +849,7 @@
 	error = 0;
 	for (i = 0; i < n; i++) {
 		inp = inp_list[i];
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		if (inp->inp_gencnt <= gencnt) {
 			struct xinpcb xi;
 			bzero(&xi, sizeof(xi));
@@ -855,10 +858,10 @@
 			bcopy(inp, &xi.xi_inp, sizeof *inp);
 			if (inp->inp_socket)
 				sotoxsocket(inp->inp_socket, &xi.xi_socket);
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			error = SYSCTL_OUT(req, &xi, sizeof xi);
 		} else
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 	}
 	if (!error) {
 		/*
Index: sys/netinet/tcp_reass.c
===================================================================
--- sys/netinet/tcp_reass.c	(revision 181343)
+++ sys/netinet/tcp_reass.c	(working copy)
@@ -131,7 +131,7 @@
 	struct socket *so = tp->t_inpcb->inp_socket;
 	int flags;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	/*
 	 * XXX: tcp_reass() is rather inefficient with its data structures
Index: sys/netinet/ip_divert.c
===================================================================
--- sys/netinet/ip_divert.c	(revision 181343)
+++ sys/netinet/ip_divert.c	(working copy)
@@ -268,7 +268,7 @@
 	nport = htons((u_int16_t)divert_info(mtag));
 	INP_INFO_RLOCK(&divcbinfo);
 	LIST_FOREACH(inp, &divcb, inp_list) {
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		/* XXX why does only one socket match? */
 		if (inp->inp_lport == nport) {
 			sa = inp->inp_socket;
@@ -280,10 +280,10 @@
 				sa = NULL;	/* force mbuf reclaim below */
 			} else
 				sorwakeup_locked(sa);
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			break;
 		}
-		INP_UNLOCK(inp);
+		INP_RUNLOCK(inp);
 	}
 	INP_INFO_RUNLOCK(&divcbinfo);
 	if (sa == NULL) {
@@ -356,7 +356,7 @@
 		dt->info |= IP_FW_DIVERT_OUTPUT_FLAG;
 		INP_INFO_WLOCK(&divcbinfo);
 		inp = sotoinpcb(so);
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		/*
 		 * Don't allow both user specified and setsockopt options,
 		 * and don't allow packet length sizes that will crash
@@ -364,7 +364,7 @@
 		if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options) ||
 		     ((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) {
 			error = EINVAL;
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			INP_INFO_WUNLOCK(&divcbinfo);
 			m_freem(m);
 		} else {
@@ -405,7 +405,7 @@
 				if (options == NULL)
 					error = ENOBUFS;
 			}
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			INP_INFO_WUNLOCK(&divcbinfo);
 			if (error == ENOBUFS) {
 				m_freem(m);
@@ -480,7 +480,7 @@
 	inp->inp_ip_p = proto;
 	inp->inp_vflag |= INP_IPV4;
 	inp->inp_flags |= INP_HDRINCL;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return 0;
 }
 
@@ -492,7 +492,7 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("div_detach: inp == NULL"));
 	INP_INFO_WLOCK(&divcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	in_pcbdetach(inp);
 	in_pcbfree(inp);
 	INP_INFO_WUNLOCK(&divcbinfo);
@@ -517,9 +517,9 @@
 		return EAFNOSUPPORT;
 	((struct sockaddr_in *)nam)->sin_addr.s_addr = INADDR_ANY;
 	INP_INFO_WLOCK(&divcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	error = in_pcbbind(inp, nam, td->td_ucred);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&divcbinfo);
 	return error;
 }
@@ -531,9 +531,9 @@
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("div_shutdown: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	socantsendmore(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return 0;
 }
 
@@ -615,11 +615,11 @@
 	INP_INFO_RLOCK(&divcbinfo);
 	for (inp = LIST_FIRST(divcbinfo.ipi_listhead), i = 0; inp && i < n;
 	     inp = LIST_NEXT(inp, inp_list)) {
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		if (inp->inp_gencnt <= gencnt &&
 		    cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
 			inp_list[i++] = inp;
-		INP_UNLOCK(inp);
+		INP_RUNLOCK(inp);
 	}
 	INP_INFO_RUNLOCK(&divcbinfo);
 	n = i;
@@ -627,7 +627,7 @@
 	error = 0;
 	for (i = 0; i < n; i++) {
 		inp = inp_list[i];
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		if (inp->inp_gencnt <= gencnt) {
 			struct xinpcb xi;
 			bzero(&xi, sizeof(xi));
@@ -636,10 +636,10 @@
 			bcopy(inp, &xi.xi_inp, sizeof *inp);
 			if (inp->inp_socket)
 				sotoxsocket(inp->inp_socket, &xi.xi_socket);
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			error = SYSCTL_OUT(req, &xi, sizeof xi);
 		} else
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 	}
 	if (!error) {
 		/*
Index: sys/netinet/tcp_timer.c
===================================================================
--- sys/netinet/tcp_timer.c	(revision 181343)
+++ sys/netinet/tcp_timer.c	(working copy)
@@ -166,11 +166,11 @@
 		INP_INFO_RUNLOCK(&tcbinfo);
 		return;
 	}
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	INP_INFO_RUNLOCK(&tcbinfo);
 	if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_delack)
 	    || !callout_active(&tp->t_timers->tt_delack)) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		return;
 	}
 	callout_deactivate(&tp->t_timers->tt_delack);
@@ -178,7 +178,7 @@
 	tp->t_flags |= TF_ACKNOW;
 	tcpstat.tcps_delack++;
 	(void) tcp_output(tp);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 }
 
 void
@@ -208,11 +208,11 @@
 		INP_INFO_WUNLOCK(&tcbinfo);
 		return;
 	}
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	tcp_free_sackholes(tp);
 	if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_2msl) ||
 	    !callout_active(&tp->t_timers->tt_2msl)) {
-		INP_UNLOCK(tp->t_inpcb);
+		INP_WUNLOCK(tp->t_inpcb);
 		INP_INFO_WUNLOCK(&tcbinfo);
 		return;
 	}
@@ -247,7 +247,7 @@
 			  PRU_SLOWTIMO);
 #endif
 	if (tp != NULL)
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 }
 
@@ -276,10 +276,10 @@
 		INP_INFO_WUNLOCK(&tcbinfo);
 		return;
 	}
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_keep)
 	    || !callout_active(&tp->t_timers->tt_keep)) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&tcbinfo);
 		return;
 	}
@@ -324,7 +324,7 @@
 		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
 			  PRU_SLOWTIMO);
 #endif
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 	return;
 
@@ -338,7 +338,7 @@
 			  PRU_SLOWTIMO);
 #endif
 	if (tp != NULL)
-		INP_UNLOCK(tp->t_inpcb);
+		INP_WUNLOCK(tp->t_inpcb);
 	INP_INFO_WUNLOCK(&tcbinfo);
 }
 
@@ -366,10 +366,10 @@
 		INP_INFO_WUNLOCK(&tcbinfo);
 		return;
 	}
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_persist)
 	    || !callout_active(&tp->t_timers->tt_persist)) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&tcbinfo);
 		return;
 	}
@@ -404,7 +404,7 @@
 		tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO);
 #endif
 	if (tp != NULL)
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 }
 
@@ -435,10 +435,10 @@
 		INP_INFO_WUNLOCK(&tcbinfo);
 		return;
 	}
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_rexmt)
 	    || !callout_active(&tp->t_timers->tt_rexmt)) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&tcbinfo);
 		return;
 	}
@@ -560,7 +560,7 @@
 			  PRU_SLOWTIMO);
 #endif
 	if (tp != NULL)
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 	if (headlocked)
 		INP_INFO_WUNLOCK(&tcbinfo);
 }
Index: sys/netinet/tcp_sack.c
===================================================================
--- sys/netinet/tcp_sack.c	(revision 181343)
+++ sys/netinet/tcp_sack.c	(working copy)
@@ -160,7 +160,7 @@
 	struct sackblk head_blk, saved_blks[MAX_SACK_BLKS];
 	int num_head, num_saved, i;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	/* Check arguments. */
 	KASSERT(SEQ_LT(rcv_start, rcv_end), ("rcv_start < rcv_end"));
@@ -240,7 +240,7 @@
 {
 	int i;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	tp->rcv_numsacks = 0;
 	for (i = 0; i < MAX_SACK_BLKS; i++)
 		tp->sackblks[i].start = tp->sackblks[i].end=0;
@@ -347,7 +347,7 @@
 	struct sackblk sack, sack_blocks[TCP_MAX_SACK + 1], *sblkp;
 	int i, j, num_sack_blks;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	num_sack_blks = 0;
 	/*
@@ -544,7 +544,7 @@
 {
 	struct sackhole *q;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	while ((q = TAILQ_FIRST(&tp->snd_holes)) != NULL)
 		tcp_sackhole_remove(tp, q);
 	tp->sackhint.sack_bytes_rexmit = 0;
@@ -567,7 +567,7 @@
 {
 	int num_segs = 1;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	tcp_timer_activate(tp, TT_REXMT, 0);
 	tp->t_rtttime = 0;
 	/* Send one or 2 segments based on how much new data was acked. */
@@ -591,7 +591,7 @@
 {
 	struct sackhole *p;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	*sack_bytes_rexmt = 0;
 	TAILQ_FOREACH(p, &tp->snd_holes, scblink) {
 		if (SEQ_LT(p->rxmit, p->end)) {
@@ -629,7 +629,7 @@
 {
 	struct sackhole *hole = NULL;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	*sack_bytes_rexmt = tp->sackhint.sack_bytes_rexmit;
 	hole = tp->sackhint.nexthole;
 	if (hole == NULL || SEQ_LT(hole->rxmit, hole->end))
@@ -654,7 +654,7 @@
 {
 	struct sackhole *p, *cur = TAILQ_FIRST(&tp->snd_holes);
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	if (cur == NULL)
 		return; /* No holes */
 	if (SEQ_GEQ(tp->snd_nxt, tp->snd_fack))
Index: sys/netinet/in_pcb.c
===================================================================
--- sys/netinet/in_pcb.c	(revision 181343)
+++ sys/netinet/in_pcb.c	(working copy)
@@ -219,9 +219,9 @@
 	if (ip6_auto_flowlabel)
 		inp->inp_flags |= IN6P_AUTOFLOWLABEL;
 #endif
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
-	
+
 #if defined(IPSEC) || defined(MAC)
 out:
 	if (error != 0)
@@ -236,7 +236,7 @@
 	int anonport, error;
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY)
 		return (EINVAL);
@@ -279,7 +279,11 @@
 	int error, prison = 0;
 	int dorandom;
 
-	INP_INFO_WLOCK_ASSERT(pcbinfo);
+	/*
+	 * Because no actual state changes occur here, a global write lock on
+	 * the pcbinfo isn't required.
+	 */
+	INP_INFO_LOCK_ASSERT(pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
 	if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */
@@ -504,7 +508,7 @@
 	int anonport, error;
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	lport = inp->inp_lport;
 	laddr = inp->inp_laddr.s_addr;
@@ -566,7 +570,11 @@
 	u_short lport, fport;
 	int error;
 
-	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
+	/*
+	 * Because a global state change doesn't actually occur here, a read
+	 * lock is sufficient.
+	 */
+	INP_INFO_LOCK_ASSERT(inp->inp_pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
 	if (oinpp != NULL)
@@ -621,7 +629,7 @@
 		/*
 		 * If we found a route, use the address corresponding to
 		 * the outgoing interface.
-		 * 
+		 *
 		 * Otherwise assume faddr is reachable on a directly connected
 		 * network and try to find a corresponding interface to take
 		 * the source address from.
@@ -686,7 +694,7 @@
 {
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	inp->inp_faddr.s_addr = INADDR_ANY;
 	inp->inp_fport = 0;
@@ -715,8 +723,9 @@
 	struct inpcbinfo *ipi = inp->inp_pcbinfo;
 
 	KASSERT(inp->inp_socket == NULL, ("in_pcbfree: inp_socket != NULL"));
+
 	INP_INFO_WLOCK_ASSERT(ipi);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 #ifdef IPSEC
 	ipsec4_delete_pcbpolicy(inp);
@@ -728,11 +737,11 @@
 	if (inp->inp_moptions != NULL)
 		inp_freemoptions(inp->inp_moptions);
 	inp->inp_vflag = 0;
-	
+
 #ifdef MAC
 	mac_destroy_inpcb(inp);
 #endif
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	uma_zfree(ipi->ipi_zone, inp);
 }
 
@@ -747,7 +756,7 @@
 {
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	inp->inp_vflag |= INP_DROPPED;
 	if (inp->inp_lport) {
@@ -791,10 +800,10 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("in_getsockaddr: inp == NULL"));
 
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	port = inp->inp_lport;
 	addr = inp->inp_laddr;
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 
 	*nam = in_sockaddr(port, &addr);
 	return 0;
@@ -810,10 +819,10 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("in_getpeeraddr: inp == NULL"));
 
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	port = inp->inp_fport;
 	addr = inp->inp_faddr;
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 
 	*nam = in_sockaddr(port, &addr);
 	return 0;
@@ -827,20 +836,20 @@
 
 	INP_INFO_WLOCK(pcbinfo);
 	LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) {
-		INP_LOCK(inp);
+		INP_WLOCK(inp);
 #ifdef INET6
 		if ((inp->inp_vflag & INP_IPV4) == 0) {
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			continue;
 		}
 #endif
 		if (inp->inp_faddr.s_addr != faddr.s_addr ||
 		    inp->inp_socket == NULL) {
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			continue;
 		}
 		if ((*notify)(inp, errno))
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 	}
 	INP_INFO_WUNLOCK(pcbinfo);
 }
@@ -854,7 +863,7 @@
 
 	INP_INFO_RLOCK(pcbinfo);
 	LIST_FOREACH(inp, pcbinfo->ipi_listhead, inp_list) {
-		INP_LOCK(inp);
+		INP_WLOCK(inp);
 		imo = inp->inp_moptions;
 		if ((inp->inp_vflag & INP_IPV4) &&
 		    imo != NULL) {
@@ -880,7 +889,7 @@
 			}
 			imo->imo_num_memberships -= gap;
 		}
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 	}
 	INP_INFO_RUNLOCK(pcbinfo);
 }
@@ -901,7 +910,7 @@
 #endif
 	int wildcard;
 
-	INP_INFO_WLOCK_ASSERT(pcbinfo);
+	INP_INFO_LOCK_ASSERT(pcbinfo);
 
 	if (!wild_okay) {
 		struct inpcbhead *head;
@@ -1008,7 +1017,7 @@
 	struct inpcb *inp;
 	u_short fport = fport_arg, lport = lport_arg;
 
-	INP_INFO_RLOCK_ASSERT(pcbinfo);
+	INP_INFO_LOCK_ASSERT(pcbinfo);
 
 	/*
 	 * First look for an exact match.
@@ -1083,7 +1092,7 @@
 	u_int32_t hashkey_faddr;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 #ifdef INET6
 	if (inp->inp_vflag & INP_IPV6)
@@ -1137,7 +1146,7 @@
 	u_int32_t hashkey_faddr;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 #ifdef INET6
 	if (inp->inp_vflag & INP_IPV6)
@@ -1162,7 +1171,7 @@
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
 	if (inp->inp_lport) {
@@ -1192,11 +1201,11 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("in_pcbsosetlabel: so->so_pcb == NULL"));
 
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	SOCK_LOCK(so);
 	mac_inpcb_sosetlabel(so, inp);
 	SOCK_UNLOCK(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 #endif
 }
 
Index: sys/netinet/in_mcast.c
===================================================================
--- sys/netinet/in_mcast.c	(revision 181343)
+++ sys/netinet/in_mcast.c	(working copy)
@@ -653,7 +653,7 @@
 	}
 
 out_locked:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -669,11 +669,11 @@
 	struct in_mfilter	 *imfp;
 	size_t			  idx;
 
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_moptions != NULL)
 		return (inp->inp_moptions);
 
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 
 	imo = (struct ip_moptions *)malloc(sizeof(*imo), M_IPMOPTS,
 	    M_WAITOK);
@@ -700,7 +700,7 @@
 	}
 	imo->imo_mfilters = imfp;
 
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_moptions != NULL) {
 		free(imfp, M_IPMSOURCE);
 		free(immp, M_IPMOPTS);
@@ -764,12 +764,12 @@
 	int			 error;
 	size_t			 idx;
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	imo = inp->inp_moptions;
 	KASSERT(imo != NULL, ("%s: null ip_moptions", __func__));
 
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 
 	error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
 	    sizeof(struct __msfilterreq));
@@ -783,7 +783,7 @@
 	if (ifp == NULL)
 		return (EINVAL);
 
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 
 	/*
 	 * Lookup group on the socket.
@@ -791,7 +791,7 @@
 	gsa = (sockunion_t *)&msfr.msfr_group;
 	idx = imo_match_group(imo, ifp, &gsa->sa);
 	if (idx == -1 || imo->imo_mfilters == NULL) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		return (EADDRNOTAVAIL);
 	}
 
@@ -828,7 +828,7 @@
 		}
 	}
 
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 
 	if (tss != NULL) {
 		error = copyout(tss, msfr.msfr_srcs,
@@ -857,7 +857,7 @@
 	int			 error, optval;
 	u_char			 coptval;
 
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	imo = inp->inp_moptions;
 	/*
 	 * If socket is neither of type SOCK_RAW or SOCK_DGRAM,
@@ -866,7 +866,7 @@
 	if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_DIVERT ||
 	    (inp->inp_socket->so_proto->pr_type != SOCK_RAW &&
 	    inp->inp_socket->so_proto->pr_type != SOCK_DGRAM)) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		return (EOPNOTSUPP);
 	}
 
@@ -877,7 +877,7 @@
 			optval = imo->imo_multicast_vif;
 		else
 			optval = -1;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		error = sooptcopyout(sopt, &optval, sizeof(int));
 		break;
 
@@ -896,7 +896,7 @@
 				}
 			}
 		}
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) {
 			error = sooptcopyout(sopt, &mreqn,
 			    sizeof(struct ip_mreqn));
@@ -911,7 +911,7 @@
 			optval = coptval = IP_DEFAULT_MULTICAST_TTL;
 		else
 			optval = coptval = imo->imo_multicast_ttl;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		if (sopt->sopt_valsize == sizeof(u_char))
 			error = sooptcopyout(sopt, &coptval, sizeof(u_char));
 		else
@@ -923,7 +923,7 @@
 			optval = coptval = IP_DEFAULT_MULTICAST_LOOP;
 		else
 			optval = coptval = imo->imo_multicast_loop;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		if (sopt->sopt_valsize == sizeof(u_char))
 			error = sooptcopyout(sopt, &coptval, sizeof(u_char));
 		else
@@ -933,14 +933,14 @@
 	case IP_MSFILTER:
 		if (imo == NULL) {
 			error = EADDRNOTAVAIL;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 		} else {
 			error = inp_get_source_filters(inp, sopt);
 		}
 		break;
 
 	default:
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		error = ENOPROTOOPT;
 		break;
 	}
@@ -1195,14 +1195,14 @@
 			 * to prevent a lock order reversal.
 			 */
 			--imo->imo_num_memberships;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			in_delmulti(inm);
 			return (error);
 		}
 	}
 
 out_locked:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -1385,7 +1385,7 @@
 	imo->imo_num_memberships--;
 
 out_locked:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -1457,7 +1457,7 @@
 	imo = inp_findmoptions(inp);
 	imo->imo_multicast_ifp = ifp;
 	imo->imo_multicast_addr.s_addr = INADDR_ANY;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 
 	return (0);
 }
@@ -1548,7 +1548,7 @@
 		 * in order to satisfy a malloc request.
 		 * We will re-take it before changing socket state.
 		 */
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 #ifdef DIAGNOSTIC
 		if (bootverbose) {
 			printf("%s: loading %lu source list entries\n",
@@ -1649,7 +1649,7 @@
 		 * Re-take the inp lock; we are changing socket state.
 		 */
 		pkss = kss;
-		INP_LOCK(inp);
+		INP_WLOCK(inp);
 		for (i = 0; i < msfr.msfr_nsrcs; i++, pkss++) {
 			memcpy(&(pnims[i]->ims_addr), pkss,
 			    sizeof(struct sockaddr_storage));
@@ -1664,11 +1664,11 @@
 	/*
 	 * Update the filter mode on the socket before releasing the inpcb.
 	 */
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 	imf->imf_fmode = msfr.msfr_fmode;
 
 out_locked:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -1719,7 +1719,7 @@
 		}
 		imo = inp_findmoptions(inp);
 		imo->imo_multicast_vif = vifi;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		break;
 	}
 
@@ -1756,7 +1756,7 @@
 		}
 		imo = inp_findmoptions(inp);
 		imo->imo_multicast_ttl = ttl;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		break;
 	}
 
@@ -1785,7 +1785,7 @@
 		}
 		imo = inp_findmoptions(inp);
 		imo->imo_multicast_loop = !!loop;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		break;
 	}
 
Index: sys/netinet/in_pcb.h
===================================================================
--- sys/netinet/in_pcb.h	(revision 181343)
+++ sys/netinet/in_pcb.h	(working copy)
@@ -36,9 +36,14 @@
 #include <sys/queue.h>
 #include <sys/_lock.h>
 #include <sys/_mutex.h>
+#include <sys/_rwlock.h>
 
 #include <net/route.h>
 
+#ifdef _KERNEL
+#include <sys/rwlock.h>
+#endif
+
 #define	in6pcb		inpcb	/* for KAME src sync over BSD*'s */
 #define	in6p_sp		inp_sp	/* for KAME src sync over BSD*'s */
 struct inpcbpolicy;
@@ -110,17 +115,49 @@
 
 struct	icmp6_filter;
 
+/*-
+ * struct inpcb captures the network layer state for TCP, UDP, and raw IPv4
+ * and IPv6 sockets.  In the case of TCP, further per-connection state is
+ * hung off of inp_ppcb most of the time.  Almost all fields of struct inpcb
+ * are static after creation or protected by a per-inpcb rwlock, inp_lock.  A
+ * few fields also require the global pcbinfo lock for the inpcb to be held,
+ * when modified, such as the global connection lists and hashes, as well as
+ * binding information (which affects which hash a connection is on).  This
+ * model means that connections can be looked up without holding the
+ * per-connection lock, which is important for performance when attempting to
+ * find the connection for a packet given its IP and port tuple.  Writing to
+ * these fields that write locks be held on both the inpcb and global locks.
+ *
+ * Key:
+ * (c) - Constant after initialization
+ * (i) - Protected by the inpcb lock
+ * (p) - Protected by the pcbinfo lock for the inpcb
+ * (s) - Protected by another subsystem's locks
+ * (x) - Undefined locking
+ *
+ * A few other notes:
+ *
+ * When a read lock is held, stability of the field is guaranteed; to write
+ * to a field, a write lock must generally be held.
+ *
+ * netinet/netinet6-layer code should not assume that the inp_socket pointer
+ * is safe to dereference without inp_lock being held, even for protocols
+ * other than TCP (where the inpcb persists during TIMEWAIT even after the
+ * socket has been freed), or there may be close(2)-related races.
+ *
+ * The inp_vflag field is overloaded, and would otherwise ideally be (c).
+ */
 struct inpcb {
-	LIST_ENTRY(inpcb) inp_hash;	/* hash list */
-	LIST_ENTRY(inpcb) inp_list;	/* list for all PCBs of this proto */
-	void	*inp_ppcb;		/* pointer to per-protocol pcb */
-	struct	inpcbinfo *inp_pcbinfo;	/* PCB list info */
-	struct	socket *inp_socket;	/* back pointer to socket */
+	LIST_ENTRY(inpcb) inp_hash;	/* (i/p) hash list */
+	LIST_ENTRY(inpcb) inp_list;	/* (i/p) list for all PCBs for proto */
+	void	*inp_ppcb;		/* (i) pointer to per-protocol pcb */
+	struct	inpcbinfo *inp_pcbinfo;	/* (c) PCB list info */
+	struct	socket *inp_socket;	/* (i)  back pointer to socket */
 
-	u_int32_t	inp_flow;
-	int	inp_flags;		/* generic IP/datagram flags */
+	u_int32_t	inp_flow;	/* (i) IPv6 flow information */
+	int	inp_flags;		/* (i) generic IP/datagram flags */
 
-	u_char	inp_vflag;		/* IP version flag (v4/v6) */
+	u_char	inp_vflag;		/* (i) IP version flag (v4/v6) */
 #define	INP_IPV4	0x1
 #define	INP_IPV6	0x2
 #define	INP_IPV6PROTO	0x4		/* opened under IPv6 protocol */
@@ -128,24 +165,24 @@
 #define	INP_ONESBCAST	0x10		/* send all-ones broadcast */
 #define	INP_DROPPED	0x20		/* protocol drop flag */
 #define	INP_SOCKREF	0x40		/* strong socket reference */
-	u_char	inp_ip_ttl;		/* time to live proto */
-	u_char	inp_ip_p;		/* protocol proto */
-	u_char	inp_ip_minttl;		/* minimum TTL or drop */
-	uint32_t inp_ispare1;		/* connection id / queue id */
-	void	*inp_pspare[2];		/* rtentry / general use */
+	u_char	inp_ip_ttl;		/* (i) time to live proto */
+	u_char	inp_ip_p;		/* (c) protocol proto */
+	u_char	inp_ip_minttl;		/* (i) minimum TTL or drop */
+	uint32_t inp_ispare1;		/* (x) connection id / queue id */
+	void	*inp_pspare[2];		/* (x) rtentry / general use */
 
 	/* Local and foreign ports, local and foreign addr. */
 	struct	in_conninfo inp_inc;
 
-					/* list for this PCB's local port */
-	struct	label *inp_label;	/* MAC label */
-	struct	inpcbpolicy *inp_sp;    /* for IPSEC */
+					/* (i/p) list for PCB's local port */
+	struct	label *inp_label;	/* (i) MAC label */
+	struct	inpcbpolicy *inp_sp;    /* (s) for IPSEC */
 
 	/* Protocol-dependent part; options. */
 	struct {
-		u_char	inp4_ip_tos;		/* type of service proto */
-		struct	mbuf *inp4_options;	/* IP options */
-		struct	ip_moptions *inp4_moptions; /* IP multicast options */
+		u_char	inp4_ip_tos;		/* (i) type of service proto */
+		struct	mbuf *inp4_options;	/* (i) IP options */
+		struct	ip_moptions *inp4_moptions; /* (i) IP multicast options */
 	} inp_depend4;
 #define	inp_fport	inp_inc.inc_fport
 #define	inp_lport	inp_inc.inc_lport
@@ -155,23 +192,23 @@
 #define	inp_options	inp_depend4.inp4_options
 #define	inp_moptions	inp_depend4.inp4_moptions
 	struct {
-		/* IP options */
+		/* (i) IP options */
 		struct	mbuf *inp6_options;
-		/* IP6 options for outgoing packets */
+		/* (i) IP6 options for outgoing packets */
 		struct	ip6_pktopts *inp6_outputopts;
-		/* IP multicast options */
+		/* (i) IP multicast options */
 		struct	ip6_moptions *inp6_moptions;
-		/* ICMPv6 code type filter */
+		/* (i) ICMPv6 code type filter */
 		struct	icmp6_filter *inp6_icmp6filt;
-		/* IPV6_CHECKSUM setsockopt */
+		/* (i) IPV6_CHECKSUM setsockopt */
 		int	inp6_cksum;
 		short	inp6_hops;
 	} inp_depend6;
-	LIST_ENTRY(inpcb) inp_portlist;
-	struct	inpcbport *inp_phd;	/* head of this list */
+	LIST_ENTRY(inpcb) inp_portlist;	/* (i/p) */
+	struct	inpcbport *inp_phd;	/* (i/p) head of this list */
 #define inp_zero_size offsetof(struct inpcb, inp_gencnt)
-	inp_gen_t	inp_gencnt;	/* generation count of this instance */
-	struct mtx	inp_mtx;
+	inp_gen_t	inp_gencnt;	/* (c) generation count of this instance */
+	struct rwlock	inp_lock;
 
 #define	in6p_faddr	inp_inc.inc6_faddr
 #define	in6p_laddr	inp_inc.inc6_laddr
@@ -264,29 +301,32 @@
 	 * or freed.
 	 */
 	u_quad_t		 ipi_gencnt;
-	struct mtx		 ipi_mtx;
+	struct rwlock		 ipi_lock;
 
 	/*
 	 * vimage 1
 	 * general use 1
 	 */
-	void 			*ipi_pspare[2];	
+	void 			*ipi_pspare[2];
 };
 
 #define INP_LOCK_INIT(inp, d, t) \
-	mtx_init(&(inp)->inp_mtx, (d), (t), MTX_DEF | MTX_RECURSE | MTX_DUPOK)
-#define INP_LOCK_DESTROY(inp)	mtx_destroy(&(inp)->inp_mtx)
-#define INP_LOCK(inp)		mtx_lock(&(inp)->inp_mtx)
-#define INP_UNLOCK(inp)		mtx_unlock(&(inp)->inp_mtx)
-#define INP_WLOCK(inp)		mtx_lock(&(inp)->inp_mtx)
-#define INP_WUNLOCK(inp)	mtx_unlock(&(inp)->inp_mtx)
-#define INP_LOCK_ASSERT(inp)	mtx_assert(&(inp)->inp_mtx, MA_OWNED)
-#define INP_WLOCK_ASSERT(inp)	mtx_assert(&(inp)->inp_mtx, MA_OWNED)
-#define	INP_UNLOCK_ASSERT(inp)	mtx_assert(&(inp)->inp_mtx, MA_NOTOWNED)
+	rw_init_flags(&(inp)->inp_lock, (t), RW_RECURSE |  RW_DUPOK)
+#define INP_LOCK_DESTROY(inp)	rw_destroy(&(inp)->inp_lock)
+#define INP_RLOCK(inp)		rw_rlock(&(inp)->inp_lock)
+#define INP_WLOCK(inp)		rw_wlock(&(inp)->inp_lock)
+#define INP_TRY_RLOCK(inp)	rw_try_rlock(&(inp)->inp_lock)
+#define INP_TRY_WLOCK(inp)	rw_try_wlock(&(inp)->inp_lock)
+#define INP_RUNLOCK(inp)	rw_runlock(&(inp)->inp_lock)
+#define INP_WUNLOCK(inp)	rw_wunlock(&(inp)->inp_lock)
+#define INP_LOCK_ASSERT(inp)	rw_assert(&(inp)->inp_lock, RA_LOCKED)
+#define	INP_RLOCK_ASSERT(inp)	rw_assert(&(inp)->inp_lock, RA_RLOCKED)
+#define	INP_WLOCK_ASSERT(inp)	rw_assert(&(inp)->inp_lock, RA_WLOCKED)
+#define	INP_UNLOCK_ASSERT(inp)	rw_assert(&(inp)->inp_lock, RA_UNLOCKED)
 
 #ifdef _KERNEL
 /*
- * These locking functions are for inpcb consumers outside of sys/netinet, 
+ * These locking functions are for inpcb consumers outside of sys/netinet,
  * more specifically, they were added for the benefit of TOE drivers. The
  * macros are reserved for use by the stack.
  */
@@ -318,21 +358,24 @@
 	inp_inpcbtosocket(struct inpcb *inp);
 struct tcpcb *
 	inp_inpcbtotcpcb(struct inpcb *inp);
-void 	inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp, 
+void 	inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
 		uint32_t *faddr, uint16_t *fp);
 
 #endif /* _KERNEL */
 
 #define INP_INFO_LOCK_INIT(ipi, d) \
-	mtx_init(&(ipi)->ipi_mtx, (d), NULL, MTX_DEF | MTX_RECURSE)
-#define INP_INFO_LOCK_DESTROY(ipi)  mtx_destroy(&(ipi)->ipi_mtx)
-#define INP_INFO_RLOCK(ipi)	mtx_lock(&(ipi)->ipi_mtx)
-#define INP_INFO_WLOCK(ipi)	mtx_lock(&(ipi)->ipi_mtx)
-#define INP_INFO_RUNLOCK(ipi)	mtx_unlock(&(ipi)->ipi_mtx)
-#define INP_INFO_WUNLOCK(ipi)	mtx_unlock(&(ipi)->ipi_mtx)
-#define INP_INFO_RLOCK_ASSERT(ipi)	mtx_assert(&(ipi)->ipi_mtx, MA_OWNED)
-#define INP_INFO_WLOCK_ASSERT(ipi)	mtx_assert(&(ipi)->ipi_mtx, MA_OWNED)
-#define INP_INFO_UNLOCK_ASSERT(ipi)	mtx_assert(&(ipi)->ipi_mtx, MA_NOTOWNED)
+	rw_init_flags(&(ipi)->ipi_lock, (d), RW_RECURSE)
+#define INP_INFO_LOCK_DESTROY(ipi)  rw_destroy(&(ipi)->ipi_lock)
+#define INP_INFO_RLOCK(ipi)	rw_rlock(&(ipi)->ipi_lock)
+#define INP_INFO_WLOCK(ipi)	rw_wlock(&(ipi)->ipi_lock)
+#define INP_INFO_TRY_RLOCK(ipi)	rw_try_rlock(&(ipi)->ipi_lock)
+#define INP_INFO_TRY_WLOCK(ipi)	rw_try_wlock(&(ipi)->ipi_lock)
+#define INP_INFO_RUNLOCK(ipi)	rw_runlock(&(ipi)->ipi_lock)
+#define INP_INFO_WUNLOCK(ipi)	rw_wunlock(&(ipi)->ipi_lock)
+#define	INP_INFO_LOCK_ASSERT(ipi)	rw_assert(&(ipi)->ipi_lock, RA_LOCKED)
+#define INP_INFO_RLOCK_ASSERT(ipi)	rw_assert(&(ipi)->ipi_lock, RA_RLOCKED)
+#define INP_INFO_WLOCK_ASSERT(ipi)	rw_assert(&(ipi)->ipi_lock, RA_WLOCKED)
+#define INP_INFO_UNLOCK_ASSERT(ipi)	rw_assert(&(ipi)->ipi_lock, RA_UNLOCKED)
 
 #define INP_PCBHASH(faddr, lport, fport, mask) \
 	(((faddr) ^ ((faddr) >> 16) ^ ntohs((lport) ^ (fport))) & (mask))
Index: sys/netinet/tcp_output.c
===================================================================
--- sys/netinet/tcp_output.c	(revision 181343)
+++ sys/netinet/tcp_output.c	(working copy)
@@ -152,7 +152,7 @@
 	isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0;
 #endif
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	/*
 	 * Determine length of data that should be transmitted,
Index: sys/netinet/ip_output.c
===================================================================
--- sys/netinet/ip_output.c	(revision 181343)
+++ sys/netinet/ip_output.c	(working copy)
@@ -836,9 +836,9 @@
 				m_free(m);
 				break;
 			}
-			INP_LOCK(inp);
+			INP_WLOCK(inp);
 			error = ip_pcbopts(inp, sopt->sopt_name, m);
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			return (error);
 		}
 
@@ -875,12 +875,12 @@
 				break;
 
 #define	OPTSET(bit) do {						\
-	INP_LOCK(inp);							\
+	INP_WLOCK(inp);							\
 	if (optval)							\
 		inp->inp_flags |= bit;					\
 	else								\
 		inp->inp_flags &= ~bit;					\
-	INP_UNLOCK(inp);						\
+	INP_WUNLOCK(inp);						\
 } while (0)
 
 			case IP_RECVOPTS:
@@ -947,7 +947,7 @@
 			if (error)
 				break;
 
-			INP_LOCK(inp);
+			INP_WLOCK(inp);
 			switch (optval) {
 			case IP_PORTRANGE_DEFAULT:
 				inp->inp_flags &= ~(INP_LOWPORT);
@@ -968,7 +968,7 @@
 				error = EINVAL;
 				break;
 			}
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			break;
 
 #ifdef IPSEC
Index: sys/netinet/tcp_syncache.c
===================================================================
--- sys/netinet/tcp_syncache.c	(revision 181343)
+++ sys/netinet/tcp_syncache.c	(working copy)
@@ -674,7 +674,7 @@
 	inp = sotoinpcb(so);
 	inp->inp_inc.inc_fibnum = sc->sc_inc.inc_fibnum;
 	so->so_fibnum = sc->sc_inc.inc_fibnum;
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 
 	/* Insert new socket into PCB hash list. */
 	inp->inp_inc.inc_isipv6 = sc->sc_inc.inc_isipv6;
@@ -821,13 +821,13 @@
 		tp->snd_cwnd = tp->t_maxseg;
 	tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
 
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 
 	tcpstat.tcps_accepts++;
 	return (so);
 
 abort:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 abort2:
 	if (so != NULL)
 		soabort(so);
@@ -1023,7 +1023,7 @@
 	struct syncache scs;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);			/* listen socket */
+	INP_WLOCK_ASSERT(inp);			/* listen socket */
 	KASSERT((th->th_flags & (TH_RST|TH_ACK|TH_SYN)) == TH_SYN,
 	    ("%s: unexpected tcp flags", __func__));
 
@@ -1050,13 +1050,13 @@
 
 #ifdef MAC
 	if (mac_init_syncache(&maclabel) != 0) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&tcbinfo);
 		goto done;
 	} else
 		mac_init_syncache_from_inpcb(maclabel, inp);
 #endif
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 
 	/*
Index: sys/netinet/tcp_usrreq.c
===================================================================
--- sys/netinet/tcp_usrreq.c	(revision 181343)
+++ sys/netinet/tcp_usrreq.c	(working copy)
@@ -160,7 +160,7 @@
 #endif
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	KASSERT(so->so_pcb == inp, ("tcp_detach: so_pcb != inp"));
 	KASSERT(inp->inp_socket == so, ("tcp_detach: inp_socket != so"));
@@ -201,7 +201,7 @@
 			else
 #endif
 				in_pcbdetach(inp);
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 		}
 	} else {
 		/*
@@ -253,7 +253,7 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_detach: inp == NULL"));
 	INP_INFO_WLOCK(&tcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	KASSERT(inp->inp_socket != NULL,
 	    ("tcp_usr_detach: inp_socket == NULL"));
 	tcp_detach(so, inp);
@@ -286,7 +286,7 @@
 	INP_INFO_WLOCK(&tcbinfo);
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_bind: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = EINVAL;
 		goto out;
@@ -296,7 +296,7 @@
 	error = in_pcbbind(inp, nam, td->td_ucred);
 out:
 	TCPDEBUG2(PRU_BIND);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 
 	return (error);
@@ -326,7 +326,7 @@
 	INP_INFO_WLOCK(&tcbinfo);
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp6_usr_bind: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = EINVAL;
 		goto out;
@@ -352,7 +352,7 @@
 	error = in6_pcbbind(inp, nam, td->td_ucred);
 out:
 	TCPDEBUG2(PRU_BIND);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 	return (error);
 }
@@ -372,7 +372,7 @@
 	INP_INFO_WLOCK(&tcbinfo);
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_listen: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = EINVAL;
 		goto out;
@@ -392,7 +392,7 @@
 
 out:
 	TCPDEBUG2(PRU_LISTEN);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 	return (error);
 }
@@ -409,7 +409,7 @@
 	INP_INFO_WLOCK(&tcbinfo);
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp6_usr_listen: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = EINVAL;
 		goto out;
@@ -432,7 +432,7 @@
 
 out:
 	TCPDEBUG2(PRU_LISTEN);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 	return (error);
 }
@@ -469,7 +469,7 @@
 	INP_INFO_WLOCK(&tcbinfo);
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_connect: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = EINVAL;
 		goto out;
@@ -481,7 +481,7 @@
 	error = tcp_output_connect(so, nam);
 out:
 	TCPDEBUG2(PRU_CONNECT);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 	return (error);
 }
@@ -510,7 +510,7 @@
 	INP_INFO_WLOCK(&tcbinfo);
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp6_usr_connect: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = EINVAL;
 		goto out;
@@ -542,7 +542,7 @@
 
 out:
 	TCPDEBUG2(PRU_CONNECT);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 	return (error);
 }
@@ -570,7 +570,7 @@
 	INP_INFO_WLOCK(&tcbinfo);
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_disconnect: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = ECONNRESET;
 		goto out;
@@ -580,7 +580,7 @@
 	tcp_disconnect(tp);
 out:
 	TCPDEBUG2(PRU_DISCONNECT);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 	return (error);
 }
@@ -606,7 +606,7 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL"));
 	INP_INFO_RLOCK(&tcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = ECONNABORTED;
 		goto out;
@@ -624,7 +624,7 @@
 
 out:
 	TCPDEBUG2(PRU_ACCEPT);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_RUNLOCK(&tcbinfo);
 	if (error == 0)
 		*nam = in_sockaddr(port, &addr);
@@ -649,7 +649,7 @@
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp6_usr_accept: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = ECONNABORTED;
 		goto out;
@@ -673,7 +673,7 @@
 
 out:
 	TCPDEBUG2(PRU_ACCEPT);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	if (error == 0) {
 		if (v4)
 			*nam = in6_v4mapsin6_sockaddr(port, &addr);
@@ -698,7 +698,7 @@
 	INP_INFO_WLOCK(&tcbinfo);
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = ECONNRESET;
 		goto out;
@@ -711,7 +711,7 @@
 
 out:
 	TCPDEBUG2(PRU_SHUTDOWN);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 
 	return (error);
@@ -730,7 +730,7 @@
 	TCPDEBUG0;
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_rcvd: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = ECONNRESET;
 		goto out;
@@ -741,7 +741,7 @@
 
 out:
 	TCPDEBUG2(PRU_RCVD);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -780,7 +780,7 @@
 	}
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		if (control)
 			m_freem(control);
@@ -899,7 +899,7 @@
 out:
 	TCPDEBUG2((flags & PRUS_OOB) ? PRU_SENDOOB :
 		  ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	if (headlocked)
 		INP_INFO_WUNLOCK(&tcbinfo);
 	return (error);
@@ -919,7 +919,7 @@
 	KASSERT(inp != NULL, ("tcp_usr_abort: inp == NULL"));
 
 	INP_INFO_WLOCK(&tcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	KASSERT(inp->inp_socket != NULL,
 	    ("tcp_usr_abort: inp_socket == NULL"));
 
@@ -939,7 +939,7 @@
 		SOCK_UNLOCK(so);
 		inp->inp_vflag |= INP_SOCKREF;
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 }
 
@@ -957,7 +957,7 @@
 	KASSERT(inp != NULL, ("tcp_usr_close: inp == NULL"));
 
 	INP_INFO_WLOCK(&tcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	KASSERT(inp->inp_socket != NULL,
 	    ("tcp_usr_close: inp_socket == NULL"));
 
@@ -978,7 +978,7 @@
 		SOCK_UNLOCK(so);
 		inp->inp_vflag |= INP_SOCKREF;
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 }
 
@@ -995,7 +995,7 @@
 	TCPDEBUG0;
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_rcvoob: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = ECONNRESET;
 		goto out;
@@ -1020,7 +1020,7 @@
 
 out:
 	TCPDEBUG2(PRU_RCVOOB);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -1086,7 +1086,7 @@
 	int error;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if (inp->inp_lport == 0) {
 		error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
@@ -1141,7 +1141,7 @@
 	int error;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if (inp->inp_lport == 0) {
 		error = in6_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
@@ -1205,7 +1205,7 @@
 tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti)
 {
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	bzero(ti, sizeof(*ti));
 
 	ti->tcpi_state = tp->t_state;
@@ -1245,10 +1245,10 @@
  * has to revalidate that the connection is still valid for the socket
  * option.
  */
-#define INP_LOCK_RECHECK(inp) do {					\
-	INP_LOCK(inp);							\
+#define INP_WLOCK_RECHECK(inp) do {					\
+	INP_WLOCK(inp);							\
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {		\
-		INP_UNLOCK(inp);					\
+		INP_WUNLOCK(inp);					\
 		return (ECONNRESET);					\
 	}								\
 	tp = intotcpcb(inp);						\
@@ -1265,15 +1265,15 @@
 	error = 0;
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_ctloutput: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (sopt->sopt_level != IPPROTO_TCP) {
 #ifdef INET6
 		if (INP_CHECK_SOCKAF(so, AF_INET6)) {
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = ip6_ctloutput(so, sopt);
 		} else {
 #endif /* INET6 */
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = ip_ctloutput(so, sopt);
 #ifdef INET6
 		}
@@ -1281,7 +1281,7 @@
 		return (error);
 	}
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		return (ECONNRESET);
 	}
 
@@ -1290,29 +1290,29 @@
 		switch (sopt->sopt_name) {
 #ifdef TCP_SIGNATURE
 		case TCP_MD5SIG:
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyin(sopt, &optval, sizeof optval,
 			    sizeof optval);
 			if (error)
 				return (error);
 
-			INP_LOCK_RECHECK(inp);
+			INP_WLOCK_RECHECK(inp);
 			if (optval > 0)
 				tp->t_flags |= TF_SIGNATURE;
 			else
 				tp->t_flags &= ~TF_SIGNATURE;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			break;
 #endif /* TCP_SIGNATURE */
 		case TCP_NODELAY:
 		case TCP_NOOPT:
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyin(sopt, &optval, sizeof optval,
 			    sizeof optval);
 			if (error)
 				return (error);
 
-			INP_LOCK_RECHECK(inp);
+			INP_WLOCK_RECHECK(inp);
 			switch (sopt->sopt_name) {
 			case TCP_NODELAY:
 				opt = TF_NODELAY;
@@ -1329,49 +1329,49 @@
 				tp->t_flags |= opt;
 			else
 				tp->t_flags &= ~opt;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			break;
 
 		case TCP_NOPUSH:
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyin(sopt, &optval, sizeof optval,
 			    sizeof optval);
 			if (error)
 				return (error);
 
-			INP_LOCK_RECHECK(inp);
+			INP_WLOCK_RECHECK(inp);
 			if (optval)
 				tp->t_flags |= TF_NOPUSH;
 			else {
 				tp->t_flags &= ~TF_NOPUSH;
 				error = tcp_output(tp);
 			}
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			break;
 
 		case TCP_MAXSEG:
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyin(sopt, &optval, sizeof optval,
 			    sizeof optval);
 			if (error)
 				return (error);
 
-			INP_LOCK_RECHECK(inp);
+			INP_WLOCK_RECHECK(inp);
 			if (optval > 0 && optval <= tp->t_maxseg &&
 			    optval + 40 >= tcp_minmss)
 				tp->t_maxseg = optval;
 			else
 				error = EINVAL;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			break;
 
 		case TCP_INFO:
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = EINVAL;
 			break;
 
 		default:
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = ENOPROTOOPT;
 			break;
 		}
@@ -1383,38 +1383,38 @@
 #ifdef TCP_SIGNATURE
 		case TCP_MD5SIG:
 			optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
 #endif
 
 		case TCP_NODELAY:
 			optval = tp->t_flags & TF_NODELAY;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
 		case TCP_MAXSEG:
 			optval = tp->t_maxseg;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
 		case TCP_NOOPT:
 			optval = tp->t_flags & TF_NOOPT;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
 		case TCP_NOPUSH:
 			optval = tp->t_flags & TF_NOPUSH;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
 		case TCP_INFO:
 			tcp_fill_info(tp, &ti);
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = sooptcopyout(sopt, &ti, sizeof ti);
 			break;
 		default:
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			error = ENOPROTOOPT;
 			break;
 		}
@@ -1422,7 +1422,7 @@
 	}
 	return (error);
 }
-#undef INP_LOCK_RECHECK
+#undef INP_WLOCK_RECHECK
 
 /*
  * tcp_sendspace and tcp_recvspace are the default send and receive window
@@ -1490,7 +1490,7 @@
 		return (ENOBUFS);
 	}
 	tp->t_state = TCPS_CLOSED;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 	return (0);
 }
@@ -1510,7 +1510,7 @@
 	struct socket *so = inp->inp_socket;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	/*
 	 * Neither tcp_close() nor tcp_drop() should return NULL, as the
@@ -1548,7 +1548,7 @@
 {
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	switch (tp->t_state) {
 	case TCPS_LISTEN:
Index: sys/netinet/ip_options.c
===================================================================
--- sys/netinet/ip_options.c	(revision 181343)
+++ sys/netinet/ip_options.c	(working copy)
@@ -590,7 +590,7 @@
 	struct mbuf **pcbopt;
 	u_char opt;
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	pcbopt = &inp->inp_options;
 
Index: sys/netinet/ip_fw2.c
===================================================================
--- sys/netinet/ip_fw2.c	(revision 181343)
+++ sys/netinet/ip_fw2.c	(working copy)
@@ -2015,12 +2015,12 @@
 				dst_ip, htons(dst_port),
 				wildcard, NULL);
 		if (pcb != NULL) {
-			INP_LOCK(pcb);
+			INP_RLOCK(pcb);
 			if (pcb->inp_socket != NULL) {
 				fill_ugid_cache(pcb, ugp);
 				*lookup = 1;
 			}
-			INP_UNLOCK(pcb);
+			INP_RUNLOCK(pcb);
 		}
 		INP_INFO_RUNLOCK(pi);
 		if (*lookup == 0) {
Index: sys/netinet/tcp_timewait.c
===================================================================
--- sys/netinet/tcp_timewait.c	(revision 181343)
+++ sys/netinet/tcp_timewait.c	(working copy)
@@ -186,12 +186,12 @@
 	struct socket *so;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);	/* tcp_tw_2msl_reset(). */
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if (nolocaltimewait && in_localip(inp->inp_faddr)) {
 		tp = tcp_close(tp);
 		if (tp != NULL)
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 		return;
 	}
 
@@ -201,7 +201,7 @@
 		if (tw == NULL) {
 			tp = tcp_close(tp);
 			if (tp != NULL)
-				INP_UNLOCK(inp);
+				INP_WUNLOCK(inp);
 			return;
 		}
 	}
@@ -267,13 +267,13 @@
 		KASSERT(so->so_state & SS_PROTOREF,
 		    ("tcp_twstart: !SS_PROTOREF"));
 		inp->inp_vflag &= ~INP_SOCKREF;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		ACCEPT_LOCK();
 		SOCK_LOCK(so);
 		so->so_state &= ~SS_PROTOREF;
 		sofree(so);
 	} else
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 }
 
 #if 0
@@ -328,7 +328,7 @@
 
 	/* tcbinfo lock required for tcp_twclose(), tcp_tw_2msl_reset(). */
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	/*
 	 * XXXRW: Time wait state for inpcb has been recycled, but inpcb is
@@ -441,11 +441,11 @@
 		tcp_respond(NULL,
 		    mtod(m, void *), th, m, seq, 0, TH_RST|TH_ACK);
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (0);
 
 drop:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	m_freem(m);
 	return (0);
 }
@@ -469,7 +469,7 @@
 	KASSERT((inp->inp_vflag & INP_TIMEWAIT), ("tcp_twclose: !timewait"));
 	KASSERT(intotw(inp) == tw, ("tcp_twclose: inp_ppcb != tw"));
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);	/* tcp_tw_2msl_stop(). */
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	tw->tw_inpcb = NULL;
 	tcp_tw_2msl_stop(tw);
@@ -486,7 +486,7 @@
 		 */
 		if (inp->inp_vflag & INP_SOCKREF) {
 			inp->inp_vflag &= ~INP_SOCKREF;
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			ACCEPT_LOCK();
 			SOCK_LOCK(so);
 			KASSERT(so->so_state & SS_PROTOREF,
@@ -499,7 +499,7 @@
 			 * inpcb need to be left around to be handled by
 			 * tcp_usr_detach() later.
 			 */
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 		}
 	} else {
 #ifdef INET6
@@ -532,7 +532,7 @@
 	int isipv6 = inp->inp_inc.inc_isipv6;
 #endif
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	m = m_gethdr(M_DONTWAIT, MT_DATA);
 	if (m == NULL)
@@ -615,7 +615,7 @@
 {
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(tw->tw_inpcb);
+	INP_WLOCK_ASSERT(tw->tw_inpcb);
 	if (rearm)
 		TAILQ_REMOVE(&twq_2msl, tw, tw_2msl);
 	tw->tw_time = ticks + 2 * tcp_msl;
@@ -640,7 +640,7 @@
 		tw = TAILQ_FIRST(&twq_2msl);
 		if (tw == NULL || (!reuse && tw->tw_time > ticks))
 			break;
-		INP_LOCK(tw->tw_inpcb);
+		INP_WLOCK(tw->tw_inpcb);
 		tcp_twclose(tw, reuse);
 		if (reuse)
 			return (tw);
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c	(revision 181343)
+++ sys/netinet/udp_usrreq.c	(working copy)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
  *	The Regents of the University of California.
+ * Copyright (c) 2008 Robert N. M. Watson
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -195,7 +196,7 @@
 	struct sockaddr_in6 udp_in6;
 #endif
 
-	INP_LOCK_ASSERT(inp);
+	INP_RLOCK_ASSERT(inp);
 
 #ifdef IPSEC
 	/* Check AH/ESP integrity. */
@@ -407,7 +408,7 @@
 			    inp->inp_fport != uh->uh_sport)
 				continue;
 
-			INP_LOCK(inp);
+			INP_RLOCK(inp);
 
 			/*
 			 * Handle socket delivery policy for any-source
@@ -464,7 +465,7 @@
 					}
 				}
 				if (blocked != 0) {
-					INP_UNLOCK(inp);
+					INP_RUNLOCK(inp);
 					continue;
 				}
 			}
@@ -475,7 +476,7 @@
 				if (n != NULL)
 					udp_append(last, ip, n, iphlen +
 					    sizeof(struct udphdr), &udp_in);
-				INP_UNLOCK(last);
+				INP_RUNLOCK(last);
 			}
 			last = inp;
 			/*
@@ -502,7 +503,7 @@
 		}
 		udp_append(last, ip, m, iphlen + sizeof(struct udphdr),
 		    &udp_in);
-		INP_UNLOCK(last);
+		INP_RUNLOCK(last);
 		INP_INFO_RUNLOCK(&udbinfo);
 		return;
 	}
@@ -541,17 +542,19 @@
 	/*
 	 * Check the minimum TTL for socket.
 	 */
-	INP_LOCK(inp);
-	if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl)
-		goto badheadlocked;
+	INP_RLOCK(inp);
+	INP_INFO_RUNLOCK(&udbinfo);
+	if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) {
+		INP_RUNLOCK(inp);
+		goto badunlocked;
+	}
 	udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in);
-	INP_UNLOCK(inp);
-	INP_INFO_RUNLOCK(&udbinfo);
+	INP_RUNLOCK(inp);
 	return;
 
 badheadlocked:
 	if (inp)
-		INP_UNLOCK(inp);
+		INP_RUNLOCK(inp);
 	INP_INFO_RUNLOCK(&udbinfo);
 badunlocked:
 	m_freem(m);
@@ -565,6 +568,14 @@
 udp_notify(struct inpcb *inp, int errno)
 {
 
+	/*
+	 * While udp_ctlinput() always calls udp_notify() with a read lock
+	 * when invoking it directly, in_pcbnotifyall() currently uses write
+	 * locks due to sharing code with TCP.  For now, accept either a read
+	 * or a write lock, but a read lock is sufficient.
+	 */
+	INP_LOCK_ASSERT(inp);
+
 	inp->inp_socket->so_error = errno;
 	sorwakeup(inp->inp_socket);
 	sowwakeup(inp->inp_socket);
@@ -605,11 +616,11 @@
 		inp = in_pcblookup_hash(&udbinfo, faddr, uh->uh_dport,
 		    ip->ip_src, uh->uh_sport, 0, NULL);
 		if (inp != NULL) {
-			INP_LOCK(inp);
+			INP_RLOCK(inp);
 			if (inp->inp_socket != NULL) {
 				udp_notify(inp, inetctlerrmap[cmd]);
 			}
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 		}
 		INP_INFO_RUNLOCK(&udbinfo);
 	} else
@@ -667,11 +678,11 @@
 	INP_INFO_RLOCK(&udbinfo);
 	for (inp = LIST_FIRST(udbinfo.ipi_listhead), i = 0; inp && i < n;
 	     inp = LIST_NEXT(inp, inp_list)) {
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		if (inp->inp_gencnt <= gencnt &&
 		    cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
 			inp_list[i++] = inp;
-		INP_UNLOCK(inp);
+		INP_RUNLOCK(inp);
 	}
 	INP_INFO_RUNLOCK(&udbinfo);
 	n = i;
@@ -679,7 +690,7 @@
 	error = 0;
 	for (i = 0; i < n; i++) {
 		inp = inp_list[i];
-		INP_LOCK(inp);
+		INP_RLOCK(inp);
 		if (inp->inp_gencnt <= gencnt) {
 			struct xinpcb xi;
 			bzero(&xi, sizeof(xi));
@@ -689,10 +700,10 @@
 			if (inp->inp_socket)
 				sotoxsocket(inp->inp_socket, &xi.xi_socket);
 			xi.xi_inp.inp_gencnt = inp->inp_gencnt;
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			error = SYSCTL_OUT(req, &xi, sizeof xi);
 		} else
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 	}
 	if (!error) {
 		/*
@@ -732,16 +743,21 @@
 	INP_INFO_RLOCK(&udbinfo);
 	inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
 				addrs[0].sin_addr, addrs[0].sin_port, 1, NULL);
-	if (inp == NULL || inp->inp_socket == NULL) {
+	if (inp != NULL) {
+		INP_RLOCK(inp);
+		INP_INFO_RUNLOCK(&udbinfo);
+		if (inp->inp_socket == NULL)
+			error = ENOENT;
+		if (error == 0)
+			error = cr_canseesocket(req->td->td_ucred,
+			    inp->inp_socket);
+		if (error == 0)
+			cru2x(inp->inp_socket->so_cred, &xuc);
+		INP_RUNLOCK(inp);
+	} else {
+		INP_INFO_RUNLOCK(&udbinfo);
 		error = ENOENT;
-		goto out;
 	}
-	error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
-	if (error)
-		goto out;
-	cru2x(inp->inp_socket->so_cred, &xuc);
-out:
-	INP_INFO_RUNLOCK(&udbinfo);
 	if (error == 0)
 		error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 	return (error);
@@ -830,17 +846,43 @@
 		return (error);
 	}
 
-	if (src.sin_family == AF_INET || addr != NULL) {
+	/*
+	 * Depending on whether or not the application has bound or connected
+	 * the socket, we may have to do varying levels of work.  The optimal
+	 * case is for a connected UDP socket, as a global lock isn't
+	 * required at all.
+	 *
+	 * In order to decide which we need, we require stability of the
+	 * inpcb binding, which we ensure by acquiring a read lock on the
+	 * inpcb.  This doesn't strictly follow the lock order, so we play
+	 * the trylock and retry game; note that we may end up with more
+	 * conservative locks than required the second time around, so later
+	 * assertions have to accept that.  Further analysis of the number of
+	 * misses under contention is required.
+	 */
+	sin = (struct sockaddr_in *)addr;
+	INP_RLOCK(inp);
+	if (sin != NULL &&
+	    (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) {
+		INP_RUNLOCK(inp);
 		INP_INFO_WLOCK(&udbinfo);
+		INP_WLOCK(inp);
+		unlock_udbinfo = 2;
+	} else if ((sin != NULL && (
+	    (sin->sin_addr.s_addr == INADDR_ANY) ||
+	    (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+	    (inp->inp_laddr.s_addr == INADDR_ANY) ||
+	    (inp->inp_lport == 0))) ||
+	    (src.sin_family == AF_INET)) {
+		if (!INP_INFO_TRY_RLOCK(&udbinfo)) {
+			INP_RUNLOCK(inp);
+			INP_INFO_RLOCK(&udbinfo);
+			INP_RLOCK(inp);
+		}
 		unlock_udbinfo = 1;
 	} else
 		unlock_udbinfo = 0;
-	INP_LOCK(inp);
 
-#ifdef MAC
-	mac_create_mbuf_from_inpcb(inp, m);
-#endif
-
 	/*
 	 * If the IP_SENDSRCADDR control message was specified, override the
 	 * source address for this datagram.  Its use is invalidated if the
@@ -849,6 +891,7 @@
 	laddr = inp->inp_laddr;
 	lport = inp->inp_lport;
 	if (src.sin_family == AF_INET) {
+		INP_INFO_LOCK_ASSERT(&udbinfo);
 		if ((lport == 0) ||
 		    (laddr.s_addr == INADDR_ANY &&
 		     src.sin_addr.s_addr == INADDR_ANY)) {
@@ -861,37 +904,80 @@
 			goto release;
 	}
 
-	if (addr) {
-		sin = (struct sockaddr_in *)addr;
-		if (jailed(td->td_ucred))
-			prison_remote_ip(td->td_ucred, 0,
-			    &sin->sin_addr.s_addr);
+	/*
+	 * If a UDP socket has been connected, then a local address/port will
+	 * have been selected and bound.
+	 *
+	 * If a UDP socket has not been connected to, then an explicit
+	 * destination address must be used, in which case a local
+	 * address/port may not have been selected and bound.
+	 */
+	if (sin != NULL) {
+		INP_LOCK_ASSERT(inp);
 		if (inp->inp_faddr.s_addr != INADDR_ANY) {
 			error = EISCONN;
 			goto release;
 		}
-		error = in_pcbconnect_setup(inp, addr, &laddr.s_addr, &lport,
-		    &faddr.s_addr, &fport, NULL, td->td_ucred);
-		if (error)
-			goto release;
 
-		/* Commit the local port if newly assigned. */
-		if (inp->inp_laddr.s_addr == INADDR_ANY &&
-		    inp->inp_lport == 0) {
+		/*
+		 * Jail may rewrite the destination address, so let it do
+		 * that before we use it.
+		 */
+		if (jailed(td->td_ucred))
+			prison_remote_ip(td->td_ucred, 0,
+			    &sin->sin_addr.s_addr);
+
+		/*
+		 * If a local address or port hasn't yet been selected, or if
+		 * the destination address needs to be rewritten due to using
+		 * a special INADDR_ constant, invoke in_pcbconnect_setup()
+		 * to do the heavy lifting.  Once a port is selected, we
+		 * commit the binding back to the socket; we also commit the
+		 * binding of the address if in jail.
+		 *
+		 * If we already have a valid binding and we're not
+		 * requesting a destination address rewrite, use a fast path.
+		 */
+		if (inp->inp_laddr.s_addr == INADDR_ANY ||
+		    inp->inp_lport == 0 ||
+		    sin->sin_addr.s_addr == INADDR_ANY ||
+		    sin->sin_addr.s_addr == INADDR_BROADCAST) {
+			INP_INFO_LOCK_ASSERT(&udbinfo);
+			error = in_pcbconnect_setup(inp, addr, &laddr.s_addr,
+			    &lport, &faddr.s_addr, &fport, NULL,
+			    td->td_ucred);
+			if (error)
+				goto release;
+
 			/*
-			 * Remember addr if jailed, to prevent rebinding.
+			 * XXXRW: Why not commit the port if the address is
+			 * !INADDR_ANY?
 			 */
-			if (jailed(td->td_ucred))
-				inp->inp_laddr = laddr;
-			inp->inp_lport = lport;
-			if (in_pcbinshash(inp) != 0) {
-				inp->inp_lport = 0;
-				error = EAGAIN;
-				goto release;
+			/* Commit the local port if newly assigned. */
+			if (inp->inp_laddr.s_addr == INADDR_ANY &&
+			    inp->inp_lport == 0) {
+				INP_INFO_WLOCK_ASSERT(&udbinfo);
+				INP_WLOCK_ASSERT(inp);
+				/*
+				 * Remember addr if jailed, to prevent
+				 * rebinding.
+				 */
+				if (jailed(td->td_ucred))
+					inp->inp_laddr = laddr;
+				inp->inp_lport = lport;
+				if (in_pcbinshash(inp) != 0) {
+					inp->inp_lport = 0;
+					error = EAGAIN;
+					goto release;
+				}
+				inp->inp_flags |= INP_ANONPORT;
 			}
-			inp->inp_flags |= INP_ANONPORT;
+		} else {
+			faddr = sin->sin_addr;
+			fport = sin->sin_port;
 		}
 	} else {
+		INP_LOCK_ASSERT(inp);
 		faddr = inp->inp_faddr;
 		fport = inp->inp_fport;
 		if (faddr.s_addr == INADDR_ANY) {
@@ -945,6 +1031,10 @@
 	if (inp->inp_flags & INP_ONESBCAST)
 		ipflags |= IP_SENDONES;
 
+#ifdef MAC
+	mac_create_mbuf_from_inpcb(inp, m);
+#endif
+
 	/*
 	 * Set up checksum and output datagram.
 	 */
@@ -962,17 +1052,27 @@
 	((struct ip *)ui)->ip_tos = inp->inp_ip_tos;	/* XXX */
 	udpstat.udps_opackets++;
 
-	if (unlock_udbinfo)
+	if (unlock_udbinfo == 2)
 		INP_INFO_WUNLOCK(&udbinfo);
+	else if (unlock_udbinfo == 1)
+		INP_INFO_RUNLOCK(&udbinfo);
 	error = ip_output(m, inp->inp_options, NULL, ipflags,
 	    inp->inp_moptions, inp);
-	INP_UNLOCK(inp);
+	if (unlock_udbinfo == 2)
+		INP_WUNLOCK(inp);
+	else
+		INP_RUNLOCK(inp);
 	return (error);
 
 release:
-	INP_UNLOCK(inp);
-	if (unlock_udbinfo)
+	if (unlock_udbinfo == 2) {
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&udbinfo);
+	} else if (unlock_udbinfo == 1) {
+		INP_RUNLOCK(inp);
+		INP_INFO_RUNLOCK(&udbinfo);
+	} else
+		INP_RUNLOCK(inp);
 	m_freem(m);
 	return (error);
 }
@@ -985,13 +1085,13 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp_abort: inp == NULL"));
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_faddr.s_addr != INADDR_ANY) {
 		in_pcbdisconnect(inp);
 		inp->inp_laddr.s_addr = INADDR_ANY;
 		soisdisconnected(so);
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 }
 
@@ -1017,7 +1117,7 @@
 	INP_INFO_WUNLOCK(&udbinfo);
 	inp->inp_vflag |= INP_IPV4;
 	inp->inp_ip_ttl = ip_defttl;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (0);
 }
 
@@ -1030,9 +1130,9 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp_bind: inp == NULL"));
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	error = in_pcbbind(inp, nam, td->td_ucred);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (error);
 }
@@ -1045,13 +1145,13 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp_close: inp == NULL"));
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_faddr.s_addr != INADDR_ANY) {
 		in_pcbdisconnect(inp);
 		inp->inp_laddr.s_addr = INADDR_ANY;
 		soisdisconnected(so);
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 }
 
@@ -1065,9 +1165,9 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp_connect: inp == NULL"));
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_faddr.s_addr != INADDR_ANY) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&udbinfo);
 		return (EISCONN);
 	}
@@ -1077,7 +1177,7 @@
 	error = in_pcbconnect(inp, nam, td->td_ucred);
 	if (error == 0)
 		soisconnected(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (error);
 }
@@ -1092,7 +1192,7 @@
 	KASSERT(inp->inp_faddr.s_addr == INADDR_ANY,
 	    ("udp_detach: not disconnected"));
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	in_pcbdetach(inp);
 	in_pcbfree(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
@@ -1106,10 +1206,10 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp_disconnect: inp == NULL"));
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_faddr.s_addr == INADDR_ANY) {
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&udbinfo);
-		INP_UNLOCK(inp);
 		return (ENOTCONN);
 	}
 
@@ -1118,7 +1218,7 @@
 	SOCK_LOCK(so);
 	so->so_state &= ~SS_ISCONNECTED;		/* XXX */
 	SOCK_UNLOCK(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (0);
 }
@@ -1141,9 +1241,9 @@
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp_shutdown: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	socantsendmore(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (0);
 }
 

Property changes on: sys/modules/geom/geom_part
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/modules/geom/geom_part:r180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/modules/cxgb
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/modules/cxgb:r181364-181365


Property changes on: sys/modules/cxgb/cxgb_t3fw
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/modules/cxgb/cxgb_t3fw:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/pci
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/pci:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/dev/mfi
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/dev/mfi:r180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/dev/gem
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/dev/gem:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/dev/cxgb
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/dev/cxgb:r178285,181364-181365

Index: sys/dev/cxgb/ulp/tom/cxgb_cpl_socket.c
===================================================================
--- sys/dev/cxgb/ulp/tom/cxgb_cpl_socket.c	(revision 181343)
+++ sys/dev/cxgb/ulp/tom/cxgb_cpl_socket.c	(working copy)
@@ -336,9 +336,9 @@
 static void
 cxgb_wait_dma_completion(struct toepcb *toep)
 {
-	struct mtx *lock;
+	struct rwlock *lock;
 	
-	lock = &toep->tp_tp->t_inpcb->inp_mtx;
+	lock = &toep->tp_tp->t_inpcb->inp_lock;
 	inp_wlock(toep->tp_tp->t_inpcb);
 	cv_wait_unlock(&toep->tp_cv, lock);
 }

Property changes on: sys/dev/usb
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/dev/usb:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/dev/ata
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/dev/ata:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/net/if_gre.c
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/net/if_gre.c:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365


Property changes on: sys/geom/part
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/geom/part:r180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365

Index: sys/netinet6/raw_ip6.c
===================================================================
--- sys/netinet6/raw_ip6.c	(revision 181343)
+++ sys/netinet6/raw_ip6.c	(working copy)
@@ -153,10 +153,10 @@
 
 	INP_INFO_RLOCK(&ripcbinfo);
 	LIST_FOREACH(in6p, &ripcb, inp_list) {
-		INP_LOCK(in6p);
+		INP_RLOCK(in6p);
 		if ((in6p->in6p_vflag & INP_IPV6) == 0) {
 docontinue:
-			INP_UNLOCK(in6p);
+			INP_RUNLOCK(in6p);
 			continue;
 		}
 		if (in6p->in6p_ip6_nxt &&
@@ -206,7 +206,7 @@
 					sorwakeup(last->in6p_socket);
 				opts = NULL;
 			}
-			INP_UNLOCK(last);
+			INP_RUNLOCK(last);
 		}
 		last = in6p;
 	}
@@ -219,7 +219,7 @@
 		ipsec6stat.in_polvio++;
 		ip6stat.ip6s_delivered--;
 		/* do not inject data into pcb */
-		INP_UNLOCK(last);
+		INP_RUNLOCK(last);
 	} else
 #endif /* IPSEC */
 	if (last) {
@@ -236,7 +236,7 @@
 			rip6stat.rip6s_fullsock++;
 		} else
 			sorwakeup(last->in6p_socket);
-		INP_UNLOCK(last);
+		INP_RUNLOCK(last);
 	} else {
 		rip6stat.rip6s_nosock++;
 		if (m->m_flags & M_MCAST)
@@ -334,7 +334,7 @@
 	va_end(ap);
 
 	in6p = sotoin6pcb(so);
-	INP_LOCK(in6p);
+	INP_WLOCK(in6p);
 
 	dst = &dstsock->sin6_addr;
 	if (control) {
@@ -464,7 +464,7 @@
 		ip6_clearpktopts(&opt, -1);
 		m_freem(control);
 	}
-	INP_UNLOCK(in6p);
+	INP_WUNLOCK(in6p);
 	return (error);
 }
 
@@ -568,7 +568,7 @@
 	inp->in6p_cksum = -1;
 	inp->in6p_icmp6filt = filter;
 	ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return 0;
 }
 
@@ -584,7 +584,7 @@
 		ip6_mrouter_done();
 	/* xxx: RSVP */
 	INP_INFO_WLOCK(&ripcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->in6p_icmp6filt) {
 		FREE(inp->in6p_icmp6filt, M_PCB);
 		inp->in6p_icmp6filt = NULL;
@@ -655,9 +655,9 @@
 		return (EADDRNOTAVAIL);
 	}
 	INP_INFO_WLOCK(&ripcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	inp->in6p_laddr = addr->sin6_addr;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&ripcbinfo);
 	return 0;
 }
@@ -693,13 +693,13 @@
 		return(error);
 
 	INP_INFO_WLOCK(&ripcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	/* Source address selection. XXX: need pcblookup? */
 	in6a = in6_selectsrc(addr, inp->in6p_outputopts,
 			     inp, NULL, so->so_cred,
 			     &ifp, &error);
 	if (in6a == NULL) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&ripcbinfo);
 		return (error ? error : EADDRNOTAVAIL);
 	}
@@ -707,14 +707,14 @@
 	/* XXX: see above */
 	if (ifp && scope_ambiguous &&
 	    (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&ripcbinfo);
 		return(error);
 	}
 	inp->in6p_faddr = addr->sin6_addr;
 	inp->in6p_laddr = *in6a;
 	soisconnected(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&ripcbinfo);
 	return 0;
 }
@@ -726,9 +726,9 @@
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("rip6_shutdown: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	socantsendmore(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return 0;
 }
 
Index: sys/netinet6/icmp6.c
===================================================================
--- sys/netinet6/icmp6.c	(revision 181343)
+++ sys/netinet6/icmp6.c	(working copy)
@@ -1889,10 +1889,10 @@
 
 	INP_INFO_RLOCK(&ripcbinfo);
 	LIST_FOREACH(in6p, &ripcb, inp_list) {
-		INP_LOCK(in6p);
+		INP_RLOCK(in6p);
 		if ((in6p->inp_vflag & INP_IPV6) == 0) {
 	docontinue:
-			INP_UNLOCK(in6p);
+			INP_RUNLOCK(in6p);
 			continue;
 		}
 		if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)
@@ -1963,7 +1963,7 @@
 					sorwakeup_locked(last->in6p_socket);
 				opts = NULL;
 			}
-			INP_UNLOCK(last);
+			INP_RUNLOCK(last);
 		}
 		last = in6p;
 	}
@@ -2001,7 +2001,7 @@
 			SOCKBUF_UNLOCK(&last->in6p_socket->so_rcv);
 		} else
 			sorwakeup_locked(last->in6p_socket);
-		INP_UNLOCK(last);
+		INP_RUNLOCK(last);
 	} else {
 		m_freem(m);
 		ip6stat.ip6s_delivered--;
Index: sys/netinet6/udp6_usrreq.c
===================================================================
--- sys/netinet6/udp6_usrreq.c	(revision 181343)
+++ sys/netinet6/udp6_usrreq.c	(working copy)
@@ -275,9 +275,9 @@
 				struct mbuf *n;
 
 				if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
-					INP_LOCK(last);
+					INP_RLOCK(last);
 					udp6_append(last, n, off, &fromsa);
-					INP_UNLOCK(last);
+					INP_RUNLOCK(last);
 				}
 			}
 			last = inp;
@@ -304,9 +304,9 @@
 			udpstat.udps_noportmcast++;
 			goto badheadlocked;
 		}
-		INP_LOCK(last);
+		INP_RLOCK(last);
 		udp6_append(last, m, off, &fromsa);
-		INP_UNLOCK(last);
+		INP_RUNLOCK(last);
 		INP_INFO_RUNLOCK(&udbinfo);
 		return (IPPROTO_DONE);
 	}
@@ -341,10 +341,10 @@
 		icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
 		return (IPPROTO_DONE);
 	}
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
+	INP_INFO_RUNLOCK(&udbinfo);
 	udp6_append(inp, m, off, &fromsa);
-	INP_UNLOCK(inp);
-	INP_INFO_RUNLOCK(&udbinfo);
+	INP_RUNLOCK(inp);
 	return (IPPROTO_DONE);
 
 badheadlocked:
@@ -447,21 +447,22 @@
 	inp = in6_pcblookup_hash(&udbinfo, &addrs[1].sin6_addr,
 	    addrs[1].sin6_port, &addrs[0].sin6_addr, addrs[0].sin6_port, 1,
 	    NULL);
-	if (inp == NULL) {
+	if (inp != NULL) {
+		INP_RLOCK(inp);
 		INP_INFO_RUNLOCK(&udbinfo);
-		return (ENOENT);
-	}
-	INP_LOCK(inp);
-	if (inp->inp_socket == NULL) {
+		if (inp->inp_socket == NULL)
+			error = ENOENT;
+		if (error == 0)
+			error = cr_canseesocket(req->td->td_ucred,
+			    inp->inp_socket);
+		if (error == 0)
+			cru2x(inp->inp_socket->so_cred, &xuc);
+		INP_RUNLOCK(inp);
+	} else {
+		INP_INFO_RUNLOCK(&udbinfo);
 		error = ENOENT;
-		goto out;
 	}
-	error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
-	if (error)
-		goto out;
-	cru2x(inp->inp_socket->so_cred, &xuc);
-out:
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 	INP_INFO_RUNLOCK(&udbinfo);
 	if (error == 0)
 		error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
@@ -490,7 +491,7 @@
 	int flags;
 	struct sockaddr_in6 tmp;
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if (addr6) {
 		/* addr6 has been validated in udp6_send(). */
@@ -706,13 +707,13 @@
 #endif
 
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
 		in6_pcbdisconnect(inp);
 		inp->in6p_laddr = in6addr_any;
 		soisdisconnected(so);
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 }
 
@@ -750,7 +751,7 @@
 	 * which may match an IPv4-mapped IPv6 address.
 	 */
 	inp->inp_ip_ttl = ip_defttl;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (0);
 }
 
@@ -764,7 +765,7 @@
 	KASSERT(inp != NULL, ("udp6_bind: inp == NULL"));
 
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	inp->inp_vflag &= ~INP_IPV4;
 	inp->inp_vflag |= INP_IPV6;
 	if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
@@ -788,7 +789,7 @@
 
 	error = in6_pcbbind(inp, nam, td->td_ucred);
 out:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (error);
 }
@@ -811,13 +812,13 @@
 	}
 #endif
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
 		in6_pcbdisconnect(inp);
 		inp->in6p_laddr = in6addr_any;
 		soisdisconnected(so);
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 }
 
@@ -831,7 +832,7 @@
 	KASSERT(inp != NULL, ("udp6_connect: inp == NULL"));
 
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
 		struct sockaddr_in6 *sin6_p;
 
@@ -868,7 +869,7 @@
 		soisconnected(so);
 	}
 out:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (error);
 }
@@ -882,7 +883,7 @@
 	KASSERT(inp != NULL, ("udp6_detach: inp == NULL"));
 
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	in6_pcbdetach(inp);
 	in6_pcbfree(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
@@ -898,7 +899,7 @@
 	KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL"));
 
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 
 #ifdef INET
 	if (inp->inp_vflag & INP_IPV4) {
@@ -920,7 +921,7 @@
 	/* XXXRW: so_state locking? */
 	so->so_state &= ~SS_ISCONNECTED;		/* XXX */
 out:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (0);
 }
@@ -936,7 +937,7 @@
 	KASSERT(inp != NULL, ("udp6_send: inp == NULL"));
 
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (addr) {
 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
 			error = EINVAL;
@@ -989,12 +990,12 @@
 #endif
 	error = udp6_output(inp, m, addr, control, td);
 out:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (error);
 
 bad:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	m_freem(m);
 	return (error);
Index: sys/netinet6/in6_src.c
===================================================================
--- sys/netinet6/in6_src.c	(revision 181343)
+++ sys/netinet6/in6_src.c	(working copy)
@@ -761,7 +761,7 @@
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	/* XXX: this is redundant when called from in6_pcbbind */
 	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
Index: sys/netinet6/in6_pcb.c
===================================================================
--- sys/netinet6/in6_pcb.c	(revision 181343)
+++ sys/netinet6/in6_pcb.c	(working copy)
@@ -121,7 +121,7 @@
 	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
 
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if (!in6_ifaddr) /* XXX broken! */
 		return (EADDRNOTAVAIL);
@@ -287,7 +287,7 @@
 	int scope_ambiguous = 0;
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if (nam->sa_len != sizeof (*sin6))
 		return (EINVAL);
@@ -354,7 +354,7 @@
 	int error;
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	/*
 	 * Call inner routine, to assign local interface address.
@@ -396,7 +396,7 @@
 {
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
 	inp->inp_fport = 0;
@@ -421,7 +421,7 @@
 
 	KASSERT(inp->inp_socket == NULL, ("in6_pcbfree: inp_socket != NULL"));
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 #ifdef IPSEC
 	if (inp->in6p_sp != NULL)
@@ -440,7 +440,7 @@
 #ifdef MAC
 	mac_destroy_inpcb(inp);
 #endif
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	uma_zfree(ipi->ipi_zone, inp);
 }
 
@@ -489,10 +489,10 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("in6_getsockaddr: inp == NULL"));
 
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	port = inp->inp_lport;
 	addr = inp->in6p_laddr;
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 
 	*nam = in6_sockaddr(port, &addr);
 	return 0;
@@ -508,10 +508,10 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("in6_getpeeraddr: inp == NULL"));
 
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	port = inp->inp_fport;
 	addr = inp->in6p_faddr;
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 
 	*nam = in6_sockaddr(port, &addr);
 	return 0;
@@ -611,9 +611,9 @@
 	errno = inet6ctlerrmap[cmd];
 	INP_INFO_WLOCK(pcbinfo);
 	LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) {
-		INP_LOCK(inp);
+		INP_WLOCK(inp);
 		if ((inp->inp_vflag & INP_IPV6) == 0) {
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			continue;
 		}
 
@@ -654,16 +654,16 @@
 			  !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
 					      &sa6_src.sin6_addr)) ||
 			 (fport && inp->inp_fport != fport)) {
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			continue;
 		}
 
 	  do_notify:
 		if (notify) {
 			if ((*notify)(inp, errno))
-				INP_UNLOCK(inp);
+				INP_WUNLOCK(inp);
 		} else
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 	}
 	INP_INFO_WUNLOCK(pcbinfo);
 }
@@ -764,7 +764,7 @@
 
 	INP_INFO_RLOCK(pcbinfo);
 	LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) {
-		INP_LOCK(in6p);
+		INP_WLOCK(in6p);
 		im6o = in6p->in6p_moptions;
 		if ((in6p->inp_vflag & INP_IPV6) &&
 		    im6o) {
@@ -791,7 +791,7 @@
 				}
 			}
 		}
-		INP_UNLOCK(in6p);
+		INP_WUNLOCK(in6p);
 	}
 	INP_INFO_RUNLOCK(pcbinfo);
 }
@@ -838,7 +838,7 @@
 	u_short fport = fport_arg, lport = lport_arg;
 	int faith;
 
-	INP_INFO_RLOCK_ASSERT(pcbinfo);
+	INP_INFO_LOCK_ASSERT(pcbinfo);
 
 	if (faithprefix_p != NULL)
 		faith = (*faithprefix_p)(laddr);
Index: sys/contrib/pf/net/pf.c
===================================================================
--- sys/contrib/pf/net/pf.c	(revision 181343)
+++ sys/contrib/pf/net/pf.c	(working copy)
@@ -3039,16 +3039,15 @@
 		return (-1);
 	}
 #ifdef __FreeBSD__
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
+	INP_INFO_RUNLOCK(pi);
 	if ((inp->inp_socket == NULL) || (inp->inp_socket->so_cred == NULL)) {
-		INP_UNLOCK(inp);
-		INP_INFO_RUNLOCK(pi);
+		INP_RUNLOCK(inp);
 		return (-1);
 	}
 	pd->lookup.uid = inp->inp_socket->so_cred->cr_uid;
 	pd->lookup.gid = inp->inp_socket->so_cred->cr_groups[0];
-	INP_UNLOCK(inp);
-	INP_INFO_RUNLOCK(pi);
+	INP_RUNLOCK(inp);
 #else
 	pd->lookup.uid = inp->inp_socket->so_euid;
 	pd->lookup.gid = inp->inp_socket->so_egid;
Index: sys/security/mac/mac_inet.c
===================================================================
--- sys/security/mac/mac_inet.c	(revision 181343)
+++ sys/security/mac/mac_inet.c	(working copy)
@@ -267,7 +267,7 @@
 mac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp)
 {
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 	SOCK_LOCK_ASSERT(so);
 	MAC_PERFORM(inpcb_sosetlabel, so, so->so_label, inp, inp->inp_label);
 }
@@ -326,7 +326,7 @@
 mac_init_syncache_from_inpcb(struct label *label, struct inpcb *inp)
 {
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 	MAC_PERFORM(init_syncache_from_inpcb, label, inp);
 }
 

Property changes on: sys/security/audit
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/security/audit:r178285,178318-178322,178325,178376-178378,178419,179412,179414,180127,180338,180343-180344,180346,180348,180368,180422,180429,180536,180558,180589,181364-181365

Index: sys/security/audit/audit_arg.c
===================================================================
--- sys/security/audit/audit_arg.c	(revision 181343)
+++ sys/security/audit/audit_arg.c	(working copy)
@@ -649,7 +649,7 @@
 			    so->so_proto->pr_protocol;
 			SOCK_UNLOCK(so);
 			pcb = (struct inpcb *)so->so_pcb;
-			INP_LOCK(pcb);
+			INP_RLOCK(pcb);
 			ar->k_ar.ar_arg_sockinfo.so_raddr =
 			    pcb->inp_faddr.s_addr;
 			ar->k_ar.ar_arg_sockinfo.so_laddr =
@@ -658,7 +658,7 @@
 			    pcb->inp_fport;
 			ar->k_ar.ar_arg_sockinfo.so_lport =
 			    pcb->inp_lport;
-			INP_UNLOCK(pcb);
+			INP_RUNLOCK(pcb);
 			ARG_SET_VALID(ar, ARG_SOCKINFO);
 		}
 		break;
