From 8681082ba2aee22b256a2e32a36258ee4e1fc764 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Sat, 25 Dec 2004 22:44:04 +0000 Subject: Merge tcp_input.c:1.257, tcp_subr.c:1.211, tcp_timer.c:1.69 from HEAD to RELENG_5: date: 2004/11/23 17:21:30; author: rwatson; state: Exp; lines: +4 -0 date: 2004/11/23 17:21:30; author: rwatson; state: Exp; lines: +2 -0 date: 2004/11/23 17:21:30; author: rwatson; state: Exp; lines: +9 -0 tcp_timewait() performs multiple non-atomic reads on the tcptw structure, so assert the inpcb lock associated with the tcptw. Also assert the tcbinfo lock, as tcp_timewait() may call tcp_twclose() or tcp_2msl_rest(), which require it. Since tcp_timewait() is already called with that lock from tcp_input(), this doesn't change current locking, merely documents reasons for it. In tcp_twstart(), assert the tcbinfo lock, as tcp_timer_2msl_rest() is called, which requires that lock. In tcp_twclose(), assert the tcbinfo lock, as tcp_timer_2msl_stop() is called, which requires that lock. Document the locking strategy for the time wait queues in tcp_timer.c, which consists of protecting the time wait queues in the same manner as the tcbinfo structure (using the tcbinfo lock). In tcp_timer_2msl_reset(), assert the tcbinfo lock, as the time wait queues are modified. In tcp_timer_2msl_stop(), assert the tcbinfo lock, as the time wait queues may be modified. In tcp_timer_2msl_tw(), assert the tcbinfo lock, as the time wait queues may be modified. MFC after: 2 weeks --- sys/netinet/tcp_input.c | 4 ++++ sys/netinet/tcp_subr.c | 2 ++ sys/netinet/tcp_timer.c | 9 +++++++++ 3 files changed, 15 insertions(+) (limited to 'sys/netinet') diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index a58b4ca583a7..54a0560a8788 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -3235,6 +3235,10 @@ tcp_timewait(tw, to, th, m, tlen) const int isipv6 = 0; #endif + /* tcbinfo lock required for tcp_twclose(), tcp_2msl_reset. */ + INP_INFO_WLOCK_ASSERT(&tcbinfo); + INP_LOCK_ASSERT(tw->tw_inpcb); + thflags = th->th_flags; /* diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 91841aeca5d4..23dbfa803b9a 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1642,6 +1642,7 @@ tcp_twstart(tp) int tw_time, acknow; struct socket *so; + INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_reset(). */ INP_LOCK_ASSERT(tp->t_inpcb); tw = uma_zalloc(tcptw_zone, M_NOWAIT); @@ -1749,6 +1750,7 @@ tcp_twclose(struct tcptw *tw, int reuse) struct inpcb *inp; inp = tw->tw_inpcb; + INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_stop(). */ INP_LOCK_ASSERT(inp); tw->tw_inpcb = NULL; diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 420dedfc4817..f83a96d65a80 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -246,6 +246,12 @@ tcp_timer_2msl(xtp) INP_INFO_WUNLOCK(&tcbinfo); } +/* + * The timed wait lists contain references to each of the TCP sessions + * currently TIME_WAIT state. The list pointers, including the list pointers + * in each tcptw structure, are protected using the global tcbinfo lock, + * which must be held over list iteration and modification. + */ struct twlist { LIST_HEAD(, tcptw) tw_list; struct tcptw tw_tail; @@ -273,6 +279,7 @@ tcp_timer_2msl_reset(struct tcptw *tw, int timeo) int i; struct tcptw *tw_tail; + INP_INFO_WLOCK_ASSERT(&tcbinfo); if (tw->tw_time != 0) LIST_REMOVE(tw, tw_2msl); tw->tw_time = timeo + ticks; @@ -285,6 +292,7 @@ void tcp_timer_2msl_stop(struct tcptw *tw) { + INP_INFO_WLOCK_ASSERT(&tcbinfo); if (tw->tw_time != 0) LIST_REMOVE(tw, tw_2msl); } @@ -296,6 +304,7 @@ tcp_timer_2msl_tw(int reuse) struct twlist *twl; int i; + INP_INFO_WLOCK_ASSERT(&tcbinfo); for (i = 0; i < 2; i++) { twl = tw_2msl_list[i]; tw_tail = &twl->tw_tail; -- cgit v1.3