Re: [PATCH v2] mm: avoid KCSAN false positive in memdesc_nid()

From: Andrew Morton

Date: Wed Jun 24 2026 - 17:01:16 EST


On Tue, 23 Jun 2026 16:44:32 +0800 Hui Zhu <hui.zhu@xxxxxxxxx> wrote:

> From: Hui Zhu <zhuhui@xxxxxxxxxx>
>
> KCSAN reports a data race between page_to_nid()/folio_nid() reading
> page->flags and folio_trylock()/folio_lock() concurrently doing
> test_and_set_bit_lock(PG_locked, ...) on the same word, e.g.:
>
> BUG: KCSAN: data-race in __lruvec_stat_mod_folio / shmem_get_folio_gfp
>
> The node id occupies a fixed bit-range of page->flags that is set
> once at page init and never modified afterwards, so it can never
> overlap with the low PG_locked/PG_waiters bits touched by the folio
> lock path.
>
> Use ASSERT_EXCLUSIVE_BITS() in memdesc_nid() to scope the exemption
> to just the node-id bits, consistent with how memdesc_zonenum()
> already handles the same class of race for the zone-id bits.
>
> ...
>
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2290,6 +2290,7 @@ int memdesc_nid(memdesc_flags_t mdf);
> #else
> static inline int memdesc_nid(memdesc_flags_t mdf)
> {
> + ASSERT_EXCLUSIVE_BITS(mdf.f, NODES_MASK << NODES_PGSHIFT);
> return (mdf.f >> NODES_PGSHIFT) & NODES_MASK;
> }
> #endif

It seems weird to be doing this against a local variable within a
random function, seemingly unrelated to the problematic functions which
you've identified.

Seems that it fooled Sashiko:
https://sashiko.dev/#/patchset/20260623084432.701120-1-hui.zhu@xxxxxxxxx

I'm wondering what the heck is going on here?