tcp: tcp_gro_dev_warn() cleanup
authorEric Dumazet <edumazet@google.com>
Thu, 30 Nov 2023 18:41:35 +0000 (18:41 +0000)
committerJakub Kicinski <kuba@kernel.org>
Sat, 2 Dec 2023 03:31:10 +0000 (19:31 -0800)
Use DO_ONCE_LITE_IF() and __cold attribute to put tcp_gro_dev_warn()
out of line.

This also allows the message to be printed again after a
"echo 1 > /sys/kernel/debug/clear_warn_once"

Also add a READ_ONCE() when reading device mtu, as it could
be changed concurrently.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20231130184135.4130860-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/tcp_input.c

index bcb55d98004c5213f0095613124d5193b15b2793..0548f0c12155404bcc14cae620c23265072d5b1e 100644 (file)
@@ -202,23 +202,17 @@ static void bpf_skops_established(struct sock *sk, int bpf_op,
 }
 #endif
 
-static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb,
-                            unsigned int len)
+static __cold void tcp_gro_dev_warn(const struct sock *sk, const struct sk_buff *skb,
+                                   unsigned int len)
 {
-       static bool __once __read_mostly;
+       struct net_device *dev;
 
-       if (!__once) {
-               struct net_device *dev;
-
-               __once = true;
-
-               rcu_read_lock();
-               dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif);
-               if (!dev || len >= dev->mtu)
-                       pr_warn("%s: Driver has suspect GRO implementation, TCP performance may be compromised.\n",
-                               dev ? dev->name : "Unknown driver");
-               rcu_read_unlock();
-       }
+       rcu_read_lock();
+       dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif);
+       if (!dev || len >= READ_ONCE(dev->mtu))
+               pr_warn("%s: Driver has suspect GRO implementation, TCP performance may be compromised.\n",
+                       dev ? dev->name : "Unknown driver");
+       rcu_read_unlock();
 }
 
 /* Adapt the MSS value used to make delayed ack decision to the
@@ -250,9 +244,8 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
                icsk->icsk_ack.rcv_mss = min_t(unsigned int, len,
                                               tcp_sk(sk)->advmss);
                /* Account for possibly-removed options */
-               if (unlikely(len > icsk->icsk_ack.rcv_mss +
-                                  MAX_TCP_OPTION_SPACE))
-                       tcp_gro_dev_warn(sk, skb, len);
+               DO_ONCE_LITE_IF(len > icsk->icsk_ack.rcv_mss + MAX_TCP_OPTION_SPACE,
+                               tcp_gro_dev_warn, sk, skb, len);
                /* If the skb has a len of exactly 1*MSS and has the PSH bit
                 * set then it is likely the end of an application write. So
                 * more data may not be arriving soon, and yet the data sender