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-head mailing list