tcp: annotate sk->sk_sndbuf lockless reads
For the sake of tcp_poll(), there are few places where we fetch sk->sk_sndbuf while this field can change from IRQ or other cpu. We need to add READ_ONCE() annotations, and also make sure write sides use corresponding WRITE_ONCE() to avoid store-tearing. Note that other transports probably need similar fixes. 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
ebb3b78db7
commit
e292f05e0d
@@ -883,7 +883,7 @@ static inline int sk_stream_min_wspace(const struct sock *sk)
|
||||
|
||||
static inline int sk_stream_wspace(const struct sock *sk)
|
||||
{
|
||||
return sk->sk_sndbuf - sk->sk_wmem_queued;
|
||||
return READ_ONCE(sk->sk_sndbuf) - sk->sk_wmem_queued;
|
||||
}
|
||||
|
||||
void sk_stream_write_space(struct sock *sk);
|
||||
@@ -1207,7 +1207,7 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
|
||||
|
||||
static inline bool __sk_stream_memory_free(const struct sock *sk, int wake)
|
||||
{
|
||||
if (sk->sk_wmem_queued >= sk->sk_sndbuf)
|
||||
if (sk->sk_wmem_queued >= READ_ONCE(sk->sk_sndbuf))
|
||||
return false;
|
||||
|
||||
return sk->sk_prot->stream_memory_free ?
|
||||
@@ -2220,10 +2220,14 @@ static inline void sk_wake_async(const struct sock *sk, int how, int band)
|
||||
|
||||
static inline void sk_stream_moderate_sndbuf(struct sock *sk)
|
||||
{
|
||||
if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) {
|
||||
sk->sk_sndbuf = min(sk->sk_sndbuf, sk->sk_wmem_queued >> 1);
|
||||
sk->sk_sndbuf = max_t(u32, sk->sk_sndbuf, SOCK_MIN_SNDBUF);
|
||||
}
|
||||
u32 val;
|
||||
|
||||
if (sk->sk_userlocks & SOCK_SNDBUF_LOCK)
|
||||
return;
|
||||
|
||||
val = min(sk->sk_sndbuf, sk->sk_wmem_queued >> 1);
|
||||
|
||||
WRITE_ONCE(sk->sk_sndbuf, max_t(u32, val, SOCK_MIN_SNDBUF));
|
||||
}
|
||||
|
||||
struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp,
|
||||
@@ -2251,7 +2255,7 @@ bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag);
|
||||
*/
|
||||
static inline bool sock_writeable(const struct sock *sk)
|
||||
{
|
||||
return refcount_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf >> 1);
|
||||
return refcount_read(&sk->sk_wmem_alloc) < (READ_ONCE(sk->sk_sndbuf) >> 1);
|
||||
}
|
||||
|
||||
static inline gfp_t gfp_any(void)
|
||||
|
Reference in New Issue
Block a user