[PATCH v1] mm: fix data-race in folio_batch_count()

From: Xuewen Wang

Date: Wed Jun 24 2026 - 05:28:21 EST


KCSAN reports:

BUG: KCSAN: data-race in __lru_add_drain_all / folio_batch_add_and_move

write to 0xffff98fe74c015f8 of 1 bytes by task 45153 on cpu 2:
folio_batch_add+0x30/0xe0

read to 0xffff98fe74c015f8 of 1 bytes by task 45175 on cpu 0:
folio_batch_count+0x0/0x10
cpu_needs_drain+0x253/0x430

The write side is a per-cpu local operation (folio_batch_add on the
CPU that owns the per-cpu batch), while cpu_needs_drain() reads
another CPU's per-cpu batch without locking. Reading a slightly stale
value is harmless -- it only determines whether to schedule a drain,
and a subsequent check will catch it.

Use READ_ONCE() to annotate the read and prevent load tearing, which
also suppresses the KCSAN warning.

Signed-off-by: Xuewen Wang <wangxuewen@xxxxxxxxxx>
---
include/linux/folio_batch.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/folio_batch.h b/include/linux/folio_batch.h
index b45946adc50b..1e31e058e19d 100644
--- a/include/linux/folio_batch.h
+++ b/include/linux/folio_batch.h
@@ -53,7 +53,7 @@ static inline void folio_batch_reinit(struct folio_batch *fbatch)

static inline unsigned int folio_batch_count(const struct folio_batch *fbatch)
{
- return fbatch->nr;
+ return READ_ONCE(fbatch->nr);
}

static inline unsigned int folio_batch_space(const struct folio_batch *fbatch)
--
2.25.1