]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: rps: annotate data-races around (struct sd_flow_limit)->count
authorEric Dumazet <edumazet@google.com>
Mon, 7 Apr 2025 16:36:00 +0000 (16:36 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 8 Apr 2025 19:30:55 +0000 (12:30 -0700)
softnet_seq_show() can read fl->count while another cpu
updates this field from skb_flow_limit().

Make this field an 'unsigned int', as its only consumer
only deals with 32 bit.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20250407163602.170356-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/core/dev.c
net/core/dev.h
net/core/net-procfs.c

index f674236f34bebb619b02d6e3ab8dfb89dc536142..969883173182b368aacdfb3471486421fc51a936 100644 (file)
@@ -5049,7 +5049,8 @@ static bool skb_flow_limit(struct sk_buff *skb, unsigned int qlen)
                        fl->buckets[old_flow]--;
 
                if (++fl->buckets[new_flow] > (FLOW_LIMIT_HISTORY >> 1)) {
-                       fl->count++;
+                       /* Pairs with READ_ONCE() in softnet_seq_show() */
+                       WRITE_ONCE(fl->count, fl->count + 1);
                        rcu_read_unlock();
                        return true;
                }
index b1cd44b5f009bfd98e2e8ecde20aa6052cc36282..e855e1cb43fd1a88a0cd67709f4704d774cc4e9d 100644 (file)
@@ -15,7 +15,7 @@ struct cpumask;
 /* Random bits of netdevice that don't need to be exposed */
 #define FLOW_LIMIT_HISTORY     (1 << 7)  /* must be ^2 and !overflow buckets */
 struct sd_flow_limit {
-       u64                     count;
+       unsigned int            count;
        u8                      log_buckets;
        unsigned int            history_head;
        u16                     history[FLOW_LIMIT_HISTORY];
index 3e92bf0f9060b19a3d9b0ace6bb4005352fedafe..69782d62fbe1935930eda5fd895b49573ba88c98 100644 (file)
@@ -132,8 +132,9 @@ static int softnet_seq_show(struct seq_file *seq, void *v)
 
        rcu_read_lock();
        fl = rcu_dereference(sd->flow_limit);
+       /* Pairs with WRITE_ONCE() in skb_flow_limit() */
        if (fl)
-               flow_limit_count = fl->count;
+               flow_limit_count = READ_ONCE(fl->count);
        rcu_read_unlock();
 #endif