From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 411EE399CFD for ; Thu, 9 Jul 2026 04:29:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783571365; cv=none; b=aFJ9PrNAlrnp4D4+VuzrqTL82PQ/nzggvGgkZJh9LwU/hAfronhK+ImBoCUlGGvsE31XSs5Bv6c6rKQVimStwXeRHAwNFzov+ylaAkF3l3GDvwQIBTB7X06IecKTY8bVYXae2WWiacpFHZMnOp7Kyi46UmxqEO2zJH6CU7O6lVs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783571365; c=relaxed/simple; bh=CtF2eQiIGv55Z1K0Ql3xdE6FU8Hc/ju/vj+dtct6pHU=; h=MIME-Version:Date:Content-Type:From:Message-ID:Subject:To:Cc: In-Reply-To:References; b=Yr6QFhBmGY+JI3k8fxrMOVdJm0HLPE+iqBPJtslOmOEiGmZcm5+p57po2vXzAIse+NXTUAqDv5FnnvQJEEif3c8pPtkpHZy9b3jztJvXzZBxBdRcy9ybrwnkAQx8lgfbh6SpaZAHIpzcsYQjgYC7ZwqyQycA/PpiHkEFDZTSsKM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=mCflFV4x; arc=none smtp.client-ip=91.218.175.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="mCflFV4x" Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1783571360; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ERKaoA5wnk6n6gGHWnQOiOQ4MZO14KJEaRX6W6rDBxA=; b=mCflFV4xyj4cu2NwR8t4TVIr0krNxA0YaUS+5Ketxq8UXwyF8DbsynMal5Zos/6zLhKmZH myXFcDCrK84O1y85+fil24h4NvPKt4DpWIzisXE8MGjLLFKwpSPbpGY8UcYeatNHIXiunM YJebN/Su6vflGOOw3xljF9LZRKLq9/c= Date: Thu, 09 Jul 2026 04:29:15 +0000 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: "Hui Zhu" Message-ID: <220399d6c91aa81704eca2f1485fed2b11bbaf1f@linux.dev> TLS-Required: No Subject: Re: [PATCH v11] mm: fix ASSERT_EXCLUSIVE_BITS by passing memdesc_flags_t by pointer To: "Andrew Morton" Cc: "David Hildenbrand" , "Lorenzo Stoakes" , "Liam R. Howlett" , "Vlastimil Babka" , "Mike Rapoport" , "Suren Baghdasaryan" , "Michal Hocko" , "Kairui Song" , "Qi Zheng" , "Shakeel Butt" , "Barry Song" , "Axel Rasmussen" , "Yuanchu Xie" , "Wei Xu" , linux-mm@kvack.org, linux-kernel@vger.kernel.org, "Hui Zhu" In-Reply-To: <20260708204853.8542f27d6554c1ff3ce7162e@linux-foundation.org> References: <20260708083308.747930-1-hui.zhu@linux.dev> <20260708204853.8542f27d6554c1ff3ce7162e@linux-foundation.org> X-Migadu-Flow: FLOW_OUT >=20 >=20On Wed, 8 Jul 2026 16:33:08 +0800 Hui Zhu wrote: >=20 >=20>=20 >=20> From: Hui Zhu > >=20=20 >=20> KCSAN reports a data race between page_to_nid()/folio_pgdat() read= ing > > page->flags and folio_trylock()/folio_lock() concurrently doing > > test_and_set_bit_lock(PG_locked, ...) on the same word, e.g.: > >=20=20 >=20> BUG: KCSAN: data-race in __lruvec_stat_mod_folio / shmem_get_folio= _gfp > >=20=20 >=20> The race is benign: nid/zone bits are set once at page init and ne= ver > > overlap with PG_locked. However, ASSERT_EXCLUSIVE_BITS() inside > > memdesc_nid/zonenum() was checking a by-value copy of the flags word= , > > not the live page->flags, so it failed to annotate the real access. > >=20=20 >=20> Change memdesc_nid(), memdesc_zonenum(), memdesc_section(), and > > memdesc_is_zone_device() to take a const memdesc_flags_t * and updat= e > > all callers to pass &page->flags / &folio->flags, so > > ASSERT_EXCLUSIVE_BITS() operates on the actual shared word. > >=20=20 >=20> Guard the ASSERT_EXCLUSIVE_BITS() call in memdesc_zonenum() under > > ZONES_WIDTH !=3D 0 to avoid a zero-mask check on configs where the z= one > > field is absent. memdesc_section() needs no such guard, since > > SECTIONS_WIDTH is never 0 wherever SECTION_IN_PAGE_FLAGS is defined. > > Under CONFIG_NUMA=3Dn, memdesc_nid() itself is stubbed to "return 0" > > instead of reading page->flags, since NODES_MASK is 0 and the check > > can never fire; page_to_nid()/folio_nid() now just call memdesc_nid(= ) > > unconditionally and rely on that stub, instead of duplicating the > > CONFIG_NUMA split at each call site. > >=20 >=20Thanks. >=20 >=20>=20 >=20> Co-developed-by: David Hildenbrand (Arm) > > Signed-off-by: David Hildenbrand (Arm) > > Signed-off-by: Hui Zhu > > Acked-by: David Hildenbrand (Arm) > > --- > > Changelog: > > v11: > > According to the comments of David, simplify page_to_nid() to pass > > &(PF_POISONED_CHECK(page)->flags) directly. > > v10: > > According to the comments of David, drop the redundant CONFIG_NUMA s= plit > > in page_to_nid()/folio_nid() and remove the SECTIONS_WIDTH !=3D 0 gu= ard > > around ASSERT_EXCLUSIVE_BITS() in memdesc_section(). > >=20 >=20I'm having trouble comparing this changelogging with the actual v9->v= 11 > diff? "drop the redundant CONFIG_NUMA split"? Because memdesc_nid already handles the non-config_NUMa case, the code for page_to_nid and folio_nid handling the non-config_NUMa case is remove= d. Sorry for the trouble, I will write more details in the changelog next time. Best, Hui >=20 >=20--- a/include/linux/mm.h~mm-fix-assert_exclusive_bits-by-passing-memd= esc_flags_t-by-pointer-fix > +++ a/include/linux/mm.h > @@ -2303,29 +2303,15 @@ static inline int memdesc_nid(const memd > #endif > #endif >=20=20 >=20-#ifdef CONFIG_NUMA > static inline int page_to_nid(const struct page *page) > { > - const struct page *p =3D PF_POISONED_CHECK(page); > - > - return memdesc_nid(&p->flags); > + return memdesc_nid(&(PF_POISONED_CHECK(page)->flags)); > } >=20=20 >=20 static inline int folio_nid(const struct folio *folio) > { > return memdesc_nid(&folio->flags); > } > -#else > -static inline int page_to_nid(const struct page *page) > -{ > - return 0; > -} > - > -static inline int folio_nid(const struct folio *folio) > -{ > - return 0; > -} > -#endif >=20=20 >=20 #ifdef CONFIG_NUMA_BALANCING > /* page access time bits needs to hold at least 4 seconds */ > @@ -2566,9 +2552,7 @@ static inline void set_page_section(stru >=20=20 >=20 static inline unsigned long memdesc_section(const memdesc_flags_t *m= df) > { > -#if SECTIONS_WIDTH !=3D 0 > ASSERT_EXCLUSIVE_BITS(mdf->f, SECTIONS_MASK << SECTIONS_PGSHIFT); > -#endif > return (mdf->f >> SECTIONS_PGSHIFT) & SECTIONS_MASK; > } > #else /* !SECTION_IN_PAGE_FLAGS */ > _ >