aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2019-10-10 23:17:46 -0400
committerDavid S. Miller <davem@davemloft.net>2019-10-13 13:13:08 -0400
commitab4e846a82d0ae00176de19f2db3c5c64f8eb5f2 (patch)
tree7be26ef02ab2f2979be9a3cdeb36ed1bafc51354
parente292f05e0df73f9fcc93329663936e1ded97a988 (diff)
tcp: annotate sk->sk_wmem_queued lockless reads
For the sake of tcp_poll(), there are few places where we fetch sk->sk_wmem_queued 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. sk_wmem_queued_add() helper is added so that we can in the future convert to ADD_ONCE() or equivalent if/when available. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sock.h15
-rw-r--r--include/trace/events/sock.h2
-rw-r--r--net/core/datagram.c2
-rw-r--r--net/core/sock.c2
-rw-r--r--net/ipv4/inet_diag.c2
-rw-r--r--net/ipv4/tcp.c4
-rw-r--r--net/ipv4/tcp_output.c14
-rw-r--r--net/sched/em_meta.c2
8 files changed, 24 insertions, 19 deletions
diff --git a/include/net/sock.h b/include/net/sock.h
index 3d1e7502333e..f69b58bff7e5 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -878,12 +878,17 @@ static inline bool sk_acceptq_is_full(const struct sock *sk)
878 */ 878 */
879static inline int sk_stream_min_wspace(const struct sock *sk) 879static inline int sk_stream_min_wspace(const struct sock *sk)
880{ 880{
881 return sk->sk_wmem_queued >> 1; 881 return READ_ONCE(sk->sk_wmem_queued) >> 1;
882} 882}
883 883
884static inline int sk_stream_wspace(const struct sock *sk) 884static inline int sk_stream_wspace(const struct sock *sk)
885{ 885{
886 return READ_ONCE(sk->sk_sndbuf) - sk->sk_wmem_queued; 886 return READ_ONCE(sk->sk_sndbuf) - READ_ONCE(sk->sk_wmem_queued);
887}
888
889static inline void sk_wmem_queued_add(struct sock *sk, int val)
890{
891 WRITE_ONCE(sk->sk_wmem_queued, sk->sk_wmem_queued + val);
887} 892}
888 893
889void sk_stream_write_space(struct sock *sk); 894void sk_stream_write_space(struct sock *sk);
@@ -1207,7 +1212,7 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
1207 1212
1208static inline bool __sk_stream_memory_free(const struct sock *sk, int wake) 1213static inline bool __sk_stream_memory_free(const struct sock *sk, int wake)
1209{ 1214{
1210 if (sk->sk_wmem_queued >= READ_ONCE(sk->sk_sndbuf)) 1215 if (READ_ONCE(sk->sk_wmem_queued) >= READ_ONCE(sk->sk_sndbuf))
1211 return false; 1216 return false;
1212 1217
1213 return sk->sk_prot->stream_memory_free ? 1218 return sk->sk_prot->stream_memory_free ?
@@ -1467,7 +1472,7 @@ DECLARE_STATIC_KEY_FALSE(tcp_tx_skb_cache_key);
1467static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb) 1472static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
1468{ 1473{
1469 sock_set_flag(sk, SOCK_QUEUE_SHRUNK); 1474 sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
1470 sk->sk_wmem_queued -= skb->truesize; 1475 sk_wmem_queued_add(sk, -skb->truesize);
1471 sk_mem_uncharge(sk, skb->truesize); 1476 sk_mem_uncharge(sk, skb->truesize);
1472 if (static_branch_unlikely(&tcp_tx_skb_cache_key) && 1477 if (static_branch_unlikely(&tcp_tx_skb_cache_key) &&
1473 !sk->sk_tx_skb_cache && !skb_cloned(skb)) { 1478 !sk->sk_tx_skb_cache && !skb_cloned(skb)) {
@@ -2014,7 +2019,7 @@ static inline int skb_copy_to_page_nocache(struct sock *sk, struct iov_iter *fro
2014 skb->len += copy; 2019 skb->len += copy;
2015 skb->data_len += copy; 2020 skb->data_len += copy;
2016 skb->truesize += copy; 2021 skb->truesize += copy;
2017 sk->sk_wmem_queued += copy; 2022 sk_wmem_queued_add(sk, copy);
2018 sk_mem_charge(sk, copy); 2023 sk_mem_charge(sk, copy);
2019 return 0; 2024 return 0;
2020} 2025}
diff --git a/include/trace/events/sock.h b/include/trace/events/sock.h
index f720c32e7dfd..51fe9f6719eb 100644
--- a/include/trace/events/sock.h
+++ b/include/trace/events/sock.h
@@ -115,7 +115,7 @@ TRACE_EVENT(sock_exceed_buf_limit,
115 __entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc); 115 __entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc);
116 __entry->sysctl_wmem = sk_get_wmem0(sk, prot); 116 __entry->sysctl_wmem = sk_get_wmem0(sk, prot);
117 __entry->wmem_alloc = refcount_read(&sk->sk_wmem_alloc); 117 __entry->wmem_alloc = refcount_read(&sk->sk_wmem_alloc);
118 __entry->wmem_queued = sk->sk_wmem_queued; 118 __entry->wmem_queued = READ_ONCE(sk->sk_wmem_queued);
119 __entry->kind = kind; 119 __entry->kind = kind;
120 ), 120 ),
121 121
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 4cc8dc5db2b7..c210fc116103 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -640,7 +640,7 @@ int __zerocopy_sg_from_iter(struct sock *sk, struct sk_buff *skb,
640 skb->len += copied; 640 skb->len += copied;
641 skb->truesize += truesize; 641 skb->truesize += truesize;
642 if (sk && sk->sk_type == SOCK_STREAM) { 642 if (sk && sk->sk_type == SOCK_STREAM) {
643 sk->sk_wmem_queued += truesize; 643 sk_wmem_queued_add(sk, truesize);
644 sk_mem_charge(sk, truesize); 644 sk_mem_charge(sk, truesize);
645 } else { 645 } else {
646 refcount_add(truesize, &skb->sk->sk_wmem_alloc); 646 refcount_add(truesize, &skb->sk->sk_wmem_alloc);
diff --git a/net/core/sock.c b/net/core/sock.c
index cd075bc86407..a515392ba84b 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -3212,7 +3212,7 @@ void sk_get_meminfo(const struct sock *sk, u32 *mem)
3212 mem[SK_MEMINFO_WMEM_ALLOC] = sk_wmem_alloc_get(sk); 3212 mem[SK_MEMINFO_WMEM_ALLOC] = sk_wmem_alloc_get(sk);
3213 mem[SK_MEMINFO_SNDBUF] = READ_ONCE(sk->sk_sndbuf); 3213 mem[SK_MEMINFO_SNDBUF] = READ_ONCE(sk->sk_sndbuf);
3214 mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc; 3214 mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc;
3215 mem[SK_MEMINFO_WMEM_QUEUED] = sk->sk_wmem_queued; 3215 mem[SK_MEMINFO_WMEM_QUEUED] = READ_ONCE(sk->sk_wmem_queued);
3216 mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc); 3216 mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc);
3217 mem[SK_MEMINFO_BACKLOG] = READ_ONCE(sk->sk_backlog.len); 3217 mem[SK_MEMINFO_BACKLOG] = READ_ONCE(sk->sk_backlog.len);
3218 mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops); 3218 mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops);
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index bbb005eb5218..7dc79b973e6e 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -193,7 +193,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
193 if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { 193 if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
194 struct inet_diag_meminfo minfo = { 194 struct inet_diag_meminfo minfo = {
195 .idiag_rmem = sk_rmem_alloc_get(sk), 195 .idiag_rmem = sk_rmem_alloc_get(sk),
196 .idiag_wmem = sk->sk_wmem_queued, 196 .idiag_wmem = READ_ONCE(sk->sk_wmem_queued),
197 .idiag_fmem = sk->sk_forward_alloc, 197 .idiag_fmem = sk->sk_forward_alloc,
198 .idiag_tmem = sk_wmem_alloc_get(sk), 198 .idiag_tmem = sk_wmem_alloc_get(sk),
199 }; 199 };
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 111853262972..b2ac4f074e2d 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -659,7 +659,7 @@ static void skb_entail(struct sock *sk, struct sk_buff *skb)
659 tcb->sacked = 0; 659 tcb->sacked = 0;
660 __skb_header_release(skb); 660 __skb_header_release(skb);
661 tcp_add_write_queue_tail(sk, skb); 661 tcp_add_write_queue_tail(sk, skb);
662 sk->sk_wmem_queued += skb->truesize; 662 sk_wmem_queued_add(sk, skb->truesize);
663 sk_mem_charge(sk, skb->truesize); 663 sk_mem_charge(sk, skb->truesize);
664 if (tp->nonagle & TCP_NAGLE_PUSH) 664 if (tp->nonagle & TCP_NAGLE_PUSH)
665 tp->nonagle &= ~TCP_NAGLE_PUSH; 665 tp->nonagle &= ~TCP_NAGLE_PUSH;
@@ -1034,7 +1034,7 @@ new_segment:
1034 skb->len += copy; 1034 skb->len += copy;
1035 skb->data_len += copy; 1035 skb->data_len += copy;
1036 skb->truesize += copy; 1036 skb->truesize += copy;
1037 sk->sk_wmem_queued += copy; 1037 sk_wmem_queued_add(sk, copy);
1038 sk_mem_charge(sk, copy); 1038 sk_mem_charge(sk, copy);
1039 skb->ip_summed = CHECKSUM_PARTIAL; 1039 skb->ip_summed = CHECKSUM_PARTIAL;
1040 WRITE_ONCE(tp->write_seq, tp->write_seq + copy); 1040 WRITE_ONCE(tp->write_seq, tp->write_seq + copy);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index a115a991dfb5..0488607c5cd3 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1199,7 +1199,7 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
1199 WRITE_ONCE(tp->write_seq, TCP_SKB_CB(skb)->end_seq); 1199 WRITE_ONCE(tp->write_seq, TCP_SKB_CB(skb)->end_seq);
1200 __skb_header_release(skb); 1200 __skb_header_release(skb);
1201 tcp_add_write_queue_tail(sk, skb); 1201 tcp_add_write_queue_tail(sk, skb);
1202 sk->sk_wmem_queued += skb->truesize; 1202 sk_wmem_queued_add(sk, skb->truesize);
1203 sk_mem_charge(sk, skb->truesize); 1203 sk_mem_charge(sk, skb->truesize);
1204} 1204}
1205 1205
@@ -1333,7 +1333,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
1333 return -ENOMEM; /* We'll just try again later. */ 1333 return -ENOMEM; /* We'll just try again later. */
1334 skb_copy_decrypted(buff, skb); 1334 skb_copy_decrypted(buff, skb);
1335 1335
1336 sk->sk_wmem_queued += buff->truesize; 1336 sk_wmem_queued_add(sk, buff->truesize);
1337 sk_mem_charge(sk, buff->truesize); 1337 sk_mem_charge(sk, buff->truesize);
1338 nlen = skb->len - len - nsize; 1338 nlen = skb->len - len - nsize;
1339 buff->truesize += nlen; 1339 buff->truesize += nlen;
@@ -1443,7 +1443,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
1443 1443
1444 if (delta_truesize) { 1444 if (delta_truesize) {
1445 skb->truesize -= delta_truesize; 1445 skb->truesize -= delta_truesize;
1446 sk->sk_wmem_queued -= delta_truesize; 1446 sk_wmem_queued_add(sk, -delta_truesize);
1447 sk_mem_uncharge(sk, delta_truesize); 1447 sk_mem_uncharge(sk, delta_truesize);
1448 sock_set_flag(sk, SOCK_QUEUE_SHRUNK); 1448 sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
1449 } 1449 }
@@ -1888,7 +1888,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
1888 return -ENOMEM; 1888 return -ENOMEM;
1889 skb_copy_decrypted(buff, skb); 1889 skb_copy_decrypted(buff, skb);
1890 1890
1891 sk->sk_wmem_queued += buff->truesize; 1891 sk_wmem_queued_add(sk, buff->truesize);
1892 sk_mem_charge(sk, buff->truesize); 1892 sk_mem_charge(sk, buff->truesize);
1893 buff->truesize += nlen; 1893 buff->truesize += nlen;
1894 skb->truesize -= nlen; 1894 skb->truesize -= nlen;
@@ -2152,7 +2152,7 @@ static int tcp_mtu_probe(struct sock *sk)
2152 nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC, false); 2152 nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC, false);
2153 if (!nskb) 2153 if (!nskb)
2154 return -1; 2154 return -1;
2155