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
This commit is contained in:
rwatson 2004-11-23 17:21:30 +00:00
parent 53e97a895b
commit 75d5a09a05
5 changed files with 21 additions and 0 deletions

View File

@ -3062,6 +3062,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;
/*

View File

@ -3062,6 +3062,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;
/*

View File

@ -1624,6 +1624,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);
@ -1722,6 +1723,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;

View File

@ -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;

View File

@ -1624,6 +1624,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);
@ -1722,6 +1723,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;