svn commit: r197795 - head/sys/netinet
Robert Watson
rwatson at FreeBSD.org
Mon Oct 5 22:24:14 UTC 2009
Author: rwatson
Date: Mon Oct 5 22:24:13 2009
New Revision: 197795
URL: http://svn.freebsd.org/changeset/base/197795
Log:
In tcp_input(), we acquire a global write lock at first only if a
segment is likely to trigger a TCP state change (i.e., FIN/RST/SYN).
If we later have to upgrade the lock, we acquire an inpcb reference
and drop both global/inpcb locks before reacquiring in-order. In
that gap, the connection may transition into TIMEWAIT, so we need
to loop back and reevaluate the inpcb after relocking.
MFC after: 3 days
Reported by: Kamigishi Rei <spambox at haruhiism.net>
Reviewed by: bz
Modified:
head/sys/netinet/tcp_input.c
Modified: head/sys/netinet/tcp_input.c
==============================================================================
--- head/sys/netinet/tcp_input.c Mon Oct 5 22:23:12 2009 (r197794)
+++ head/sys/netinet/tcp_input.c Mon Oct 5 22:24:13 2009 (r197795)
@@ -648,6 +648,7 @@ findpcb:
* tried to free the inpcb, in which case we need to loop back and
* try to find a new inpcb to deliver to.
*/
+relocked:
if (inp->inp_flags & INP_TIMEWAIT) {
KASSERT(ti_locked == TI_RLOCKED || ti_locked == TI_WLOCKED,
("%s: INP_TIMEWAIT ti_locked %d", __func__, ti_locked));
@@ -698,7 +699,8 @@ findpcb:
* We've identified a valid inpcb, but it could be that we need an
* inpcbinfo write lock and have only a read lock. In this case,
* attempt to upgrade/relock using the same strategy as the TIMEWAIT
- * case above.
+ * case above. If we relock, we have to jump back to 'relocked' as
+ * the connection might now be in TIMEWAIT.
*/
if (tp->t_state != TCPS_ESTABLISHED ||
(thflags & (TH_SYN | TH_FIN | TH_RST)) != 0 ||
@@ -720,6 +722,7 @@ findpcb:
goto findpcb;
}
tcp_wlock_relocked++;
+ goto relocked;
} else {
ti_locked = TI_WLOCKED;
tcp_wlock_upgraded++;
More information about the svn-src-all
mailing list