tcp: ensure proper barriers in lockless contexts
Some functions access TCP sockets without holding a lock and might output non consistent data, depending on compiler and or architecture. tcp_diag_get_info(), tcp_get_info(), tcp_poll(), get_tcp4_sock() ... Introduce sk_state_load() and sk_state_store() to fix the issues, and more clearly document where this lack of locking is happening. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
5883d9c6d7
commit
00fd38d938
@@ -2226,6 +2226,31 @@ static inline bool sk_listener(const struct sock *sk)
|
||||
return (1 << sk->sk_state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV);
|
||||
}
|
||||
|
||||
/**
|
||||
* sk_state_load - read sk->sk_state for lockless contexts
|
||||
* @sk: socket pointer
|
||||
*
|
||||
* Paired with sk_state_store(). Used in places we do not hold socket lock :
|
||||
* tcp_diag_get_info(), tcp_get_info(), tcp_poll(), get_tcp4_sock() ...
|
||||
*/
|
||||
static inline int sk_state_load(const struct sock *sk)
|
||||
{
|
||||
return smp_load_acquire(&sk->sk_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* sk_state_store - update sk->sk_state
|
||||
* @sk: socket pointer
|
||||
* @newstate: new state
|
||||
*
|
||||
* Paired with sk_state_load(). Should be used in contexts where
|
||||
* state change might impact lockless readers.
|
||||
*/
|
||||
static inline void sk_state_store(struct sock *sk, int newstate)
|
||||
{
|
||||
smp_store_release(&sk->sk_state, newstate);
|
||||
}
|
||||
|
||||
void sock_enable_timestamp(struct sock *sk, int flag);
|
||||
int sock_get_timestamp(struct sock *, struct timeval __user *);
|
||||
int sock_get_timestampns(struct sock *, struct timespec __user *);
|
||||
|
Reference in New Issue
Block a user