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 B5739345EAD for ; Mon, 21 Sep 2026 04:09:57 +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=1789963799; cv=none; b=DXWfEE2y+neH33lQq9UchDWmgFuJ3jbElFsqL5BhJLLyRi5zGwYJETdk0raPR6hK3MElfR6pKGz8U8F/aXyuyvq+P//IIEipe7RIF4FhzlBUo4MYoUa3y/yQ/eMZw/FL9HZApDtwEKBVLJUMQya9Q+O5I9Ka7K8O/OcZzXxrRCE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789963799; c=relaxed/simple; bh=mFPpkvHSNKF4vePeFeobedd45AWjCkt2uo1QQRpmQYc=; h=Date:To:From:Subject:Message-Id; b=X5swN2UuXbg1x2szsA+RGYwFjcHkWO2ZUCV3yIiImkUVRx00yAbORpysPdK/b1niKTrEUFx7Z88T6nyiNDSiAYq4GmXKKnr0ldcZrO6xby7Z2nyTTvGWjVVuewWywbAhYu2IhWtObsLZRr687V9vrAo4oZw7VmgRo9w4RFeT0rY= 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=GPw2hf7a; 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="GPw2hf7a" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 515841F000FF; Mon, 21 Sep 2026 04:09:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux-foundation.org; s=korg; t=1789963797; bh=XnMPVYPxDl4QRAd/utT2ghRm5pCs4c6K9V4qooSGkoo=; h=Date:To:From:Subject; b=GPw2hf7a41tnX699HOepfcnD+9nTiMpa4MbfyiN/rTKsO0Zr0g4qAzQfuZbjAIcPr 8Gcgg8bQ1P3KJRdAix1Sv205R4+P85uv+51QxBqwEPp4zH4KzFOmOC+ZTVIdg1zL2q iIuXyROn0YhLR3OkOnVAthtzPNtaOThlyyNZRaTg= Date: Sun, 20 Sep 2026 21:09:56 -0700 To: mm-commits@vger.kernel.org,ziy@nvidia.com,akpm@linux-foundation.org From: Andrew Morton Subject: + mm-page-flags-check-page-folio-private-instead-of-pg_private.patch added to mm-unstable branch Message-Id: <20260921040957.515841F000FF@smtp.kernel.org> Precedence: bulk X-Mailing-List: mm-commits@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: The patch titled Subject: mm/page-flags: check page/folio->private instead of PG_private has been added to the -mm mm-unstable branch. Its filename is mm-page-flags-check-page-folio-private-instead-of-pg_private.patch This patch will shortly appear at https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/mm-page-flags-check-page-folio-private-instead-of-pg_private.patch This patch will later appear in the mm-unstable branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next via various branches at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm and is updated there most days ------------------------------------------------------ From: Zi Yan Subject: mm/page-flags: check page/folio->private instead of PG_private Date: Sun, 20 Sep 2026 22:28:06 -0400 After the changes of the prior commits, page/folio->private != NULL is now equivalent to checking PG_private. Stop checking PG_private on pages and folios and use page/folio->private instead, except swapcache and hugetlb folios, because the former uses a field (swp_entry_t swap) overlapping with ->private and the latter sets its flags in ->private. Exclude swapcache and hugetlb when the code is meant to check PG_private only. PG_swapcache and folio->swap.val cannot be set/clear as a whole, so excluding swapcache with folio_test_swapcache() is not reliable. Instead, use folio_test_swapbacked(), since PG_swapbacked is stable when a folio is added to/removed from swapcache. Add a helper, folio_has_attached_private(), for this check. folio_test_private() and PagePrivate() now read folio/page->private plainly instead of an atomic read of PG_private bit, so KCSAN complains about possible data races. Annotate them with data_race(). folio_expected_ref_count() can be called without the folio lock, so annotate folio->mapping with data_race() while at it. folio_set/clear_private() and Set/ClearPagePrivate() become no-ops. PG_private is no longer checked at page free time. They will be removed in an upcoming commit. Remove KPF_PRIVATE since PG_private is no longer used. Assisted-by: LLM Link: https://lore.kernel.org/20260920-remove-pg_private-v5-10-bb68b6a21869@nvidia.com Signed-off-by: Zi Yan Signed-off-by: Andrew Morton Cc: David Hildenbrand Cc: Steven Rostedt Cc: Masami Hiramatsu Cc: Lorenzo Stoakes Cc: "Matthew Wilcox (Oracle)" Cc: Jan Kara Cc: Johannes Weiner Cc: "Liam R. Howlett" Cc: Vlastimil Babka Cc: Mike Rapoport Cc: Suren Baghdasaryan Cc: Michal Hocko Cc: Mathieu Desnoyers Cc: Baolin Wang Cc: Nico Pache Cc: Ryan Roberts Cc: Dev Jain Cc: Barry Song Cc: Lance Yang Cc: Usama Arif Cc: Matthew Brost Cc: Joshua Hahn Cc: Rakie Kim Cc: Byungchul Park Cc: Gregory Price Cc: Ying Huang Cc: Alistair Popple Cc: Qi Zheng Cc: Shakeel Butt Cc: Kairui Song Cc: Axel Rasmussen Cc: Yuanchu Xie Cc: Wei Xu --- fs/proc/page.c | 1 include/linux/kernel-page-flags.h | 1 include/linux/mm.h | 19 +++++---- include/linux/page-flags.h | 57 +++++++++++++++++++++++++--- include/trace/events/pagemap.h | 2 mm/huge_memory.c | 2 mm/migrate.c | 2 mm/page-writeback.c | 2 mm/vmscan.c | 2 tools/mm/page-types.c | 2 10 files changed, 68 insertions(+), 22 deletions(-) --- a/fs/proc/page.c~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/fs/proc/page.c @@ -232,7 +232,6 @@ u64 stable_page_flags(const struct page u |= kpf_copy_bit(k, KPF_RESERVED, PG_reserved); u |= kpf_copy_bit(k, KPF_OWNER_2, PG_owner_2); - u |= kpf_copy_bit(k, KPF_PRIVATE, PG_private); u |= kpf_copy_bit(k, KPF_PRIVATE_2, PG_private_2); u |= kpf_copy_bit(k, KPF_OWNER_PRIVATE, PG_owner_priv_1); u |= kpf_copy_bit(k, KPF_ARCH, PG_arch_1); --- a/include/linux/kernel-page-flags.h~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/include/linux/kernel-page-flags.h @@ -11,7 +11,6 @@ #define KPF_RESERVED 32 #define KPF_MLOCKED 33 #define KPF_OWNER_2 34 -#define KPF_PRIVATE 35 #define KPF_PRIVATE_2 36 #define KPF_OWNER_PRIVATE 37 #define KPF_ARCH 38 --- a/include/linux/mm.h~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/include/linux/mm.h @@ -3004,9 +3004,9 @@ static inline bool folio_maybe_mapped_sh * @folio: the folio * * Calculate the expected folio refcount, taking references from the pagecache, - * swapcache, PG_private and page table mappings into account. Useful in - * combination with folio_ref_count() to detect unexpected references (e.g., - * GUP or other temporary references). + * swapcache, private data (folio->private != NULL) and page table mappings into + * account. Useful in combination with folio_ref_count() to detect unexpected + * references (e.g., GUP or other temporary references). * * Does currently not consider references from the LRU cache. If the folio * was isolated from the LRU (which is the case during migration or split), @@ -3044,10 +3044,15 @@ static inline int folio_expected_ref_cou ref_count += folio_test_swapcache(folio) << order; if (!folio_test_anon(folio)) { - /* One reference per page from the pagecache. */ - ref_count += !!folio->mapping << order; - /* One reference from PG_private. */ - ref_count += folio_test_private(folio); + /* + * One reference per page from the pagecache. + * Use data_race() since folio might not be locked. + */ + ref_count += !!data_race(folio->mapping) << order; + /* + * One reference from filesystem private data. + */ + ref_count += folio_has_attached_private(folio); } /* One reference per page table mapping. */ --- a/include/linux/page-flags.h~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/include/linux/page-flags.h @@ -575,9 +575,31 @@ FOLIO_FLAG(swapbacked, FOLIO_HEAD_PAGE) /* * Private page markings that may be used by the filesystem that owns the page * for its own purposes. - * - PG_private and PG_private_2 cause release_folio() and co to be invoked + * - folio->private and PG_private_2 cause release_folio() and co to be invoked */ -PAGEFLAG(Private, private, PF_ANY) + +static __always_inline bool folio_test_private(const struct folio *folio) +{ + /* + * data_race() is added for readers without holding the folio lock. + * Only the NULL/non-NULL answer is used and both are valid while + * private is being attached or detached, so the race is benign. + */ + return data_race(folio->private); +} + +static __always_inline int PagePrivate(const struct page *page) +{ + /* See folio_test_private() for data_race() use */ + return !!data_race(page->private); +} + +/* no-ops during transition */ +static __always_inline void folio_set_private(struct folio *folio) { } +static __always_inline void folio_clear_private(struct folio *folio) { } +static __always_inline void SetPagePrivate(struct page *page) { } +static __always_inline void ClearPagePrivate(struct page *page) { } + FOLIO_FLAG(private_2, FOLIO_HEAD_PAGE) /* owner_2 can be set on tail pages for anon memory */ @@ -1169,7 +1191,7 @@ static __always_inline void __ClearPageA */ #define PAGE_FLAGS_CHECK_AT_FREE \ (1UL << PG_lru | 1UL << PG_locked | \ - 1UL << PG_private | 1UL << PG_private_2 | \ + 1UL << PG_private_2 | \ 1UL << PG_writeback | 1UL << PG_reserved | \ 1UL << PG_active | \ 1UL << PG_unevictable | __PG_MLOCKED | LRU_GEN_MASK) @@ -1193,8 +1215,31 @@ static __always_inline void __ClearPageA (0xffUL /* order */ | 1UL << PG_has_hwpoisoned | \ 1UL << PG_large_rmappable | 1UL << PG_partially_mapped) -#define PAGE_FLAGS_PRIVATE \ - (1UL << PG_private | 1UL << PG_private_2) +/** + * folio_has_attached_private - check if the folio has private data attached + * @folio: The folio to check. + * + * Use this in code that may encounter swapcache or hugetlb folios but only + * wants to detect attached private data. + * + * Return: true if the folio has private data attached. + */ +static inline bool folio_has_attached_private(const struct folio *folio) +{ + /* + * Swapcache stores swp_entry_t in folio->swap, a union with + * folio->private, and hugetlb stores its own flags in folio->private; + * both are excluded. + * + * NOTE: For swapcache, folio->swap.val PG_swapcache are not set as + * a whole, so folio_test_swapcache() is not reliable to exclude + * swapcache. Use folio_test_swapbacked() instead, since it remains set + * when a folio is added to/removed from swapcache. + */ + + return folio_test_private(folio) && !folio_test_swapbacked(folio) && + !folio_test_hugetlb(folio); +} /** * folio_has_private - Determine if folio has private stuff * @folio: The folio to be checked @@ -1204,7 +1249,7 @@ static __always_inline void __ClearPageA */ static inline int folio_has_private(const struct folio *folio) { - return !!(folio->flags.f & PAGE_FLAGS_PRIVATE); + return folio_has_attached_private(folio) || folio_test_private_2(folio); } #undef PF_ANY --- a/include/trace/events/pagemap.h~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/include/trace/events/pagemap.h @@ -22,7 +22,7 @@ (folio_test_swapcache(folio) ? PAGEMAP_SWAPCACHE : 0) | \ (folio_test_swapbacked(folio) ? PAGEMAP_SWAPBACKED : 0) | \ (folio_test_mappedtodisk(folio) ? PAGEMAP_MAPPEDDISK : 0) | \ - (folio_test_private(folio) ? PAGEMAP_BUFFERS : 0) \ + (folio_has_attached_private(folio) ? PAGEMAP_BUFFERS : 0) \ ) TRACE_EVENT(mm_lru_insertion, --- a/mm/huge_memory.c~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/mm/huge_memory.c @@ -4846,7 +4846,7 @@ static int split_huge_pages_pid(int pid, * will try to drop it before split and then check if the folio * can be split or not. So skip the check here. */ - if (!folio_test_private(folio) && + if (!folio_has_attached_private(folio) && folio_expected_ref_count(folio) != folio_ref_count(folio)) goto next; --- a/mm/migrate.c~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/mm/migrate.c @@ -1327,7 +1327,7 @@ static int migrate_folio_unmap(new_folio * free the metadata, so the page can be freed. */ if (!src->mapping) { - if (folio_test_private(src)) { + if (folio_has_attached_private(src)) { try_to_free_buffers(src); goto out; } --- a/mm/page-writeback.c~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/mm/page-writeback.c @@ -2705,7 +2705,7 @@ bool filemap_dirty_folio(struct address_ if (folio_test_set_dirty(folio)) return false; - __folio_mark_dirty(folio, mapping, !folio_test_private(folio)); + __folio_mark_dirty(folio, mapping, !folio_has_attached_private(folio)); if (mapping->host) { /* !PageAnon && !swapper_space */ --- a/mm/vmscan.c~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/mm/vmscan.c @@ -1029,7 +1029,7 @@ static void folio_check_dirty_writeback( *writeback = folio_test_writeback(folio); /* Verify dirty/writeback state if the filesystem supports it */ - if (!folio_test_private(folio)) + if (!folio_has_attached_private(folio)) return; mapping = folio_mapping(folio); --- a/tools/mm/page-types.c~mm-page-flags-check-page-folio-private-instead-of-pg_private +++ a/tools/mm/page-types.c @@ -73,7 +73,6 @@ #define KPF_RESERVED 32 #define KPF_MLOCKED 33 #define KPF_OWNER_2 34 -#define KPF_PRIVATE 35 #define KPF_PRIVATE_2 36 #define KPF_OWNER_PRIVATE 37 #define KPF_ARCH 38 @@ -131,7 +130,6 @@ static const char * const page_flag_name [KPF_RESERVED] = "r:reserved", [KPF_MLOCKED] = "m:mlocked", [KPF_OWNER_2] = "d:owner_2", - [KPF_PRIVATE] = "P:private", [KPF_PRIVATE_2] = "p:private_2", [KPF_OWNER_PRIVATE] = "O:owner_private", [KPF_ARCH] = "h:arch", _ Patches currently in -mm which might be from ziy@nvidia.com are mm-zsmalloc-replace-pg_private-with-pointer-comparison.patch perf-ring_buffer-stop-using-pg_private-as-aux-page-high-order-marker.patch xen-grant-table-stop-setting-pg_private-on-pages-for-grant-mapping.patch fscrypt-stop-setting-pg_private-on-bounce-page.patch mm-hugetlb-use-direct-assignment-instead-of-folio_change_private.patch f2fs-stop-using-pg_private.patch f2fs-convert-the-private-flag-helpers-to-folio-only.patch erofs-mm-pagemap-add-readahead_folio_last-to-avoid-folio-private.patch erofs-use-folio_attach-detach_private-instead-of-direct-assignment.patch mm-page-flags-check-page-folio-private-instead-of-pg_private.patch treewide-remove-folio_set-clear_private-usage.patch ceph-replace-pageprivate-with-page_private.patch treewide-remove-pageprivate-and-pg_private-from-comments-and-docs.patch mm-page-flags-remove-pg_private.patch usb-gadgetfs-do-not-warn-about-excessively-large-memory-allocations.patch