* [PATCH net-next v2 1/7] u64_stats: Introduce u64_stats_reads()
2026-01-23 16:21 [PATCH net-next v2 0/7] u64_stats: Introduce u64_stats_reads() David Yang
@ 2026-01-23 16:21 ` David Yang
2026-01-23 16:21 ` [PATCH net-next v2 2/7] u64_stats: Doc incorrect usage with plain variables David Yang
` (5 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: David Yang @ 2026-01-23 16:21 UTC (permalink / raw)
To: netdev
Cc: David Yang, Sabrina Dubroca, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Nikolay Aleksandrov,
Ido Schimmel, Simon Horman, Aaron Conole, Eelco Chaudron,
Ilya Maximets, Shigeru Yoshida, Stanislav Fomichev, Breno Leitao,
Carolina Jubran, Kuniyuki Iwashima, Guillaume Nault, linux-kernel,
bridge, dev
The following pattern was observed in the code tree:
do {
start = u64_stats_fetch_begin(&pstats->syncp);
memcpy(&temp, &pstats->stats, sizeof(temp));
} while (u64_stats_fetch_retry(&pstats->syncp, start));
On 64bit arches, struct u64_stats_sync is empty and provides no help
against load/store tearing. memcpy() or struct copying does not
guarantee tear free, although compilers never generate such instructions
in practice.
Theoretically the affected code should convert to u64_stats_t, or use
atomic operations properly.
However since there are needs to copy chunks of statistics, instead of
writing loops everywhere, we provide a safe memcpy() variant for that
purpose.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
include/linux/u64_stats_sync.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
index 457879938fc1..15ea4db2a77b 100644
--- a/include/linux/u64_stats_sync.h
+++ b/include/linux/u64_stats_sync.h
@@ -79,6 +79,14 @@ static inline u64 u64_stats_read(const u64_stats_t *p)
return local64_read(&p->v);
}
+static inline void *u64_stats_reads(void *dst, const void *src, size_t len)
+{
+ BUILD_BUG_ON(len % sizeof(u64_stats_t));
+ for (size_t i = 0; i < len; i += sizeof(u64_stats_t))
+ *(u64 *)(dst + i) = u64_stats_read((const u64_stats_t *)(src + i));
+ return dst;
+}
+
static inline void u64_stats_set(u64_stats_t *p, u64 val)
{
local64_set(&p->v, val);
@@ -110,6 +118,7 @@ static inline bool __u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
}
#else /* 64 bit */
+#include <linux/string.h>
typedef struct {
u64 v;
@@ -120,6 +129,12 @@ static inline u64 u64_stats_read(const u64_stats_t *p)
return p->v;
}
+static inline void *u64_stats_reads(void *dst, const void *src, size_t len)
+{
+ BUILD_BUG_ON(len % sizeof(u64_stats_t));
+ return memcpy(dst, src, len);
+}
+
static inline void u64_stats_set(u64_stats_t *p, u64 val)
{
p->v = val;
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH net-next v2 2/7] u64_stats: Doc incorrect usage with plain variables
2026-01-23 16:21 [PATCH net-next v2 0/7] u64_stats: Introduce u64_stats_reads() David Yang
2026-01-23 16:21 ` [PATCH net-next v2 1/7] " David Yang
@ 2026-01-23 16:21 ` David Yang
2026-01-23 16:21 ` [PATCH net-next v2 3/7] net: bridge: mcast: fix memcpy with u64_stats David Yang
` (4 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: David Yang @ 2026-01-23 16:21 UTC (permalink / raw)
To: netdev
Cc: David Yang, Sabrina Dubroca, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Nikolay Aleksandrov,
Ido Schimmel, Simon Horman, Aaron Conole, Eelco Chaudron,
Ilya Maximets, Shigeru Yoshida, Stanislav Fomichev, Breno Leitao,
Carolina Jubran, Kuniyuki Iwashima, Guillaume Nault, linux-kernel,
bridge, dev
On 64-bit architectures, u64_stats does rely on the load/store atomicity
of 64-bit data.
However, users often mistakenly believe that the helpers could also
protect/"lock" plain (64-bit) variables, which can lead to load/store
tearing.
Remove the misleading "non atomic operation" comments and add explicit
examples of incorrect usage.
Users may also be tempted to use memcpy() or struct copying. Doc the
usage of u64_stats_reads() for this case.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
include/linux/u64_stats_sync.h | 41 ++++++++++++++++++++++++++--------
1 file changed, 32 insertions(+), 9 deletions(-)
diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
index 15ea4db2a77b..10f988170e51 100644
--- a/include/linux/u64_stats_sync.h
+++ b/include/linux/u64_stats_sync.h
@@ -39,21 +39,44 @@
* spin_lock_bh(...) or other synchronization to get exclusive access
* ...
* u64_stats_update_begin(&stats->syncp);
- * u64_stats_add(&stats->bytes64, len); // non atomic operation
- * u64_stats_inc(&stats->packets64); // non atomic operation
+ * u64_stats_add(&stats->bytes64, len);
+ * u64_stats_inc(&stats->packets64);
* u64_stats_update_end(&stats->syncp);
*
* While a consumer (reader) should use following template to get consistent
* snapshot for each variable (but no guarantee on several ones)
*
- * u64 tbytes, tpackets;
- * unsigned int start;
+ * u64 tbytes, tpackets;
+ * unsigned int start;
*
- * do {
- * start = u64_stats_fetch_begin(&stats->syncp);
- * tbytes = u64_stats_read(&stats->bytes64); // non atomic operation
- * tpackets = u64_stats_read(&stats->packets64); // non atomic operation
- * } while (u64_stats_fetch_retry(&stats->syncp, start));
+ * do {
+ * start = u64_stats_fetch_begin(&stats->syncp);
+ * tbytes = u64_stats_read(&stats->bytes64);
+ * tpackets = u64_stats_read(&stats->packets64);
+ * } while (u64_stats_fetch_retry(&stats->syncp, start));
+ *
+ * Remember point #2: update_begin()/update_end() and
+ * fetch_begin()/fetch_retry() are no-ops on 64-bit architectures. u64_stats
+ * _cannot_ be used to protect plain variables against tearing.
+ *
+ * u64 stats64, cnt;
+ * struct { u64_stats_t stats[10]; } st, buf;
+ *
+ * u64_stats_update_begin(&stats->syncp);
+ * stats64 = cnt; // no
+ * stats64 += cnt; // no
+ * stats64++; // no
+ * st = buf; // no
+ * memcpy(&st, &buf, sizeof(st)); // no
+ * u64_stats_update_end(&stats->syncp);
+ *
+ * do {
+ * start = u64_stats_fetch_begin(&stats->syncp);
+ * cnt = stats64; // no
+ * buf = st; // no
+ * memcpy(&buf, &st, sizeof(st)); // no
+ * u64_stats_reads(&buf, &st, sizeof(st)); // use this instead
+ * } while (u64_stats_fetch_retry(&stats->syncp, start));
*
*
* Example of use in drivers/net/loopback.c, using per_cpu containers,
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH net-next v2 3/7] net: bridge: mcast: fix memcpy with u64_stats
2026-01-23 16:21 [PATCH net-next v2 0/7] u64_stats: Introduce u64_stats_reads() David Yang
2026-01-23 16:21 ` [PATCH net-next v2 1/7] " David Yang
2026-01-23 16:21 ` [PATCH net-next v2 2/7] u64_stats: Doc incorrect usage with plain variables David Yang
@ 2026-01-23 16:21 ` David Yang
2026-01-23 16:21 ` [PATCH net-next v2 4/7] net: openvswitch: fix load tearing " David Yang
` (3 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: David Yang @ 2026-01-23 16:21 UTC (permalink / raw)
To: netdev
Cc: David Yang, Nikolay Aleksandrov, Ido Schimmel, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, bridge,
linux-kernel
On 64bit arches, struct u64_stats_sync is empty and provides no help
against load/store tearing. memcpy() should not be considered tear-free.
Use u64_stats_reads() instead.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
net/bridge/br_multicast.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index d55a4ab87837..0f8e15b4fa60 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -5201,7 +5201,7 @@ void br_multicast_get_stats(const struct net_bridge *br,
do {
start = u64_stats_fetch_begin(&cpu_stats->syncp);
- memcpy(&temp, &cpu_stats->mstats, sizeof(temp));
+ u64_stats_reads(&temp, &cpu_stats->mstats, sizeof(temp));
} while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
mcast_stats_add_dir(tdst.igmp_v1queries, temp.igmp_v1queries);
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH net-next v2 4/7] net: openvswitch: fix load tearing with u64_stats
2026-01-23 16:21 [PATCH net-next v2 0/7] u64_stats: Introduce u64_stats_reads() David Yang
` (2 preceding siblings ...)
2026-01-23 16:21 ` [PATCH net-next v2 3/7] net: bridge: mcast: fix memcpy with u64_stats David Yang
@ 2026-01-23 16:21 ` David Yang
2026-01-24 0:49 ` kernel test robot
` (2 more replies)
2026-01-23 16:21 ` [PATCH net-next v2 5/7] macsec: fix memcpy " David Yang
` (2 subsequent siblings)
6 siblings, 3 replies; 13+ messages in thread
From: David Yang @ 2026-01-23 16:21 UTC (permalink / raw)
To: netdev
Cc: David Yang, Aaron Conole, Eelco Chaudron, Ilya Maximets,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, dev, linux-kernel
On 64bit arches, struct u64_stats_sync is empty and provides no help
against load/store tearing. struct copying should not be considered
tear-free. Use u64_stats_reads() instead.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
net/openvswitch/datapath.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index d5b6e2002bc1..8ba94df7f942 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -770,7 +770,8 @@ static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats,
do {
start = u64_stats_fetch_begin(&percpu_stats->syncp);
- local_stats = *percpu_stats;
+ u64_stats_reads(&local_stats, percpu_stats,
+ sizeof(local_stats));
} while (u64_stats_fetch_retry(&percpu_stats->syncp, start));
stats->n_hit += local_stats.n_hit;
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH net-next v2 4/7] net: openvswitch: fix load tearing with u64_stats
2026-01-23 16:21 ` [PATCH net-next v2 4/7] net: openvswitch: fix load tearing " David Yang
@ 2026-01-24 0:49 ` kernel test robot
2026-01-26 12:25 ` Ilya Maximets
2026-01-26 18:29 ` David Laight
2 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2026-01-24 0:49 UTC (permalink / raw)
To: David Yang, netdev
Cc: oe-kbuild-all, David Yang, Aaron Conole, Eelco Chaudron,
Ilya Maximets, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, dev, linux-kernel
Hi David,
kernel test robot noticed the following build errors:
[auto build test ERROR on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/David-Yang/u64_stats-Doc-incorrect-usage-with-plain-variables/20260124-012240
base: net-next/main
patch link: https://lore.kernel.org/r/20260123162159.2877941-5-mmyangfl%40gmail.com
patch subject: [PATCH net-next v2 4/7] net: openvswitch: fix load tearing with u64_stats
config: m68k-randconfig-r073-20260124 (https://download.01.org/0day-ci/archive/20260124/202601240814.75efeFdo-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 8.5.0
smatch version: v0.5.0-8994-gd50c5a4c
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260124/202601240814.75efeFdo-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202601240814.75efeFdo-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from <command-line>:
In function 'u64_stats_reads.constprop',
inlined from 'get_dp_stats' at net/openvswitch/datapath.c:773:4:
>> include/linux/compiler_types.h:631:38: error: call to '__compiletime_assert_333' declared with attribute error: BUILD_BUG_ON failed: len % sizeof(u64_stats_t)
_compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
^
include/linux/compiler_types.h:612:4: note: in definition of macro '__compiletime_assert'
prefix ## suffix(); \
^~~~~~
include/linux/compiler_types.h:631:2: note: in expansion of macro '_compiletime_assert'
_compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
^~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
^~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:50:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
^~~~~~~~~~~~~~~~
include/linux/u64_stats_sync.h:157:2: note: in expansion of macro 'BUILD_BUG_ON'
BUILD_BUG_ON(len % sizeof(u64_stats_t));
^~~~~~~~~~~~
vim +/__compiletime_assert_333 +631 include/linux/compiler_types.h
eb5c2d4b45e3d2 Will Deacon 2020-07-21 617
eb5c2d4b45e3d2 Will Deacon 2020-07-21 618 #define _compiletime_assert(condition, msg, prefix, suffix) \
eb5c2d4b45e3d2 Will Deacon 2020-07-21 619 __compiletime_assert(condition, msg, prefix, suffix)
eb5c2d4b45e3d2 Will Deacon 2020-07-21 620
eb5c2d4b45e3d2 Will Deacon 2020-07-21 621 /**
eb5c2d4b45e3d2 Will Deacon 2020-07-21 622 * compiletime_assert - break build and emit msg if condition is false
eb5c2d4b45e3d2 Will Deacon 2020-07-21 623 * @condition: a compile-time constant condition to check
eb5c2d4b45e3d2 Will Deacon 2020-07-21 624 * @msg: a message to emit if condition is false
eb5c2d4b45e3d2 Will Deacon 2020-07-21 625 *
eb5c2d4b45e3d2 Will Deacon 2020-07-21 626 * In tradition of POSIX assert, this macro will break the build if the
eb5c2d4b45e3d2 Will Deacon 2020-07-21 627 * supplied condition is *false*, emitting the supplied error message if the
eb5c2d4b45e3d2 Will Deacon 2020-07-21 628 * compiler has support to do so.
eb5c2d4b45e3d2 Will Deacon 2020-07-21 629 */
eb5c2d4b45e3d2 Will Deacon 2020-07-21 630 #define compiletime_assert(condition, msg) \
eb5c2d4b45e3d2 Will Deacon 2020-07-21 @631 _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
eb5c2d4b45e3d2 Will Deacon 2020-07-21 632
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH net-next v2 4/7] net: openvswitch: fix load tearing with u64_stats
2026-01-23 16:21 ` [PATCH net-next v2 4/7] net: openvswitch: fix load tearing " David Yang
2026-01-24 0:49 ` kernel test robot
@ 2026-01-26 12:25 ` Ilya Maximets
2026-01-26 18:29 ` David Laight
2 siblings, 0 replies; 13+ messages in thread
From: Ilya Maximets @ 2026-01-26 12:25 UTC (permalink / raw)
To: David Yang, netdev
Cc: i.maximets, Aaron Conole, Eelco Chaudron, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, dev,
linux-kernel
On 1/23/26 5:21 PM, David Yang wrote:
> On 64bit arches, struct u64_stats_sync is empty and provides no help
> against load/store tearing. struct copying should not be considered
> tear-free. Use u64_stats_reads() instead.
>
> Signed-off-by: David Yang <mmyangfl@gmail.com>
> ---
> net/openvswitch/datapath.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
> index d5b6e2002bc1..8ba94df7f942 100644
> --- a/net/openvswitch/datapath.c
> +++ b/net/openvswitch/datapath.c
> @@ -770,7 +770,8 @@ static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats,
>
> do {
> start = u64_stats_fetch_begin(&percpu_stats->syncp);
> - local_stats = *percpu_stats;
> + u64_stats_reads(&local_stats, percpu_stats,
> + sizeof(local_stats));
I suppose, you'll either need to use offset of 'syncp' field here,
or copy fields one by one, which is not great.
Best regards, Ilya Maximets.
> } while (u64_stats_fetch_retry(&percpu_stats->syncp, start));
>
> stats->n_hit += local_stats.n_hit;
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH net-next v2 4/7] net: openvswitch: fix load tearing with u64_stats
2026-01-23 16:21 ` [PATCH net-next v2 4/7] net: openvswitch: fix load tearing " David Yang
2026-01-24 0:49 ` kernel test robot
2026-01-26 12:25 ` Ilya Maximets
@ 2026-01-26 18:29 ` David Laight
2026-01-26 18:35 ` Eric Dumazet
2 siblings, 1 reply; 13+ messages in thread
From: David Laight @ 2026-01-26 18:29 UTC (permalink / raw)
To: David Yang
Cc: netdev, Aaron Conole, Eelco Chaudron, Ilya Maximets,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, dev, linux-kernel
On Sat, 24 Jan 2026 00:21:36 +0800
David Yang <mmyangfl@gmail.com> wrote:
> On 64bit arches, struct u64_stats_sync is empty and provides no help
> against load/store tearing. struct copying should not be considered
> tear-free. Use u64_stats_reads() instead.
Except that the compiler doesn't ever generate 'tearing accesses' for
aligned 64bit accesses on any 64bit architecture.
Similarly memcpy() won't generate problematic accesses.
The problem is purely theoretical - the C language lets the compiler
split accesses, but it doesn't.
David
>
> Signed-off-by: David Yang <mmyangfl@gmail.com>
> ---
> net/openvswitch/datapath.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
> index d5b6e2002bc1..8ba94df7f942 100644
> --- a/net/openvswitch/datapath.c
> +++ b/net/openvswitch/datapath.c
> @@ -770,7 +770,8 @@ static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats,
>
> do {
> start = u64_stats_fetch_begin(&percpu_stats->syncp);
> - local_stats = *percpu_stats;
> + u64_stats_reads(&local_stats, percpu_stats,
> + sizeof(local_stats));
> } while (u64_stats_fetch_retry(&percpu_stats->syncp, start));
>
> stats->n_hit += local_stats.n_hit;
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH net-next v2 4/7] net: openvswitch: fix load tearing with u64_stats
2026-01-26 18:29 ` David Laight
@ 2026-01-26 18:35 ` Eric Dumazet
2026-01-26 19:18 ` David Laight
0 siblings, 1 reply; 13+ messages in thread
From: Eric Dumazet @ 2026-01-26 18:35 UTC (permalink / raw)
To: David Laight
Cc: David Yang, netdev, Aaron Conole, Eelco Chaudron, Ilya Maximets,
David S. Miller, Jakub Kicinski, Paolo Abeni, Simon Horman, dev,
linux-kernel
On Mon, Jan 26, 2026 at 7:29 PM David Laight
<david.laight.linux@gmail.com> wrote:
>
> On Sat, 24 Jan 2026 00:21:36 +0800
> David Yang <mmyangfl@gmail.com> wrote:
>
> > On 64bit arches, struct u64_stats_sync is empty and provides no help
> > against load/store tearing. struct copying should not be considered
> > tear-free. Use u64_stats_reads() instead.
>
> Except that the compiler doesn't ever generate 'tearing accesses' for
> aligned 64bit accesses on any 64bit architecture.
> Similarly memcpy() won't generate problematic accesses.
>
> The problem is purely theoretical - the C language lets the compiler
> split accesses, but it doesn't.
Yeah, although we still have races that KCSAN can detect.
data_race() or READ_ONCE() would be necessary to avoid noisy KCSAN reports.
While many LCSAN reports are boring, some of them point to real bugs.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v2 4/7] net: openvswitch: fix load tearing with u64_stats
2026-01-26 18:35 ` Eric Dumazet
@ 2026-01-26 19:18 ` David Laight
0 siblings, 0 replies; 13+ messages in thread
From: David Laight @ 2026-01-26 19:18 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Yang, netdev, Aaron Conole, Eelco Chaudron, Ilya Maximets,
David S. Miller, Jakub Kicinski, Paolo Abeni, Simon Horman, dev,
linux-kernel
On Mon, 26 Jan 2026 19:35:38 +0100
Eric Dumazet <edumazet@google.com> wrote:
> On Mon, Jan 26, 2026 at 7:29 PM David Laight
> <david.laight.linux@gmail.com> wrote:
> >
> > On Sat, 24 Jan 2026 00:21:36 +0800
> > David Yang <mmyangfl@gmail.com> wrote:
> >
> > > On 64bit arches, struct u64_stats_sync is empty and provides no help
> > > against load/store tearing. struct copying should not be considered
> > > tear-free. Use u64_stats_reads() instead.
> >
> > Except that the compiler doesn't ever generate 'tearing accesses' for
> > aligned 64bit accesses on any 64bit architecture.
> > Similarly memcpy() won't generate problematic accesses.
> >
> > The problem is purely theoretical - the C language lets the compiler
> > split accesses, but it doesn't.
>
> Yeah, although we still have races that KCSAN can detect.
>
> data_race() or READ_ONCE() would be necessary to avoid noisy KCSAN reports.
>
> While many KCSAN reports are boring, some of them point to real bugs.
>
Could something be put in u64_stats_fetch_begin() to stop KCSAN bleating?
With the way READ_ONCE and WRITE_ONCE now get enforced I do wonder if
some data shouldn't just be marked 'volatile'?
That would give 'non-tearing' accesses, but without the inter-cpu
ordering that (I think) READ/WRITE_ONCE also give.
For stats counters that is enough.
David
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next v2 5/7] macsec: fix memcpy with u64_stats
2026-01-23 16:21 [PATCH net-next v2 0/7] u64_stats: Introduce u64_stats_reads() David Yang
` (3 preceding siblings ...)
2026-01-23 16:21 ` [PATCH net-next v2 4/7] net: openvswitch: fix load tearing " David Yang
@ 2026-01-23 16:21 ` David Yang
2026-01-23 16:21 ` [PATCH net-next v2 6/7] mpls: Fix load tearing " David Yang
2026-01-23 16:21 ` [PATCH net-next v2 7/7] vxlan: vnifilter: fix memcpy " David Yang
6 siblings, 0 replies; 13+ messages in thread
From: David Yang @ 2026-01-23 16:21 UTC (permalink / raw)
To: netdev
Cc: David Yang, Sabrina Dubroca, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
On 64bit arches, struct u64_stats_sync is empty and provides no help
against load/store tearing. memcpy() should not be considered tear-free.
Use u64_stats_reads() instead.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
drivers/net/macsec.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 5200fd5a10e5..533a64713ea7 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -2806,7 +2806,7 @@ static void get_rx_sc_stats(struct net_device *dev,
stats = per_cpu_ptr(rx_sc->stats, cpu);
do {
start = u64_stats_fetch_begin(&stats->syncp);
- memcpy(&tmp, &stats->stats, sizeof(tmp));
+ u64_stats_reads(&tmp, &stats->stats, sizeof(tmp));
} while (u64_stats_fetch_retry(&stats->syncp, start));
sum->InOctetsValidated += tmp.InOctetsValidated;
@@ -2887,7 +2887,7 @@ static void get_tx_sc_stats(struct net_device *dev,
stats = per_cpu_ptr(macsec_priv(dev)->secy.tx_sc.stats, cpu);
do {
start = u64_stats_fetch_begin(&stats->syncp);
- memcpy(&tmp, &stats->stats, sizeof(tmp));
+ u64_stats_reads(&tmp, &stats->stats, sizeof(tmp));
} while (u64_stats_fetch_retry(&stats->syncp, start));
sum->OutPktsProtected += tmp.OutPktsProtected;
@@ -2943,7 +2943,7 @@ static void get_secy_stats(struct net_device *dev, struct macsec_dev_stats *sum)
stats = per_cpu_ptr(macsec_priv(dev)->stats, cpu);
do {
start = u64_stats_fetch_begin(&stats->syncp);
- memcpy(&tmp, &stats->stats, sizeof(tmp));
+ u64_stats_reads(&tmp, &stats->stats, sizeof(tmp));
} while (u64_stats_fetch_retry(&stats->syncp, start));
sum->OutPktsUntagged += tmp.OutPktsUntagged;
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH net-next v2 6/7] mpls: Fix load tearing with u64_stats
2026-01-23 16:21 [PATCH net-next v2 0/7] u64_stats: Introduce u64_stats_reads() David Yang
` (4 preceding siblings ...)
2026-01-23 16:21 ` [PATCH net-next v2 5/7] macsec: fix memcpy " David Yang
@ 2026-01-23 16:21 ` David Yang
2026-01-23 16:21 ` [PATCH net-next v2 7/7] vxlan: vnifilter: fix memcpy " David Yang
6 siblings, 0 replies; 13+ messages in thread
From: David Yang @ 2026-01-23 16:21 UTC (permalink / raw)
To: netdev
Cc: David Yang, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Kuniyuki Iwashima, Guillaume Nault,
Breno Leitao, Stanislav Fomichev, linux-kernel
On 64bit arches, struct u64_stats_sync is empty and provides no help
against load/store tearing. struct copying should not be considered
tear-free. Use u64_stats_reads() instead.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
net/mpls/af_mpls.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 580aac112dd2..bd2e02b89d09 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1097,7 +1097,7 @@ static void mpls_get_stats(struct mpls_dev *mdev,
p = per_cpu_ptr(mdev->stats, i);
do {
start = u64_stats_fetch_begin(&p->syncp);
- local = p->stats;
+ u64_stats_reads(&local, &p->stats, sizeof(local));
} while (u64_stats_fetch_retry(&p->syncp, start));
stats->rx_packets += local.rx_packets;
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH net-next v2 7/7] vxlan: vnifilter: fix memcpy with u64_stats
2026-01-23 16:21 [PATCH net-next v2 0/7] u64_stats: Introduce u64_stats_reads() David Yang
` (5 preceding siblings ...)
2026-01-23 16:21 ` [PATCH net-next v2 6/7] mpls: Fix load tearing " David Yang
@ 2026-01-23 16:21 ` David Yang
6 siblings, 0 replies; 13+ messages in thread
From: David Yang @ 2026-01-23 16:21 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Ido Schimmel, Nikolay Aleksandrov,
Breno Leitao, Stanislav Fomichev, Shigeru Yoshida,
Carolina Jubran, linux-kernel
On 64bit arches, struct u64_stats_sync is empty and provides no help
against load/store tearing. memcpy() should not be considered tear-free.
Use u64_stats_reads() instead.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
drivers/net/vxlan/vxlan_vnifilter.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
index adc89e651e27..afd5df154376 100644
--- a/drivers/net/vxlan/vxlan_vnifilter.c
+++ b/drivers/net/vxlan/vxlan_vnifilter.c
@@ -126,7 +126,7 @@ static void vxlan_vnifilter_stats_get(const struct vxlan_vni_node *vninode,
pstats = per_cpu_ptr(vninode->stats, i);
do {
start = u64_stats_fetch_begin(&pstats->syncp);
- memcpy(&temp, &pstats->stats, sizeof(temp));
+ u64_stats_reads(&temp, &pstats->stats, sizeof(temp));
} while (u64_stats_fetch_retry(&pstats->syncp, start));
dest->rx_packets += temp.rx_packets;
--
2.51.0
^ permalink raw reply related [flat|nested] 13+ messages in thread