From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 0795328314C for ; Thu, 9 Jul 2026 03:48:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783568936; cv=none; b=Q3STU74R8Len0irxyamFWC/gMa0N1bxDz6w/FrbBBqMZUo0dtTh11LgvgNznChT256WWTeDjo+X5y1bjtgJdU9pEKO6lZKFxbuv+1veIZu/MlxGQyzi88EecfvkaACr20y+LukmZ3ctUX6NhOe1zyvUC0yRSH4WNyLFlWIPF3i0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783568936; c=relaxed/simple; bh=eM0xgnTFlk/h9BmPpKMvX7HhgooSBPgdMIQRZERMeb4=; h=Date:From:To:Cc:Subject:Message-Id:In-Reply-To:References: Mime-Version:Content-Type; b=EMHDxPWfaAryxSKbqkmwGQt0bfshXGAhcL20AGc/4M9MuGPl+ylTFGB4BunkCg9Q0LaryuRsDMbEu95vR92KO+qKTuTTbzol0QO/3sfBw0U6i/Nk4pZAAuxchXplyMc2+sNeQpU1XC+xe0Mi75DwtjhbzJ1+PojUqwuAjFEbSTw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b=ey6omSp1; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b="ey6omSp1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E32871F000E9; Thu, 9 Jul 2026 03:48:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux-foundation.org; s=korg; t=1783568934; bh=GWqonKtM4F3uLr7KBmbpx/TrfnzDPiskloBr1860j2M=; h=Date:From:To:Cc:Subject:In-Reply-To:References; b=ey6omSp1UGywZOoCct0axZFb0BPm8vsCdgcoDYXBos8zGWrCEeRAJzjl+g2stWunU 7E8MNeMI63wFFgfWGXfeOWnNvrjtcVbnSalsx3tUfwCtQlRs91ollPb+6ABPtzxkEh VMX3RCOmkQQxq1W1NZhVhoKl1ieh2VBNKPb1tito= Date: Wed, 8 Jul 2026 20:48:53 -0700 From: Andrew Morton To: Hui Zhu 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 Subject: Re: [PATCH v11] mm: fix ASSERT_EXCLUSIVE_BITS by passing memdesc_flags_t by pointer Message-Id: <20260708204853.8542f27d6554c1ff3ce7162e@linux-foundation.org> In-Reply-To: <20260708083308.747930-1-hui.zhu@linux.dev> References: <20260708083308.747930-1-hui.zhu@linux.dev> X-Mailer: Sylpheed 3.8.0beta1 (GTK+ 2.24.33; x86_64-pc-linux-gnu) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Wed, 8 Jul 2026 16:33:08 +0800 Hui Zhu wrote: > From: Hui Zhu > > KCSAN reports a data race between page_to_nid()/folio_pgdat() 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 race is benign: nid/zone bits are set once at page init and never > 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. > > Change memdesc_nid(), memdesc_zonenum(), memdesc_section(), and > memdesc_is_zone_device() to take a const memdesc_flags_t * and update > all callers to pass &page->flags / &folio->flags, so > ASSERT_EXCLUSIVE_BITS() operates on the actual shared word. > > Guard the ASSERT_EXCLUSIVE_BITS() call in memdesc_zonenum() under > ZONES_WIDTH != 0 to avoid a zero-mask check on configs where the zone > 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=n, 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. Thanks. > 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 split > in page_to_nid()/folio_nid() and remove the SECTIONS_WIDTH != 0 guard > around ASSERT_EXCLUSIVE_BITS() in memdesc_section(). I'm having trouble comparing this changelogging with the actual v9->v11 diff? "drop the redundant CONFIG_NUMA split"? --- a/include/linux/mm.h~mm-fix-assert_exclusive_bits-by-passing-memdesc_flags_t-by-pointer-fix +++ a/include/linux/mm.h @@ -2303,29 +2303,15 @@ static inline int memdesc_nid(const memd #endif #endif -#ifdef CONFIG_NUMA static inline int page_to_nid(const struct page *page) { - const struct page *p = PF_POISONED_CHECK(page); - - return memdesc_nid(&p->flags); + return memdesc_nid(&(PF_POISONED_CHECK(page)->flags)); } 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 #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 static inline unsigned long memdesc_section(const memdesc_flags_t *mdf) { -#if SECTIONS_WIDTH != 0 ASSERT_EXCLUSIVE_BITS(mdf->f, SECTIONS_MASK << SECTIONS_PGSHIFT); -#endif return (mdf->f >> SECTIONS_PGSHIFT) & SECTIONS_MASK; } #else /* !SECTION_IN_PAGE_FLAGS */ _