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