--- contrib/pf/net/pf.c	2007/11/21 10:16:46
+++ contrib/pf/net/pf.c	2008/01/06 23:09:29
@@ -2915,7 +2915,7 @@
 	pd->lookup.pid = NO_PID;		/* XXX: revisit */
 #ifdef __FreeBSD__
 	if (inp_arg != NULL) {
-		INP_LOCK_ASSERT(inp_arg);
+		INP_RLOCK_ASSERT(inp_arg);
 		if (inp_arg->inp_socket) {
 			pd->lookup.uid = inp_arg->inp_socket->so_cred->cr_uid;
 			pd->lookup.gid =
@@ -2967,6 +2967,9 @@
 #ifdef INET
 	case AF_INET:
 #ifdef __FreeBSD__
+		/*
+		 * XXXRW: rlock OK.
+		 */
 		INP_INFO_RLOCK(pi);	/* XXX LOR */
 		inp = in_pcblookup_hash(pi, saddr->v4, sport, daddr->v4,
 			dport, 0, NULL);
@@ -2991,6 +2994,9 @@
 #ifdef INET6
 	case AF_INET6:
 #ifdef __FreeBSD__
+		/*
+		 * XXXRW: rlock OK.
+		 */
 		INP_INFO_RLOCK(pi);
 		inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
 			&daddr->v6, dport, 0, NULL);
@@ -3018,15 +3024,15 @@
 		return (-1);
 	}
 #ifdef __FreeBSD__
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	if ((inp->inp_socket == NULL) || (inp->inp_socket->so_cred == NULL)) {
-		INP_UNLOCK(inp);
+		INP_RUNLOCK(inp);
 		INP_INFO_RUNLOCK(pi);
 		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_RUNLOCK(inp);
 	INP_INFO_RUNLOCK(pi);
 #else
 	pd->lookup.uid = inp->inp_socket->so_euid;
--- dev/cxgb/ulp/tom/cxgb_cpl_io.c	2007/12/17 10:06:58
+++ dev/cxgb/ulp/tom/cxgb_cpl_io.c	2008/01/06 23:09:29
@@ -191,9 +191,9 @@
 
 	
 	if (__predict_false(tp->t_state == TCPS_SYN_SENT)) {
-		INP_LOCK(tp->t_inpcb);
+		INP_WLOCK(tp->t_inpcb);
 		mbufq_tail(&toep->out_of_order_queue, m);  // defer
-		INP_UNLOCK(tp->t_inpcb);
+		INP_WUNLOCK(tp->t_inpcb);
 	} else if (through_l2t)
 		l2t_send(T3C_DEV(so), m, toep->tp_l2t);  // send through L2T
 	else
@@ -228,7 +228,7 @@
 	struct toepcb *toep = tp->t_toe;
 	struct tx_data_wr *req;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	req = mtod(m, struct tx_data_wr *);
 	m->m_len = sizeof(*req);
@@ -281,7 +281,7 @@
 		return (0);
 	}
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	
 	SOCKBUF_LOCK(&so->so_snd);
 	
@@ -401,7 +401,7 @@
 	unsigned int tid; 
 
 
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	tp = sototcpcb(so);
 	toep = tp->t_toe;
 	
@@ -409,7 +409,7 @@
 		t3_push_frames(so, 1);
 	
 	if (toep->tp_flags & TP_FIN_SENT) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		return;
 	}
 
@@ -426,7 +426,7 @@
 	req->wr.wr_lo = htonl(V_WR_TID(tid));
 	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
 	req->rsvd = htonl(toep->tp_write_seq);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	/*
 	 * XXX - need to defer shutdown while there is still data in the queue
 	 *
@@ -496,7 +496,7 @@
 	if (!((tp->t_state == TCPS_ESTABLISHED) || (tp->t_state == TCPS_FIN_WAIT_1) ||
 		(tp->t_state == TCPS_FIN_WAIT_2)))
 		return;
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	
 	so = tp->t_inpcb->inp_socket;
 	SOCKBUF_LOCK(&so->so_rcv);
@@ -592,7 +592,7 @@
 static int
 cxgb_toe_rcvd(struct tcpcb *tp)
 {
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	t3_cleanup_rbuf(tp);
 	
 	return (0);
@@ -801,7 +801,7 @@
 	if (!m)
 		return (ENOMEM);
 	
-	INP_LOCK_ASSERT(tp->t_inpcb);	
+	INP_WLOCK_ASSERT(tp->t_inpcb);	
 	m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, so));	
 	req = mtod(m, struct cpl_get_tcb *);
 	m->m_pkthdr.len = m->m_len = sizeof(*req);
@@ -919,7 +919,7 @@
 	
 	toep->tp_tp = NULL;
 	if (tp) {
-		INP_LOCK_ASSERT(tp->t_inpcb);
+		INP_WLOCK_ASSERT(tp->t_inpcb);
 		tp->t_toe = NULL;
 		tp->t_flags &= ~TF_TOE;
 	}
@@ -1143,7 +1143,7 @@
 
 	t3_release_offload_resources(toep);
 	if (tp) {
-		INP_LOCK_ASSERT(tp->t_inpcb);
+		INP_WLOCK_ASSERT(tp->t_inpcb);
 		cxgb_tcp_drop(tp, errno);
 	}
 	
@@ -1166,7 +1166,7 @@
 		goto done;
 
 	inp = toep->tp_tp->t_inpcb;
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 
 /*
  * Don't handle connection retry for now
@@ -1182,7 +1182,7 @@
 	} else
 #endif		
 		fail_act_open(toep, act_open_rpl_status_to_errno(rpl->status));
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 done:
 	INP_INFO_WUNLOCK(&tcbinfo);
 
@@ -1232,14 +1232,14 @@
 	struct inpcb *inp = tp->t_inpcb;
 	struct socket *so = toeptoso(toep);
 	
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (tp->t_state == TCPS_SYN_SENT || tp->t_state == TCPS_SYN_RECEIVED) {
 		fail_act_open(so, EHOSTUNREACH);
 		printf("freeing %p\n", m);
 		
 		m_free(m);
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 }
 #endif
 /*
@@ -1269,7 +1269,7 @@
 	if (!e)
 		goto free_tid;
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 	m = m_gethdr(MT_DATA, M_WAITOK);
 	
 #if 0	
@@ -1326,7 +1326,7 @@
 	struct mbuf *m;
 	
 	if (tp) {
-		INP_LOCK_ASSERT(tp->t_inpcb);
+		INP_WLOCK_ASSERT(tp->t_inpcb);
 		so = toeptoso(toep);
 	}
 	
@@ -1435,14 +1435,14 @@
 		inp = sotoinpcb(so);
 		tp = intotcpcb(inp);
 		    
-		INP_LOCK(inp);
+		INP_WLOCK(inp);
 		
 		oldval = tp->t_flags;
 		if (optval)
 			tp->t_flags |= TF_NODELAY;
 		else
 			tp->t_flags &= ~TF_NODELAY;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		
 		if (oldval != tp->t_flags)
 			t3_set_nagle(so);
@@ -1479,7 +1479,7 @@
 	struct socket *so = toeptoso(toep);
 	int len = be16toh(hdr->len);
 
-	INP_LOCK(tp->t_inpcb);
+	INP_WLOCK(tp->t_inpcb);
 	
 #ifdef notyet	
 	if (__predict_false(sk_no_receive(sk))) {
@@ -1545,7 +1545,7 @@
 	    ("so=%p, data contents exceed mbmax, sb_cc=%d sb_mbmax=%d",
 		so, so->so_rcv.sb_cc, so->so_rcv.sb_mbmax));
 	
-	INP_UNLOCK(tp->t_inpcb);
+	INP_WUNLOCK(tp->t_inpcb);
 	DPRINTF("sb_cc=%d sb_mbcnt=%d\n",
 	    so->so_rcv.sb_cc, so->so_rcv.sb_mbcnt);
 	    
@@ -1785,7 +1785,7 @@
 {
 	struct tcpcb *tp = sototcpcb(so);
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	/*
 	 * Bump rcv_nxt for the peer FIN.  We don't do this at the time we
 	 * process peer_close because we don't want to carry the peer FIN in
@@ -1832,7 +1832,7 @@
 	sock_set_flag(so, SOCK_DONE);
 #endif
 	INP_INFO_WLOCK(&tcbinfo);
-	INP_LOCK(tp->t_inpcb);
+	INP_WLOCK(tp->t_inpcb);
 	if (TCPS_HAVERCVDFIN(tp->t_state) == 0) 
 		socantrcvmore(so);
 	switch (tp->t_state) {
@@ -1868,7 +1868,7 @@
 	}
 	INP_INFO_WUNLOCK(&tcbinfo);
 	if (tp)
-		INP_UNLOCK(tp->t_inpcb);					
+		INP_WUNLOCK(tp->t_inpcb);					
 
 	if (!dead) {
 		DPRINTF("waking up waiters on %p rcv_notify=%d flags=0x%x\n", so, sb_notify(&so->so_rcv), so->so_rcv.sb_flags);
@@ -1922,7 +1922,7 @@
 		goto out;
 	
 	INP_INFO_WLOCK(&tcbinfo);
-	INP_LOCK(tp->t_inpcb);
+	INP_WLOCK(tp->t_inpcb);
 	switch (tp->t_state) {
 	case TCPS_CLOSING:              /* see FIN_WAIT2 case in do_peer_fin */
 		t3_release_offload_resources(toep);
@@ -1968,7 +1968,7 @@
 	}
 	INP_INFO_WUNLOCK(&tcbinfo);
 	if (tp)
-		INP_UNLOCK(tp->t_inpcb);
+		INP_WUNLOCK(tp->t_inpcb);
 out:
 	m_free(m);
 }
@@ -2006,7 +2006,7 @@
 		  "process_abort_rpl: GTS rpl pending %d",
 		  sock_flag(sk, ABORT_RPL_PENDING));
 #endif
-	INP_LOCK(tp->t_inpcb);
+	INP_WLOCK(tp->t_inpcb);
 	
 	if (toep->tp_flags & TP_ABORT_RPL_PENDING) {
 		/*
@@ -2021,7 +2021,7 @@
 				if (toep->tp_flags & TP_ABORT_REQ_RCVD)
 					panic("TP_ABORT_REQ_RCVD set");
 				INP_INFO_WLOCK(&tcbinfo);
-				INP_LOCK(tp->t_inpcb);
+				INP_WLOCK(tp->t_inpcb);
 				t3_release_offload_resources(toep);
 				tp = tcp_close(tp);
 				INP_INFO_WUNLOCK(&tcbinfo);
@@ -2029,7 +2029,7 @@
 		}
 	}
 	if (tp)
-		INP_UNLOCK(tp->t_inpcb);
+		INP_WUNLOCK(tp->t_inpcb);
 
 	m_free(m);
 }
@@ -2215,12 +2215,12 @@
 	if (__predict_false(parenttp->t_state == TCPS_LISTEN)) {
 		cleanup_syn_rcv_conn(child, parent);
 		INP_INFO_WLOCK(&tcbinfo);
-		INP_LOCK(childtp->t_inpcb);
+		INP_WLOCK(childtp->t_inpcb);
 		t3_release_offload_resources(childtp->t_toe);
 		childtp = tcp_close(childtp);
 		INP_INFO_WUNLOCK(&tcbinfo);
 		if (childtp)
-			INP_UNLOCK(childtp->t_inpcb);
+			INP_WUNLOCK(childtp->t_inpcb);
 	}
 }
 #endif
@@ -2268,7 +2268,7 @@
 	struct tcpcb *tp = sototcpcb(so);
 	struct toepcb *toep = tp->t_toe;
 
-	INP_LOCK(tp->t_inpcb);
+	INP_WLOCK(tp->t_inpcb);
 	if ((toep->tp_flags & TP_ABORT_REQ_RCVD) == 0) {
 		toep->tp_flags |= (TP_ABORT_REQ_RCVD|TP_ABORT_SHUTDOWN);
 		m_free(m);
@@ -2304,12 +2304,12 @@
 		tp = tcp_close(tp);
 	}
 	if (tp)
-		INP_UNLOCK(tp->t_inpcb);	
+		INP_WUNLOCK(tp->t_inpcb);	
 	send_abort_rpl(m, tdev, rst_status);
 	return;
 	
 skip:
-	INP_UNLOCK(tp->t_inpcb);		
+	INP_WUNLOCK(tp->t_inpcb);		
 }
 
 /*
@@ -2545,7 +2545,7 @@
 	to.to_flags = (mss ? TOF_MSS : 0) | (wsf ? TOF_SCALE : 0) | (ts ? TOF_TS : 0) | (sack ? TOF_SACKPERM : 0);
 
 	INP_INFO_WLOCK(&tcbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	syncache_offload_add(&inc, &to, &th, inp, &lso, &cxgb_toe_usrreqs, toep);
 }
 
@@ -2802,7 +2802,7 @@
 	struct tcpcb *tp = sototcpcb(so);
 	struct toepcb *toep = tp->t_toe;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	
 	toep->tp_mss_clamp = td->mtus[G_TCPOPT_MSS(opt)] - 40;
 	tp->t_flags         |= G_TCPOPT_TSTAMP(opt) ? TF_RCVD_TSTMP : 0;
@@ -2947,7 +2947,7 @@
 	toepcb_release(toep);
 	
 	tp = sototcpcb(so);
-	INP_LOCK(tp->t_inpcb);
+	INP_WLOCK(tp->t_inpcb);
 #ifdef notyet	
 	so->so_snd.sb_flags |= SB_TOE;
 	so->so_rcv.sb_flags |= SB_TOE;
@@ -2974,7 +2974,7 @@
 	     
 	make_established(so, ntohl(req->snd_isn), ntohs(req->tcp_opt));
 	INP_INFO_WUNLOCK(&tcbinfo);
-	INP_UNLOCK(tp->t_inpcb);
+	INP_WUNLOCK(tp->t_inpcb);
 	soisconnected(so);
 	
 #ifdef notyet
@@ -3022,7 +3022,7 @@
 
 	printf("fixup_and_send_ofo\n");
 	
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 	while ((m = mbufq_dequeue(&toep->out_of_order_queue)) != NULL) {
 		/*
 		 * A variety of messages can be waiting but the fields we'll
@@ -3125,7 +3125,7 @@
 	tdev = TOE_DEV(so); /* blow up here if link was down */
 	d = TOM_DATA(tdev);
 	
-	INP_LOCK(tp->t_inpcb);
+	INP_WLOCK(tp->t_inpcb);
 	
 	/*
 	 * It's OK if the TID is currently in use, the owning socket may have
@@ -3138,7 +3138,7 @@
 	toep->tp_qset = G_QNUM(ntohl(m->m_pkthdr.csum_data));
 
 	socket_act_establish(so, m);
-	INP_UNLOCK(tp->t_inpcb);
+	INP_WUNLOCK(tp->t_inpcb);
 	return (0);
 }
 
@@ -3158,7 +3158,7 @@
 	
 	DPRINTF("wr_ack: snd_una=%u credits=%d\n", snd_una, credits);
 
-	INP_LOCK(tp->t_inpcb);
+	INP_WLOCK(tp->t_inpcb);
 	
 	toep->tp_wr_avail += credits;
 	if (toep->tp_wr_unacked > toep->tp_wr_max - toep->tp_wr_avail)
@@ -3238,7 +3238,7 @@
 		t3_push_frames(so, 0);
 
 out_free:
-	INP_UNLOCK(tp->t_inpcb);
+	INP_WUNLOCK(tp->t_inpcb);
 	m_free(m);
 }
 
@@ -3290,9 +3290,9 @@
 		tp = sototcpcb(so);
 		
 		if (tp->t_flags & TF_TOE) {
-			INP_LOCK(tp->t_inpcb);
+			INP_WLOCK(tp->t_inpcb);
 			t3_reset_listen_child(so);
-			INP_UNLOCK(tp->t_inpcb);
+			INP_WUNLOCK(tp->t_inpcb);
 		}
 		
 	}
--- dev/cxgb/ulp/tom/cxgb_tcp_subr.c	2007/12/17 08:22:48
+++ dev/cxgb/ulp/tom/cxgb_tcp_subr.c	2008/01/06 23:09:29
@@ -211,7 +211,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;
@@ -236,7 +236,7 @@
 	struct socket *so;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	if (tp->t_state == TCPS_LISTEN)
 		tcp_gen_listen_close(tp);
@@ -249,7 +249,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;
@@ -273,7 +273,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))
@@ -362,7 +362,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)) {
@@ -411,7 +411,7 @@
 				}
 			}
 			if (inp != NULL)
-				INP_UNLOCK(inp);
+				INP_WUNLOCK(inp);
 		} else {
 			inc.inc_fport = th->th_dport;
 			inc.inc_lport = th->th_sport;
@@ -563,7 +563,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))
@@ -661,7 +661,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
@@ -673,15 +673,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 = cxgb_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);
--- dev/cxgb/ulp/tom/cxgb_tcp_usrreq.c	2007/12/17 08:22:48
+++ dev/cxgb/ulp/tom/cxgb_tcp_usrreq.c	2008/01/06 23:09:29
@@ -161,7 +161,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"));
@@ -254,7 +254,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);
@@ -287,7 +287,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;
@@ -327,7 +327,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;
@@ -373,7 +373,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;
@@ -410,7 +410,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;
@@ -470,7 +470,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;
@@ -513,7 +513,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;
@@ -573,7 +573,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;
@@ -608,7 +608,7 @@
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = ECONNABORTED;
 		goto out;
@@ -650,7 +650,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;
@@ -699,7 +699,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;
@@ -731,7 +731,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;
@@ -781,7 +781,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);
@@ -920,7 +920,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"));
 
@@ -958,7 +958,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"));
 
@@ -996,7 +996,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;
@@ -1087,7 +1087,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);
@@ -1142,7 +1142,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);
@@ -1281,7 +1281,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
@@ -1319,7 +1319,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:
--- dev/cxgb/ulp/tom/cxgb_tom.c	2007/12/17 08:22:48
+++ dev/cxgb/ulp/tom/cxgb_tom.c	2008/01/05 21:18:08
@@ -425,7 +425,11 @@
 {
 	struct inpcb *inp;
 	struct tcpcb *tp;
-	
+
+	/*
+	 * XXXRW: rlock OK.
+	 * XXXRW: shouldn't this lock the inpcb?
+	 */
 	INP_INFO_RLOCK(&tcbinfo);
 	LIST_FOREACH(inp, tcbinfo.ipi_listhead, inp_list) {
 		tp = intotcpcb(inp);
--- kern/subr_witness.c	2007/12/25 17:56:52
+++ kern/subr_witness.c	2008/01/06 23:42:45
@@ -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 },
 	/*
--- netinet/in_mcast.c	2007/08/06 22:20:57
+++ netinet/in_mcast.c	2008/01/06 23:09:29
@@ -651,7 +651,7 @@
 	}
 
 out_locked:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -667,11 +667,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);
@@ -698,7 +698,7 @@
 	}
 	imo->imo_mfilters = imfp;
 
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_moptions != NULL) {
 		free(imfp, M_IPMSOURCE);
 		free(immp, M_IPMOPTS);
@@ -762,12 +762,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));
@@ -781,7 +781,7 @@
 	if (ifp == NULL)
 		return (EINVAL);
 
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 
 	/*
 	 * Lookup group on the socket.
@@ -789,7 +789,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);
 	}
 
@@ -826,7 +826,7 @@
 		}
 	}
 
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 
 	if (tss != NULL) {
 		error = copyout(tss, msfr.msfr_srcs,
@@ -855,7 +855,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,
@@ -864,7 +864,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);
 	}
 
@@ -875,7 +875,7 @@
 			optval = imo->imo_multicast_vif;
 		else
 			optval = -1;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		error = sooptcopyout(sopt, &optval, sizeof(int));
 		break;
 
@@ -894,7 +894,7 @@
 				}
 			}
 		}
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) {
 			error = sooptcopyout(sopt, &mreqn,
 			    sizeof(struct ip_mreqn));
@@ -909,7 +909,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
@@ -921,7 +921,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
@@ -931,14 +931,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;
 	}
@@ -1192,14 +1192,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);
 }
 
@@ -1382,7 +1382,7 @@
 	imo->imo_num_memberships--;
 
 out_locked:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -1454,7 +1454,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);
 }
@@ -1545,7 +1545,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",
@@ -1646,7 +1646,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));
@@ -1661,11 +1661,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);
 }
 
@@ -1716,7 +1716,7 @@
 		}
 		imo = inp_findmoptions(inp);
 		imo->imo_multicast_vif = vifi;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		break;
 	}
 
@@ -1753,7 +1753,7 @@
 		}
 		imo = inp_findmoptions(inp);
 		imo->imo_multicast_ttl = ttl;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		break;
 	}
 
@@ -1782,7 +1782,7 @@
 		}
 		imo = inp_findmoptions(inp);
 		imo->imo_multicast_loop = !!loop;
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		break;
 	}
 
--- netinet/in_pcb.c	2007/12/22 10:12:29
+++ netinet/in_pcb.c	2008/01/06 23:09:29
@@ -178,6 +178,9 @@
 	struct inpcb *inp;
 	int error;
 
+	/*
+	 * XXXRW: wlock assert OK.
+	 */
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
 	error = 0;
 	inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT);
@@ -218,7 +221,7 @@
 	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)
@@ -234,8 +237,11 @@
 {
 	int anonport, error;
 
+	/*
+	 * XXXRW: wlock assert OK.
+	 */
 	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);
@@ -278,7 +284,10 @@
 	int error, prison = 0;
 	int dorandom;
 
-	INP_INFO_WLOCK_ASSERT(pcbinfo);
+	/*
+	 * XXXRW: lock assert OK.
+	 */
+	INP_INFO_LOCK_ASSERT(pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
 	if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */
@@ -502,8 +511,11 @@
 	in_addr_t laddr, faddr;
 	int anonport, error;
 
+	/*
+	 * XXXRW: wlock assert OK.
+	 */
 	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;
@@ -565,7 +577,10 @@
 	u_short lport, fport;
 	int error;
 
-	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
+	/*
+	 * XXXRW: lock assert OK.
+	 */
+	INP_INFO_LOCK_ASSERT(inp->inp_pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
 	if (oinpp != NULL)
@@ -684,8 +699,11 @@
 in_pcbdisconnect(struct inpcb *inp)
 {
 
+	/*
+	 * XXXRW: wlock assert OK.
+	 */
 	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;
@@ -714,8 +732,12 @@
 	struct inpcbinfo *ipi = inp->inp_pcbinfo;
 
 	KASSERT(inp->inp_socket == NULL, ("in_pcbfree: inp_socket != NULL"));
+
+	/*
+	 * XXXRW: wlock assert OK.
+	 */
 	INP_INFO_WLOCK_ASSERT(ipi);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 #ifdef IPSEC
 	ipsec4_delete_pcbpolicy(inp);
@@ -731,7 +753,7 @@
 #ifdef MAC
 	mac_inpcb_destroy(inp);
 #endif
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	uma_zfree(ipi->ipi_zone, inp);
 }
 
@@ -745,8 +767,11 @@
 in_pcbdrop(struct inpcb *inp)
 {
 
+	/*
+	 * XXXRW: wlock assert OK.
+	 */
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	inp->inp_vflag |= INP_DROPPED;
 	if (inp->inp_lport) {
@@ -790,10 +815,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;
@@ -809,10 +834,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;
@@ -825,24 +850,28 @@
 	struct inpcb *inp, *ninp;
 	struct inpcbhead *head;
 
+	/*
+	 * XXXRW: wlock assert OK, although could be an rlock for non-TCP
+	 * cases.
+	 */
 	INP_INFO_WLOCK(pcbinfo);
 	head = pcbinfo->ipi_listhead;
 	for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
-		INP_LOCK(inp);
+		INP_WLOCK(inp);
 		ninp = LIST_NEXT(inp, inp_list);
 #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,9 +883,12 @@
 	struct ip_moptions *imo;
 	int i, gap;
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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) {
@@ -882,7 +914,7 @@
 			}
 			imo->imo_num_memberships -= gap;
 		}
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 	}
 	INP_INFO_RUNLOCK(pcbinfo);
 }
@@ -904,7 +936,10 @@
 	int wildcard;
 	u_short lport = lport_arg;
 
-	INP_INFO_WLOCK_ASSERT(pcbinfo);
+	/*
+	 * XXXRW: lock assert OK.
+	 */
+	INP_INFO_LOCK_ASSERT(pcbinfo);
 
 	if (!wild_okay) {
 		struct inpcbhead *head;
@@ -1011,7 +1046,10 @@
 	struct inpcb *inp;
 	u_short fport = fport_arg, lport = lport_arg;
 
-	INP_INFO_RLOCK_ASSERT(pcbinfo);
+	/*
+	 * XXXRW: lock OK.
+	 */
+	INP_INFO_LOCK_ASSERT(pcbinfo);
 
 	/*
 	 * First look for an exact match.
@@ -1085,8 +1123,11 @@
 	struct inpcbport *phd;
 	u_int32_t hashkey_faddr;
 
+	/*
+	 * XXXRW: wlock assert OK.
+	 */
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 #ifdef INET6
 	if (inp->inp_vflag & INP_IPV6)
@@ -1139,8 +1180,11 @@
 	struct inpcbhead *head;
 	u_int32_t hashkey_faddr;
 
+	/*
+	 * XXXRW: wlock assert OK.
+	 */
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 #ifdef INET6
 	if (inp->inp_vflag & INP_IPV6)
@@ -1164,8 +1208,11 @@
 {
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 
+	/*
+	 * XXXRW: wlock assert OK.
+	 */
 	INP_INFO_WLOCK_ASSERT(pcbinfo);
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
 	if (inp->inp_lport) {
@@ -1195,11 +1242,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
 }
 
--- netinet/in_pcb.h	2007/12/07 01:46:38
+++ netinet/in_pcb.h	2008/01/06 23:09:29
@@ -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>		/* XXXRW: Avoid adding rwlock everywhere yet. */
+#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;
@@ -171,7 +176,7 @@
 	struct	inpcbport *inp_phd;	/* 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;
+	struct rwlock	inp_lock;
 
 #define	in6p_faddr	inp_inc.inc6_faddr
 #define	in6p_laddr	inp_inc.inc6_laddr
@@ -264,7 +269,7 @@
 	 * or freed.
 	 */
 	u_quad_t		 ipi_gencnt;
-	struct mtx		 ipi_mtx;
+	struct rwlock		 ipi_lock;
 
 	/*
 	 * vimage 1
@@ -273,24 +278,33 @@
 	void 			*ipi_pspare[2];	
 };
 
+/*
+ * XXXRW: rwlock(9) doesn't support classes, only names, unlike mutexes, so
+ * we use the class as the name.  What should we be doing?
+ */
 #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_LOCK_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_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)
 
 #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_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))
--- netinet/ip_divert.c	2007/10/24 19:06:35
+++ netinet/ip_divert.c	2008/01/06 23:09:29
@@ -266,9 +266,12 @@
 	/* Put packet on socket queue, if any */
 	sa = NULL;
 	nport = htons((u_int16_t)divert_info(mtag));
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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 +283,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 +359,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 +367,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 +408,7 @@
 				if (options == NULL)
 					error = ENOBUFS;
 			}
-			INP_UNLOCK(inp);
+			INP_RUNLOCK(inp);
 			INP_INFO_WUNLOCK(&divcbinfo);
 			if (error == ENOBUFS) {
 				m_freem(m);
@@ -480,7 +483,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 +495,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 +520,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 +534,10 @@
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("div_shutdown: inp == NULL"));
-	INP_LOCK(inp);
+	/* XXXRW: Perhaps INP_RLOCK? */
+	INP_WLOCK(inp);
 	socantsendmore(so);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return 0;
 }
 
@@ -590,6 +594,9 @@
 	/*
 	 * OK, now we're committed to doing something.
 	 */
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&divcbinfo);
 	gencnt = divcbinfo.ipi_gencnt;
 	n = divcbinfo.ipi_count;
@@ -615,11 +622,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 +634,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 +643,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) {
 		/*
--- netinet/ip_fw2.c	2007/12/09 15:35:46
+++ netinet/ip_fw2.c	2008/01/06 23:09:29
@@ -2013,6 +2013,9 @@
 		return 0;
 	match = 0;
 	if (*lookup == 0) {
+		/*
+		 * XXXRW: rlock OK.
+		 */
 		INP_INFO_RLOCK(pi);
 		pcb =  (oif) ?
 			in_pcblookup_hash(pi,
@@ -2024,12 +2027,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) {
--- netinet/ip_options.c	2007/10/24 19:06:35
+++ netinet/ip_options.c	2008/01/06 23:09:29
@@ -589,7 +589,7 @@
 	struct mbuf **pcbopt;
 	u_char opt;
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 
 	pcbopt = &inp->inp_options;
 
--- netinet/ip_output.c	2007/10/24 19:06:35
+++ netinet/ip_output.c	2008/01/06 23:09:29
@@ -415,6 +415,11 @@
 
 sendit:
 #ifdef IPSEC
+	/*
+	 * XXXRW: Check that it's OK with IPSEC that we may be passing down
+	 * a read lock on inpcb.  Is IPSEC using the inp lock to protect its
+	 * own data?
+	 */
 	switch(ip_ipsec_output(&m, inp, &flags, &error, &ro, &iproute, &dst, &ia, &ifp)) {
 	case 1:
 		goto bad;
@@ -433,6 +438,10 @@
 	if (!PFIL_HOOKED(&inet_pfil_hook))
 		goto passout;
 
+	/*
+	 * XXXRW: Confirm that pfil users aren't piggy-backing on the inpcb
+	 * lock to protect data.
+	 */
 	/* Run through list of hooks for output packets. */
 	odst.s_addr = ip->ip_dst.s_addr;
 	error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, inp);
@@ -833,9 +842,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);
 		}
 
@@ -872,12 +881,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:
@@ -944,7 +953,7 @@
 			if (error)
 				break;
 
-			INP_LOCK(inp);
+			INP_WLOCK(inp);
 			switch (optval) {
 			case IP_PORTRANGE_DEFAULT:
 				inp->inp_flags &= ~(INP_LOWPORT);
@@ -965,7 +974,7 @@
 				error = EINVAL;
 				break;
 			}
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			break;
 
 #ifdef IPSEC
--- netinet/raw_ip.c	2007/10/24 19:06:35
+++ netinet/raw_ip.c	2008/01/06 23:09:29
@@ -157,6 +157,9 @@
 
 	INP_LOCK_ASSERT(last);
 
+	/*
+	 * XXXRW: Check that IPSEC doesn't mind a read-locked inpcb.
+	 */
 #ifdef IPSEC
 	/* check AH/ESP integrity. */
 	if (ipsec4_in_reject(n, last)) {
@@ -205,14 +208,17 @@
 	int proto = ip->ip_p;
 	struct inpcb *inp, *last;
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&ripcbinfo);
 	ripsrc.sin_addr = ip->ip_src;
 	last = NULL;
 	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
@@ -236,14 +242,14 @@
 			if (n != NULL)
 				(void) raw_append(last, ip, n);
 			/* XXX count dropped packet */
-			INP_UNLOCK(last);
+			INP_RUNLOCK(last);
 		}
 		last = inp;
 	}
 	if (last != NULL) {
 		if (raw_append(last, ip, m) != 0)
 			ipstat.ips_delivered--;
-		INP_UNLOCK(last);
+		INP_RUNLOCK(last);
 	} else {
 		m_freem(m);
 		ipstat.ips_noproto++;
@@ -278,7 +284,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 +305,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 +321,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 +341,7 @@
 
 	error = ip_output(m, inp->inp_options, NULL, flags,
 	    inp->inp_moptions, inp);
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 	return error;
 }
 
@@ -621,7 +627,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;
 }
 
@@ -636,7 +642,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)
@@ -652,7 +658,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);
@@ -669,9 +675,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);
 }
 
@@ -684,9 +690,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);
 }
 
@@ -701,9 +707,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);
 }
@@ -734,9 +740,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;
 }
@@ -757,10 +763,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;
 }
@@ -770,11 +776,14 @@
 {
 	struct inpcb *inp;
 
+	/*
+	 * XXXRW: Actually, this could probably be a read lock...
+	 */
 	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;
 }
 
@@ -831,6 +840,9 @@
 	/*
 	 * OK, now we're committed to doing something.
 	 */
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&ripcbinfo);
 	gencnt = ripcbinfo.ipi_gencnt;
 	n = ripcbinfo.ipi_count;
@@ -847,17 +859,20 @@
 	inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
 	if (inp_list == 0)
 		return ENOMEM;
-	
+
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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;
@@ -865,7 +880,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));
@@ -874,10 +889,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) {
 		/*
@@ -887,6 +902,9 @@
 		 * while we were processing this request, and it
 		 * might be necessary to retry.
 		 */
+		/*
+		 * XXXRW: rlock OK.
+		 */
 		INP_INFO_RLOCK(&ripcbinfo);
 		xig.xig_gen = ripcbinfo.ipi_gencnt;
 		xig.xig_sogen = so_gencnt;
--- netinet/tcp_input.c	2007/10/24 19:06:35
+++ netinet/tcp_input.c	2008/01/06 23:09:29
@@ -476,7 +476,7 @@
 		rstreason = BANDLIM_RST_CLOSEDPORT;
 		goto dropwithreset;
 	}
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 
 #ifdef IPSEC
 #ifdef INET6
@@ -533,7 +533,7 @@
 	}
 
 #ifdef MAC
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 	if (mac_inpcb_check_deliver(inp, m))
 		goto dropunlock;
 #endif
@@ -631,9 +631,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__));
@@ -853,7 +853,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);
@@ -886,7 +886,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",
@@ -1330,7 +1330,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.
@@ -1938,7 +1938,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++;
@@ -2121,7 +2121,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.
@@ -2207,7 +2207,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,
@@ -2350,12 +2350,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:
@@ -2390,7 +2390,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;
 
@@ -2400,7 +2400,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;
@@ -2415,7 +2415,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);
@@ -2609,7 +2609,7 @@
 {
 	int delta;
 
-	INP_LOCK_ASSERT(tp->t_inpcb);
+	INP_WLOCK_ASSERT(tp->t_inpcb);
 
 	tcpstat.tcps_rttupdated++;
 	tp->t_rttupdated++;
--- netinet/tcp_output.c	2007/11/30 23:51:38
+++ netinet/tcp_output.c	2008/01/06 23:09:29
@@ -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,
--- netinet/tcp_reass.c	2007/10/07 20:49:19
+++ netinet/tcp_reass.c	2008/01/06 23:09:29
@@ -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
--- netinet/tcp_sack.c	2007/05/11 11:26:58
+++ netinet/tcp_sack.c	2008/01/06 23:09:29
@@ -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))
--- netinet/tcp_subr.c	2007/12/18 23:02:41
+++ netinet/tcp_subr.c	2008/01/06 23:09:29
@@ -332,6 +332,9 @@
 {
 	struct tcphdr *th = (struct tcphdr *)tcp_ptr;
 
+	/*
+	 * XXXRW: A read lock here is fine, but that won't ever happen.
+	 */
 	INP_LOCK_ASSERT(inp);
 
 #ifdef INET6
@@ -438,7 +441,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;
 
@@ -648,7 +651,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 +675,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 +773,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 +787,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;
@@ -811,11 +814,14 @@
 	 *	where we're really low on mbufs, this is potentially
 	 *	usefull.
 	 */
+		/*
+		 * XXXRW: rlock OK.
+		 */
 		INP_INFO_RLOCK(&tcbinfo);
 		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 +833,7 @@
 				}
 				tcp_clean_sackreport(tcpb);
 			}
-			INP_UNLOCK(inpb);
+			INP_WUNLOCK(inpb);
 		}
 		INP_INFO_RUNLOCK(&tcbinfo);
 	}
@@ -847,7 +853,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))
@@ -911,6 +917,9 @@
 	/*
 	 * OK, now we're committed to doing something.
 	 */
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&tcbinfo);
 	gencnt = tcbinfo.ipi_gencnt;
 	n = tcbinfo.ipi_count;
@@ -939,10 +948,13 @@
 	if (inp_list == NULL)
 		return (ENOMEM);
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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 +973,7 @@
 			if (error == 0)
 				inp_list[i++] = inp;
 		}
-		INP_UNLOCK(inp);
+		INP_RUNLOCK(inp);
 	}
 	INP_INFO_RUNLOCK(&tcbinfo);
 	n = i;
@@ -969,7 +981,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 +1005,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) {
@@ -1007,6 +1019,9 @@
 		 * while we were processing this request, and it
 		 * might be necessary to retry.
 		 */
+		/*
+		 * XXXRW: rlock OK.
+		 */
 		INP_INFO_RLOCK(&tcbinfo);
 		xig.xig_gen = tcbinfo.ipi_gencnt;
 		xig.xig_sogen = so_gencnt;
@@ -1035,6 +1050,9 @@
 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
 	if (error)
 		return (error);
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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);
@@ -1042,7 +1060,7 @@
 		error = ENOENT;
 		goto outunlocked;
 	}
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	if (inp->inp_socket == NULL) {
 		error = ENOENT;
 		goto out;
@@ -1052,7 +1070,7 @@
 		goto out;
 	cru2x(inp->inp_socket->so_cred, &xuc);
 out:
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 outunlocked:
 	INP_INFO_RUNLOCK(&tcbinfo);
 	if (error == 0)
@@ -1090,6 +1108,9 @@
 			return (EINVAL);
 	}
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&tcbinfo);
 	if (mapped == 1)
 		inp = in_pcblookup_hash(&tcbinfo,
@@ -1106,7 +1127,7 @@
 		error = ENOENT;
 		goto outunlocked;
 	}
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	if (inp->inp_socket == NULL) {
 		error = ENOENT;
 		goto out;
@@ -1116,7 +1137,7 @@
 		goto out;
 	cru2x(inp->inp_socket->so_cred, &xuc);
 out:
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 outunlocked:
 	INP_INFO_RUNLOCK(&tcbinfo);
 	if (error == 0)
@@ -1181,7 +1202,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)) {
@@ -1230,7 +1251,7 @@
 				}
 			}
 			if (inp != NULL)
-				INP_UNLOCK(inp);
+				INP_WUNLOCK(inp);
 		} else {
 			inc.inc_fport = th->th_dport;
 			inc.inc_lport = th->th_sport;
@@ -1381,7 +1402,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. */
@@ -1452,7 +1473,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))
@@ -1487,7 +1508,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);
@@ -1752,7 +1773,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,
@@ -2045,7 +2066,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
@@ -2057,15 +2078,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);
--- netinet/tcp_syncache.c	2007/12/19 17:01:59
+++ netinet/tcp_syncache.c	2008/01/06 23:09:29
@@ -670,7 +670,7 @@
 #endif
 
 	inp = sotoinpcb(so);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 
 	/* Insert new socket into PCB hash list. */
 	inp->inp_inc.inc_isipv6 = sc->sc_inc.inc_isipv6;
@@ -817,13 +817,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);
@@ -987,7 +987,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__));
 
@@ -1014,13 +1014,13 @@
 
 #ifdef MAC
 	if (mac_syncache_init(&maclabel) != 0) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&tcbinfo);
 		goto done;
 	} else
 		mac_syncache_create(maclabel, inp);
 #endif
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 
 	/*
--- netinet/tcp_timer.c	2007/10/07 20:49:19
+++ netinet/tcp_timer.c	2008/01/06 23:09:29
@@ -152,6 +152,9 @@
 	struct tcpcb *tp = xtp;
 	struct inpcb *inp;
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&tcbinfo);
 	inp = tp->t_inpcb;
 	/*
@@ -166,11 +169,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 +181,7 @@
 	tp->t_flags |= TF_ACKNOW;
 	tcpstat.tcps_delack++;
 	(void) tcp_output(tp);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 }
 
 void
@@ -208,11 +211,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 +250,7 @@
 			  PRU_SLOWTIMO);
 #endif
 	if (tp != NULL)
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 }
 
@@ -276,10 +279,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 +327,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 +341,7 @@
 			  PRU_SLOWTIMO);
 #endif
 	if (tp != NULL)
-		INP_UNLOCK(tp->t_inpcb);
+		INP_WUNLOCK(tp->t_inpcb);
 	INP_INFO_WUNLOCK(&tcbinfo);
 }
 
@@ -366,10 +369,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 +407,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 +438,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 +563,7 @@
 			  PRU_SLOWTIMO);
 #endif
 	if (tp != NULL)
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 	if (headlocked)
 		INP_INFO_WUNLOCK(&tcbinfo);
 }
--- netinet/tcp_timewait.c	2007/10/24 19:06:35
+++ netinet/tcp_timewait.c	2008/01/06 23:09:29
@@ -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);
--- netinet/tcp_usrreq.c	2007/12/18 23:02:41
+++ netinet/tcp_usrreq.c	2008/01/06 23:09:29
@@ -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);
 }
@@ -605,7 +605,7 @@
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 		error = ECONNABORTED;
 		goto out;
@@ -623,7 +623,7 @@
 
 out:
 	TCPDEBUG2(PRU_ACCEPT);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	if (error == 0)
 		*nam = in_sockaddr(port, &addr);
 	return error;
@@ -647,7 +647,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;
@@ -671,7 +671,7 @@
 
 out:
 	TCPDEBUG2(PRU_ACCEPT);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	if (error == 0) {
 		if (v4)
 			*nam = in6_v4mapsin6_sockaddr(port, &addr);
@@ -696,7 +696,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;
@@ -709,7 +709,7 @@
 
 out:
 	TCPDEBUG2(PRU_SHUTDOWN);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 
 	return (error);
@@ -728,7 +728,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;
@@ -739,7 +739,7 @@
 
 out:
 	TCPDEBUG2(PRU_RCVD);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -778,7 +778,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);
@@ -897,7 +897,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);
@@ -917,7 +917,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"));
 
@@ -937,7 +937,7 @@
 		SOCK_UNLOCK(so);
 		inp->inp_vflag |= INP_SOCKREF;
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 }
 
@@ -955,7 +955,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"));
 
@@ -976,7 +976,7 @@
 		SOCK_UNLOCK(so);
 		inp->inp_vflag |= INP_SOCKREF;
 	}
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 }
 
@@ -993,7 +993,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;
@@ -1018,7 +1018,7 @@
 
 out:
 	TCPDEBUG2(PRU_RCVOOB);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -1084,7 +1084,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);
@@ -1139,7 +1139,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);
@@ -1203,6 +1203,9 @@
 tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti)
 {
 
+	/*
+	 * XXXRW: lock assert OK.
+	 */
 	INP_LOCK_ASSERT(tp->t_inpcb);
 	bzero(ti, sizeof(*ti));
 
@@ -1252,9 +1255,9 @@
 	error = 0;
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("tcp_ctloutput: inp == NULL"));
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (sopt->sopt_level != IPPROTO_TCP) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 #ifdef INET6
 		if (INP_CHECK_SOCKAF(so, AF_INET6))
 			error = ip6_ctloutput(so, sopt);
@@ -1382,7 +1385,7 @@
 		break;
 	}
 out:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (error);
 }
 
@@ -1452,7 +1455,7 @@
 		return (ENOBUFS);
 	}
 	tp->t_state = TCPS_CLOSED;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&tcbinfo);
 	return (0);
 }
@@ -1472,7 +1475,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
@@ -1510,7 +1513,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:
--- netinet/udp_usrreq.c	2007/10/24 19:06:35
+++ netinet/udp_usrreq.c	2008/01/06 23:09:29
@@ -195,7 +195,7 @@
 	struct sockaddr_in6 udp_in6;
 #endif
 
-	INP_LOCK_ASSERT(inp);
+	INP_RLOCK_ASSERT(inp);
 
 #ifdef IPSEC
 	/* Check AH/ESP integrity. */
@@ -217,6 +217,11 @@
 		if (inp->inp_vflag & INP_IPV6) {
 			int savedflags;
 
+			/*
+			 * XXXRW: we have an rlock so this is bad.  Should
+			 * be passing a flag to ip6_savecontrol rather than
+			 * changing the inpcb flag.
+			 */
 			savedflags = inp->inp_flags;
 			inp->inp_flags &= ~INP_UNMAPPABLEOPTS;
 			ip6_savecontrol(inp, n, &opts);
@@ -382,6 +387,9 @@
 	}
 #endif
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&udbinfo);
 	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
 	    in_broadcast(ip->ip_dst, ifp)) {
@@ -412,7 +420,7 @@
 			    inp->inp_fport != uh->uh_sport)
 				continue;
 
-			INP_LOCK(inp);
+			INP_RLOCK(inp);
 
 			/*
 			 * Handle socket delivery policy for any-source
@@ -469,7 +477,7 @@
 					}
 				}
 				if (blocked != 0) {
-					INP_UNLOCK(inp);
+					INP_RUNLOCK(inp);
 					continue;
 				}
 			}
@@ -480,7 +488,7 @@
 				if (n != NULL)
 					udp_append(last, ip, n, iphlen +
 					    sizeof(struct udphdr), &udp_in);
-				INP_UNLOCK(last);
+				INP_RUNLOCK(last);
 			}
 			last = inp;
 			/*
@@ -507,7 +515,7 @@
 		}
 		udp_append(last, ip, m, iphlen + sizeof(struct udphdr),
 		    &udp_in);
-		INP_UNLOCK(last);
+		INP_RUNLOCK(last);
 		INP_INFO_RUNLOCK(&udbinfo);
 		return;
 	}
@@ -546,17 +554,17 @@
 	/*
 	 * Check the minimum TTL for socket.
 	 */
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl)
 		goto badheadlocked;
 	udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in);
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 	INP_INFO_RUNLOCK(&udbinfo);
 	return;
 
 badheadlocked:
 	if (inp)
-		INP_UNLOCK(inp);
+		INP_RUNLOCK(inp);
 	INP_INFO_RUNLOCK(&udbinfo);
 badunlocked:
 	m_freem(m);
@@ -570,6 +578,12 @@
 udp_notify(struct inpcb *inp, int errno)
 {
 
+	/*
+	 * XXXRW: Could be rlock assert, but in_pcbnotifyall() acquires a
+	 * wlock due to TCP.
+	 */
+	INP_LOCK_ASSERT(inp);
+
 	inp->inp_socket->so_error = errno;
 	sorwakeup(inp->inp_socket);
 	sowwakeup(inp->inp_socket);
@@ -606,15 +620,18 @@
 		return;
 	if (ip != NULL) {
 		uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
+		/*
+		 * XXXRW: rlock OK.
+		 */
 		INP_INFO_RLOCK(&udbinfo);
 		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
@@ -647,6 +664,9 @@
 	/*
 	 * OK, now we're committed to doing something.
 	 */
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&udbinfo);
 	gencnt = udbinfo.ipi_gencnt;
 	n = udbinfo.ipi_count;
@@ -669,14 +689,17 @@
 	if (inp_list == 0)
 		return (ENOMEM);
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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;
@@ -684,7 +707,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));
@@ -694,10 +717,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) {
 		/*
@@ -706,6 +729,9 @@
 		 * that something happened while we were processing this
 		 * request, and it might be necessary to retry.
 		 */
+		/*
+		 * XXXRW: rlock OK.
+		 */
 		INP_INFO_RLOCK(&udbinfo);
 		xig.xig_gen = udbinfo.ipi_gencnt;
 		xig.xig_sogen = so_gencnt;
@@ -734,6 +760,9 @@
 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
 	if (error)
 		return (error);
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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);
@@ -835,12 +864,33 @@
 		return (error);
 	}
 
-	if (src.sin_family == AF_INET || addr != NULL) {
+	/*
+	 * We may enter binding/connecting routines and manipulate global
+	 * address lists if a source address is requested explicitly, or if
+	 * an explicit destination is requested and a connect has not yet
+	 * been performed.  In these cases, acquire the global lock.
+	 *
+	 * XXXRW: In some of these cases, if may be sufficient to acquire a
+	 * read lock?
+	 *
+	 * XXXRW: This isn't right, as we are looking at the inp values
+	 * before acquiring the pcbinfo lock.  In the future, we'll want to
+	 * detect this race and handle it...
+	 */
+	if (addr != NULL && (inp->inp_laddr.s_addr == INADDR_ANY &&
+	    inp->inp_lport == 0)) {
 		INP_INFO_WLOCK(&udbinfo);
+		INP_WLOCK(inp);
+		unlock_udbinfo = 2;
+	} else if ((addr != NULL && (inp->inp_laddr.s_addr == INADDR_ANY ||
+	    inp->inp_lport == 0)) || src.sin_family == AF_INET) {
+		INP_INFO_RLOCK(&udbinfo);
+		INP_RLOCK(inp);
 		unlock_udbinfo = 1;
-	} else
+	} else {
 		unlock_udbinfo = 0;
-	INP_LOCK(inp);
+		INP_RLOCK(inp);
+	}
 
 #ifdef MAC
 	mac_inpcb_create_mbuf(inp, m);
@@ -854,6 +904,10 @@
 	laddr = inp->inp_laddr;
 	lport = inp->inp_lport;
 	if (src.sin_family == AF_INET) {
+		/*
+		 * XXXRW: lock assert OK.
+		 */
+		INP_INFO_LOCK_ASSERT(&udbinfo);
 		if ((lport == 0) ||
 		    (laddr.s_addr == INADDR_ANY &&
 		     src.sin_addr.s_addr == INADDR_ANY)) {
@@ -866,35 +920,82 @@
 			goto release;
 	}
 
+	/*
+	 * 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 local address/port
+	 * may not have been selected and bound.
+	 */
 	if (addr) {
+		if (inp->inp_faddr.s_addr != INADDR_ANY) {
+			error = EISCONN;
+			goto release;
+		}
+
+		/*
+		 * Jail may rewrite the destination address, so let it do
+		 * that before we use it.
+		 */
 		sin = (struct sockaddr_in *)addr;
 		if (jailed(td->td_ucred))
 			prison_remote_ip(td->td_ucred, 0,
 			    &sin->sin_addr.s_addr);
-		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 &&
+		/*
+		 * If local address or port hasn't yet been selected, do that
+		 * now.  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 (inp->inp_laddr.s_addr == INADDR_ANY ||
 		    inp->inp_lport == 0) {
 			/*
-			 * Remember addr if jailed, to prevent rebinding.
+			 * XXXRW: lock assert OK.
 			 */
-			if (jailed(td->td_ucred))
-				inp->inp_laddr = laddr;
-			inp->inp_lport = lport;
-			if (in_pcbinshash(inp) != 0) {
-				inp->inp_lport = 0;
-				error = EAGAIN;
+			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;
+
+			/*
+			 * XXXRW: Why not commit the port if the address is
+			 * !INADDR_ANY?
+			 */
+			/* Commit the local port if newly assigned. */
+			if (inp->inp_laddr.s_addr == INADDR_ANY &&
+			    inp->inp_lport == 0) {
+				/*
+				 * XXXRW: wlock assert OK.
+				 */
+				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 {
+			/*
+			 * XXXRW: Is it OK that we haven't checked for a
+			 * colliding binding for these foreign address and
+			 * port combined with the existing binding for local
+			 * address and port?
+			 */
+			faddr = sin->sin_addr;
+			fport = sin->sin_port;
 		}
 	} else {
 		faddr = inp->inp_faddr;
@@ -967,17 +1068,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_WUNLOCK(&udbinfo);
+	} else
+		INP_RUNLOCK(inp);
 	m_freem(m);
 	return (error);
 }
@@ -990,13 +1101,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);
 }
 
@@ -1022,7 +1133,7 @@
 	INP_INFO_WUNLOCK(&udbinfo);
 	inp->inp_vflag |= INP_IPV4;
 	inp->inp_ip_ttl = ip_defttl;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (0);
 }
 
@@ -1035,9 +1146,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);
 }
@@ -1050,13 +1161,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);
 }
 
@@ -1070,9 +1181,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);
 	}
@@ -1082,7 +1193,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);
 }
@@ -1097,7 +1208,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);
@@ -1111,10 +1222,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);
 	}
 
@@ -1123,7 +1234,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);
 }
@@ -1144,11 +1255,14 @@
 {
 	struct inpcb *inp;
 
+	/*
+	 * XXXRW: Possibly could be rlock.
+	 */
 	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);
 }
 
--- netinet6/icmp6.c	2007/12/10 16:07:50
+++ netinet6/icmp6.c	2008/01/06 23:09:29
@@ -1889,12 +1889,15 @@
 		return (IPPROTO_DONE);
 	}
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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)
@@ -1965,7 +1968,7 @@
 					sorwakeup_locked(last->in6p_socket);
 				opts = NULL;
 			}
-			INP_UNLOCK(last);
+			INP_RUNLOCK(last);
 		}
 		last = in6p;
 	}
@@ -2003,7 +2006,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--;
--- netinet6/in6_pcb.c	2007/12/17 17:22:20
+++ netinet6/in6_pcb.c	2008/01/06 23:09:29
@@ -122,7 +122,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);
@@ -288,7 +288,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_inpcb_destroy(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;
@@ -613,11 +613,11 @@
 	head = pcbinfo->ipi_listhead;
 	INP_INFO_WLOCK(pcbinfo);
 	for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
-		INP_LOCK(inp);
+		INP_WLOCK(inp);
 		ninp = LIST_NEXT(inp, inp_list);
 
 		if ((inp->inp_vflag & INP_IPV6) == 0) {
-			INP_UNLOCK(inp);
+			INP_WUNLOCK(inp);
 			continue;
 		}
 
@@ -658,16 +658,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);
 }
@@ -767,9 +767,12 @@
 	struct ip6_moptions *im6o;
 	struct in6_multi_mship *imm, *nimm;
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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) {
@@ -796,7 +799,7 @@
 				}
 			}
 		}
-		INP_UNLOCK(in6p);
+		INP_WUNLOCK(in6p);
 	}
 	INP_INFO_RUNLOCK(pcbinfo);
 }
@@ -843,7 +846,10 @@
 	u_short fport = fport_arg, lport = lport_arg;
 	int faith;
 
-	INP_INFO_RLOCK_ASSERT(pcbinfo);
+	/*
+	 * XXXRW: lock OK.
+	 */
+	INP_INFO_LOCK_ASSERT(pcbinfo);
 
 	if (faithprefix_p != NULL)
 		faith = (*faithprefix_p)(laddr);
--- netinet6/in6_src.c	2007/12/10 16:07:50
+++ netinet6/in6_src.c	2008/01/06 23:09:29
@@ -748,7 +748,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)
--- netinet6/raw_ip6.c	2007/12/10 16:07:50
+++ netinet6/raw_ip6.c	2008/01/06 23:09:29
@@ -152,12 +152,15 @@
 
 	init_sin6(&fromsa, m); /* general init */
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	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 &&
@@ -207,7 +210,7 @@
 					sorwakeup(last->in6p_socket);
 				opts = NULL;
 			}
-			INP_UNLOCK(last);
+			INP_RUNLOCK(last);
 		}
 		last = in6p;
 	}
@@ -220,7 +223,7 @@
 		ipsec6stat.in_polvio++;
 		ip6stat.ip6s_delivered--;
 		/* do not inject data into pcb */
-		INP_UNLOCK(last);
+		INP_RUNLOCK(last);
 	} else
 #endif /* IPSEC */
 	if (last) {
@@ -237,7 +240,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)
@@ -335,8 +338,13 @@
 	control = va_arg(ap, struct mbuf *);
 	va_end(ap);
 
+	/*
+	 * XXXRW: wlock here is unfortunate, but due to in6_selectsrc()
+	 * storing its results in in6p->in6p_laddr rather than a local
+	 * variable.
+	 */
 	in6p = sotoin6pcb(so);
-	INP_LOCK(in6p);
+	INP_WLOCK(in6p);
 
 	priv = 0;
 	if (suser_cred(so->so_cred, 0) == 0)
@@ -469,7 +477,7 @@
 		ip6_clearpktopts(&opt, -1);
 		m_freem(control);
 	}
-	INP_UNLOCK(in6p);
+	INP_WUNLOCK(in6p);
 	return (error);
 }
 
@@ -572,7 +580,7 @@
 	inp->in6p_cksum = -1;
 	inp->in6p_icmp6filt = filter;
 	ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return 0;
 }
 
@@ -588,7 +596,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;
@@ -659,9 +667,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;
 }
@@ -697,13 +705,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->in6p_moptions, NULL,
 			     &inp->in6p_laddr, &ifp, &error);
 	if (in6a == NULL) {
-		INP_UNLOCK(inp);
+		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&ripcbinfo);
 		return (error ? error : EADDRNOTAVAIL);
 	}
@@ -711,14 +719,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;
 }
@@ -728,11 +736,14 @@
 {
 	struct inpcb *inp;
 
+	/*
+	 * XXXRW: Technically, could use an rlock here.
+	 */
 	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;
 }
 
--- netinet6/udp6_usrreq.c	2007/12/10 16:07:50
+++ netinet6/udp6_usrreq.c	2008/01/06 23:09:29
@@ -129,6 +129,9 @@
 	struct socket *so;
 	struct mbuf *opts;
 
+	/*
+	 * XXXRW: lock assert OK.
+	 */
 	INP_LOCK_ASSERT(inp);
 
 #ifdef IPSEC
@@ -227,6 +230,9 @@
 	init_sin6(&fromsa, m);
 	fromsa.sin6_port = uh->uh_sport;
 
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&udbinfo);
 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
 		struct inpcb *last;
@@ -277,9 +283,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;
@@ -306,9 +312,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);
 	}
@@ -343,9 +349,9 @@
 		icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
 		return (IPPROTO_DONE);
 	}
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	udp6_append(inp, m, off, &fromsa);
-	INP_UNLOCK(inp);
+	INP_RUNLOCK(inp);
 	INP_INFO_RUNLOCK(&udbinfo);
 	return (IPPROTO_DONE);
 
@@ -445,6 +451,9 @@
 	    (error = sa6_embedscope(&addrs[1], ip6_use_defzone)) != 0) {
 		return (error);
 	}
+	/*
+	 * XXXRW: rlock OK.
+	 */
 	INP_INFO_RLOCK(&udbinfo);
 	inp = in6_pcblookup_hash(&udbinfo, &addrs[1].sin6_addr,
 	    addrs[1].sin6_port, &addrs[0].sin6_addr, addrs[0].sin6_port, 1,
@@ -453,7 +462,7 @@
 		INP_INFO_RUNLOCK(&udbinfo);
 		return (ENOENT);
 	}
-	INP_LOCK(inp);
+	INP_RLOCK(inp);
 	if (inp->inp_socket == NULL) {
 		error = ENOENT;
 		goto out;
@@ -463,7 +472,7 @@
 		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));
@@ -493,7 +502,12 @@
 	int flags;
 	struct sockaddr_in6 tmp;
 
-	INP_LOCK_ASSERT(inp);
+	/*
+	 * XXXRW: Could be rlock except for in6_selectsrc()?
+	 *
+	 * XXXRW: Check this.
+	 */
+	INP_WLOCK_ASSERT(inp);
 
 	priv = 0;
 	if (td && !suser(td))
@@ -713,13 +727,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);
 }
 
@@ -757,7 +771,7 @@
 	 * which may match an IPv4-mapped IPv6 address.
 	 */
 	inp->inp_ip_ttl = ip_defttl;
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	return (0);
 }
 
@@ -771,7 +785,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) {
@@ -795,7 +809,7 @@
 
 	error = in6_pcbbind(inp, nam, td->td_ucred);
 out:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (error);
 }
@@ -818,13 +832,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);
 }
 
@@ -838,7 +852,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;
 
@@ -875,7 +889,7 @@
 		soisconnected(so);
 	}
 out:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (error);
 }
@@ -889,7 +903,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);
@@ -905,7 +919,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) {
@@ -927,7 +941,7 @@
 	/* XXXRW: so_state locking? */
 	so->so_state &= ~SS_ISCONNECTED;		/* XXX */
 out:
-	INP_UNLOCK(inp);
+	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
 	return (0);
 }
@@ -942,8 +956,11 @@
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp6_send: inp == NULL"));
 
+	/*
+	 * XXXRW: When udp6_output() is rlock, make this rlock.
+	 */
 	INP_INFO_WLOCK(&udbinfo);
-	INP_LOCK(inp);
+	INP_WLOCK(inp);
 	if (addr) {
 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
 			error = EINVAL;
@@ -996,12 +1013,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);
--- security/audit/audit_arg.c	2007/06/27 17:03:26
+++ security/audit/audit_arg.c	2008/01/06 23:09:29
@@ -648,7 +648,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 =
@@ -657,7 +657,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;
--- security/mac/mac_inet.c	2007/10/28 17:17:19
+++ security/mac/mac_inet.c	2008/01/06 23:09:29
@@ -201,7 +201,7 @@
 {
 	struct label *mlabel;
 
-	INP_LOCK_ASSERT(inp);
+	INP_RLOCK_ASSERT(inp);
 	mlabel = mac_mbuf_to_label(m);
 
 	MAC_PERFORM(inpcb_create_mbuf, inp, inp->inp_label, m, mlabel);
@@ -306,7 +306,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);
 }
@@ -376,7 +376,7 @@
 mac_syncache_create(struct label *label, struct inpcb *inp)
 {
 
-	INP_LOCK_ASSERT(inp);
+	INP_WLOCK_ASSERT(inp);
 	MAC_PERFORM(syncache_create, label, inp);
 }
 
