Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109459235
D29576.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D29576.diff
View Options
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -761,9 +761,10 @@
#define INPLOOKUP_WILDCARD 0x00000001 /* Allow wildcard sockets. */
#define INPLOOKUP_RLOCKPCB 0x00000002 /* Return inpcb read-locked. */
#define INPLOOKUP_WLOCKPCB 0x00000004 /* Return inpcb write-locked. */
+#define INPLOOKUP_RLOCKLISTEN 0x00000008 /* Rlock if listening, W if !.*/
#define INPLOOKUP_MASK (INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB | \
- INPLOOKUP_WLOCKPCB)
+ INPLOOKUP_WLOCKPCB | INPLOOKUP_RLOCKLISTEN)
#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb)
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -2518,31 +2518,24 @@
struct inpcb *inp;
inp = in_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport,
- (lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp,
- numa_domain);
+ lookupflags & INPLOOKUP_WILDCARD, ifp, numa_domain);
if (inp != NULL) {
if (lookupflags & INPLOOKUP_WLOCKPCB) {
INP_WLOCK(inp);
- if (__predict_false(inp->inp_flags2 & INP_FREED)) {
- INP_WUNLOCK(inp);
- inp = NULL;
- }
} else if (lookupflags & INPLOOKUP_RLOCKPCB) {
INP_RLOCK(inp);
- if (__predict_false(inp->inp_flags2 & INP_FREED)) {
- INP_RUNLOCK(inp);
- inp = NULL;
- }
+ } else if (lookupflags & INPLOOKUP_RLOCKLISTEN) {
+ if (inp->inp_socket != NULL &&
+ SOLISTENING(inp->inp_socket))
+ INP_RLOCK(inp);
+ else
+ INP_WLOCK(inp);
} else
panic("%s: locking bug", __func__);
-#ifdef INVARIANTS
- if (inp != NULL) {
- if (lookupflags & INPLOOKUP_WLOCKPCB)
- INP_WLOCK_ASSERT(inp);
- else
- INP_RLOCK_ASSERT(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+ INP_UNLOCK(inp);
+ inp = NULL;
}
-#endif
}
return (inp);
@@ -2564,8 +2557,8 @@
KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
- KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
- ("%s: LOCKPCB not set", __func__));
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB |
+ INPLOOKUP_RLOCKLISTEN)) != 0, ("%s: LOCKPCB not set", __func__));
/*
* When not using RSS, use connection groups in preference to the
@@ -2600,8 +2593,8 @@
KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
- KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
- ("%s: LOCKPCB not set", __func__));
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB |
+ INPLOOKUP_RLOCKLISTEN)) != 0, ("%s: LOCKPCB not set", __func__));
#ifdef PCBGROUP
/*
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -626,6 +626,7 @@
int drop_hdrlen;
int thflags;
int rstreason = 0; /* For badport_bandlim accounting purposes */
+ int lookupflag;
uint8_t iptos;
struct m_tag *fwd_tag = NULL;
#ifdef INET6
@@ -825,6 +826,12 @@
)
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ /*
+ * For initial SYN packets arriving on listening socket,
+ * we don't need write lock.
+ */
+ lookupflag = (thflags & (TH_ACK|TH_SYN)) == TH_SYN ?
+ INPLOOKUP_RLOCKLISTEN : INPLOOKUP_WLOCKPCB;
findpcb:
#ifdef INET6
if (isipv6 && fwd_tag != NULL) {
@@ -837,7 +844,7 @@
*/
inp = in6_pcblookup_mbuf(&V_tcbinfo,
&ip6->ip6_src, th->th_sport, &ip6->ip6_dst, th->th_dport,
- INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif, m);
+ lookupflag, m->m_pkthdr.rcvif, m);
if (!inp) {
/*
* It's new. Try to find the ambushing socket.
@@ -847,14 +854,13 @@
inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_src,
th->th_sport, &next_hop6->sin6_addr,
next_hop6->sin6_port ? ntohs(next_hop6->sin6_port) :
- th->th_dport, INPLOOKUP_WILDCARD |
- INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif);
+ th->th_dport, INPLOOKUP_WILDCARD | lookupflag,
+ m->m_pkthdr.rcvif);
}
} else if (isipv6) {
inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
th->th_sport, &ip6->ip6_dst, th->th_dport,
- INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
- m->m_pkthdr.rcvif, m);
+ INPLOOKUP_WILDCARD | lookupflag, m->m_pkthdr.rcvif, m);
}
#endif /* INET6 */
#if defined(INET6) && defined(INET)
@@ -870,8 +876,7 @@
* already got one like this?
*/
inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src, th->th_sport,
- ip->ip_dst, th->th_dport, INPLOOKUP_WLOCKPCB,
- m->m_pkthdr.rcvif, m);
+ ip->ip_dst, th->th_dport, lookupflag, m->m_pkthdr.rcvif, m);
if (!inp) {
/*
* It's new. Try to find the ambushing socket.
@@ -881,14 +886,13 @@
inp = in_pcblookup(&V_tcbinfo, ip->ip_src,
th->th_sport, next_hop->sin_addr,
next_hop->sin_port ? ntohs(next_hop->sin_port) :
- th->th_dport, INPLOOKUP_WILDCARD |
- INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif);
+ th->th_dport, INPLOOKUP_WILDCARD | lookupflag,
+ m->m_pkthdr.rcvif);
}
} else
inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
th->th_sport, ip->ip_dst, th->th_dport,
- INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
- m->m_pkthdr.rcvif, m);
+ INPLOOKUP_WILDCARD | lookupflag, m->m_pkthdr.rcvif, m);
#endif /* INET */
/*
@@ -918,14 +922,14 @@
rstreason = BANDLIM_RST_CLOSEDPORT;
goto dropwithreset;
}
- INP_WLOCK_ASSERT(inp);
+ INP_LOCK_ASSERT(inp);
/*
* While waiting for inp lock during the lookup, another thread
* can have dropped the inpcb, in which case we need to loop back
* and try to find a new inpcb to deliver to.
*/
if (inp->inp_flags & INP_DROPPED) {
- INP_WUNLOCK(inp);
+ INP_UNLOCK(inp);
inp = NULL;
goto findpcb;
}
@@ -1014,7 +1018,6 @@
#endif
#ifdef MAC
- INP_WLOCK_ASSERT(inp);
if (mac_inpcb_check_deliver(inp, m))
goto dropunlock;
#endif
@@ -1124,8 +1127,10 @@
* Socket is created in state SYN_RECEIVED.
* Unlock the listen socket, lock the newly
* created socket and update the tp variable.
+ * If we came here via jump to tfo_socket_result,
+ * then listening socket is read-locked.
*/
- INP_WUNLOCK(inp); /* listen socket */
+ INP_UNLOCK(inp); /* listen socket */
inp = sotoinpcb(so);
/*
* New connection inpcb is already locked by
@@ -1213,6 +1218,7 @@
("%s: Listen socket: TH_RST or TH_ACK set", __func__));
KASSERT(thflags & (TH_SYN),
("%s: Listen socket: TH_SYN not set", __func__));
+ INP_RLOCK_ASSERT(inp);
#ifdef INET6
/*
* If deprecated address is forbidden,
@@ -1381,7 +1387,7 @@
if (inp != NULL) {
tcp_dropwithreset(m, th, tp, tlen, rstreason);
- INP_WUNLOCK(inp);
+ INP_UNLOCK(inp);
} else
tcp_dropwithreset(m, th, NULL, tlen, rstreason);
m = NULL; /* mbuf chain got consumed. */
@@ -1392,7 +1398,7 @@
TCP_PROBE5(receive, NULL, tp, m, tp, th);
if (inp != NULL)
- INP_WUNLOCK(inp);
+ INP_UNLOCK(inp);
drop:
INP_INFO_WUNLOCK_ASSERT(&V_tcbinfo);
@@ -3360,7 +3366,7 @@
#endif
if (tp != NULL) {
- INP_WLOCK_ASSERT(tp->t_inpcb);
+ INP_LOCK_ASSERT(tp->t_inpcb);
}
/* Don't bother if destination was broadcast/multicast. */
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1428,7 +1428,7 @@
if (tp != NULL) {
inp = tp->t_inpcb;
KASSERT(inp != NULL, ("tcp control block w/o inpcb"));
- INP_WLOCK_ASSERT(inp);
+ INP_LOCK_ASSERT(inp);
} else
inp = NULL;
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1397,7 +1397,7 @@
int tfo_response_cookie_valid = 0;
bool locked;
- INP_WLOCK_ASSERT(inp); /* listen socket */
+ INP_RLOCK_ASSERT(inp); /* listen socket */
KASSERT((th->th_flags & (TH_RST|TH_ACK|TH_SYN)) == TH_SYN,
("%s: unexpected tcp flags", __func__));
@@ -1469,13 +1469,13 @@
#ifdef MAC
if (mac_syncache_init(&maclabel) != 0) {
- INP_WUNLOCK(inp);
+ INP_RUNLOCK(inp);
goto done;
} else
mac_syncache_create(maclabel, inp);
#endif
if (!tfo_cookie_valid)
- INP_WUNLOCK(inp);
+ INP_RUNLOCK(inp);
/*
* Remember the IP options, if any.
@@ -1528,7 +1528,7 @@
}
if (sc != NULL) {
if (tfo_cookie_valid)
- INP_WUNLOCK(inp);
+ INP_RUNLOCK(inp);
TCPSTAT_INC(tcps_sc_dupsyn);
if (ipopts) {
/*
@@ -1735,7 +1735,7 @@
if (tfo_cookie_valid) {
syncache_tfo_expand(sc, lsop, m, tfo_response_cookie);
- /* INP_WUNLOCK(inp) will be performed by the caller */
+ /* INP_RUNLOCK(inp) will be performed by the caller */
rv = 1;
goto tfo_expanded;
}
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -1293,31 +1293,24 @@
struct inpcb *inp;
inp = in6_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport,
- (lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp,
- numa_domain);
+ lookupflags & INPLOOKUP_WILDCARD, ifp, numa_domain);
if (inp != NULL) {
if (lookupflags & INPLOOKUP_WLOCKPCB) {
INP_WLOCK(inp);
- if (__predict_false(inp->inp_flags2 & INP_FREED)) {
- INP_WUNLOCK(inp);
- inp = NULL;
- }
} else if (lookupflags & INPLOOKUP_RLOCKPCB) {
INP_RLOCK(inp);
- if (__predict_false(inp->inp_flags2 & INP_FREED)) {
- INP_RUNLOCK(inp);
- inp = NULL;
- }
+ } else if (lookupflags & INPLOOKUP_RLOCKLISTEN) {
+ if (inp->inp_socket != NULL &&
+ SOLISTENING(inp->inp_socket))
+ INP_RLOCK(inp);
+ else
+ INP_WLOCK(inp);
} else
panic("%s: locking bug", __func__);
-#ifdef INVARIANTS
- if (inp != NULL) {
- if (lookupflags & INPLOOKUP_WLOCKPCB)
- INP_WLOCK_ASSERT(inp);
- else
- INP_RLOCK_ASSERT(inp);
+ if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+ INP_UNLOCK(inp);
+ inp = NULL;
}
-#endif
}
return (inp);
}
@@ -1338,8 +1331,8 @@
KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
- KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
- ("%s: LOCKPCB not set", __func__));
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB |
+ INPLOOKUP_RLOCKLISTEN)) != 0, ("%s: LOCKPCB not set", __func__));
/*
* When not using RSS, use connection groups in preference to the
@@ -1374,7 +1367,8 @@
KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
- KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB |
+ INPLOOKUP_RLOCKLISTEN)) != 0,
("%s: LOCKPCB not set", __func__));
#ifdef PCBGROUP
diff --git a/sys/security/mac/mac_inet.c b/sys/security/mac/mac_inet.c
--- a/sys/security/mac/mac_inet.c
+++ b/sys/security/mac/mac_inet.c
@@ -487,7 +487,7 @@
mac_syncache_create(struct label *label, struct inpcb *inp)
{
- INP_WLOCK_ASSERT(inp);
+ INP_LOCK_ASSERT(inp);
MAC_POLICY_PERFORM_NOSLEEP(syncache_create, label, inp);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Feb 6, 8:45 AM (20 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16490027
Default Alt Text
D29576.diff (10 KB)
Attached To
Mode
D29576: First take on syn-rlock.
Attached
Detach File
Event Timeline
Log In to Comment