Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead
@ 2026-08-31 19:25 Zi Yan
  2026-08-31 19:25 ` [PATCH v2 01/14] mm/zsmalloc: replace PG_private with pointer comparison Zi Yan
                   ` (13 more replies)
  0 siblings, 14 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Minchan Kim, Sergey Senozhatsky,
	Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Thomas Gleixner, Borislav Petkov, Dave Hansen, x86,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Ian Rogers,
	Adrian Hunter, James Clark, H. Peter Anvin, linux-perf-users,
	Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
	xen-devel, Eric Biggers, Theodore Y. Ts'o, Jaegeuk Kim,
	linux-fscrypt, Oscar Salvador, Chao Yu, linux-f2fs-devel,
	Gao Xiang, Jan Kara, Yue Hu, Jeffle Xu, Sandeep Dhavale,
	Hongbo Li, Chunhai Guo, linux-erofs, linux-fsdevel,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park,
	Axel Rasmussen, Yuanchu Xie, Wei Xu, linux-trace-kernel,
	Trond Myklebust, Anna Schumaker, linux-nfs, Song Liu, Yu Kuai,
	Ilya Dryomov, Alex Markuze, Viacheslav Dubeyko, Li Nan, Xiao Ni,
	linux-raid, ceph-devel, Richard Weinberger, Zhihao Cheng,
	linux-mtd, Baoquan He, Pasha Tatashin, Pratyush Yadav,
	Jonathan Corbet, Dave Young, Shuah Khan, kexec, linux-doc

Hi all,

This patchset removes PG_private to make space for upcoming PG_folio
(reserved as __PG_folio) for identifying pages from a folio (more details
in Note below). Instead of checking PG_private, all code is changed to
check page/folio->private != NULL instead.

MM people are cc'd on all patches and subsystem people are cc'd on the
cover letter and corresponding patches.

Overview
===
Most code uses folio_attach/detach/change_private() functions, so folio
refcount is increased and decreased when folio->private is set and reset,
respectively. There is no need to change them.

Changes are needed for exceptional users:
1. zsmalloc uses PG_private to indicate first component zpdesc page and
   page->private is used to store zspage in zpdesc. To remove PG_private,
   is_first_zpdesc() is replaced by pointer comparison.

2. kernel/events/ring_buffer.c stores page order in page->private.
   Replacing PG_private with page->private != NULL works.

3. drivers/xen/grant-table.c stores xen_page_foreign in page->private,
   where on 32-bit, a pointer to xen_page_foreign is stored; on 64-bit,
   page->private is used as xen_page_foreign. PG_private check is replaced
   by page->private != NULL on 32-bit for xen_page_foreign deallocation.
   On 64-bit, page->private is cleared unconditionally since {domid=0,
   gref=0} (xen_page_foreign can be 0) is valid.

4. fs/crypto/crypto.c stores a folio pointer in page->private, PG_private
   checks are replaced by page->private != NULL.

5. fs/erofs has two different uses:

    5a. folio->private is used to form a reversed list of
    the outputs of readahead_folio(). readahead_folio_last() is added to
    output folios in reversed order, so that ->private is no longer needed.

    5b. folio->private is used as an in-flight I/O counter. Convert the
    code to use folio_attach/detach/get_private() and add bias==1 to the
    counter to avoid folio->private being zero.

6. fs/nfs/write.c: folio refcount maintenance is in a bigger scope than
   folio->private. So folio_attach/detach/get_private() is not used.
   Nothing to change.

7. fs/f2fs uses attach_page_private() to first reset folio->private then
   immediately sets PAGE_PRIVATE_NOT_POINTER bit on it. Change it to use
   attach_page_private() to set PAGE_PRIVATE_NOT_POINTER bit directly to
   avoid folio->private == NULL gap inside set_page_private_##name().

8. hugetlb uses folio_change_private(folio, NULL) without folio refcount
   maintenance. Change it to folio->private = NULL.

After the above changes, PG_private ops are converted to
page/folio->private ops.

folio_test_fs_private() is added to check filesystem-only private data by
excluding swapcache and hugetlb folios, because swapcache folios overlap
swp_entry_t swap with ->private and hugetlb sets its own flags in
->private.

Note
===
1. KPF_PRIVATE is removed after PG_private is removed.

2. Documentation/mm/hugetlbfs_reserv.rst is outdated, so I did not remove
   PG_private related text. It should be rewritten.

3. PG_folio is planned to be set on every page from a folio in
   page_rmappable_folio(), so folios with any order (currently
   PG_large_rmappable is used to identify >0 order folios) can be
   identified, vm_insert_*() can correctly reject all folios, and rmap code
   can accept only folios. Eventually, page_folio() will return NULL for
   non-folio pages by checking PG_folio, but before that all existing users
   that treat compound pages as folios will be converted. 

Tests
===
1. allmodconfig build passed.

2. zsmalloc is tested using ext4 on a 1GB lz4 zram:
    2a. zram load + zsmalloc compaction;
    2b. concurrent zspage migration via memory compaction;
    2c. confirmed that multi-page zspages actually formed.

    Details: https://github.com/x-y-z/linux-dev/blob/b4/remove-pg_private/test_zsmalloc.md

3. erofs is tested on images created with -C4096 and lz4hc, lzma,
   deflate, and zstd algorithms:
   3a. cold read of all files, verify checksums match source;
   3b. readahead + reclaim/migration race.

   Details: https://github.com/x-y-z/linux-dev/blob/b4/remove-pg_private/test_erofs.md

4. fscrypt is tested on software-encrypted ext4 with writes to exercise
   bounce pages.

   Details: https://github.com/x-y-z/linux-dev/blob/b4/remove-pg_private/test_fscrypt.md

5. f2fs is tested on an image with inline_data,compress_algorithm=lz4:
    5a. INLINE_INODE — lots of tiny files;
    5b. REF_RESOURCE + general writeback — buffered write churn with fsync;
    5c. ONGOING_MIGRATION — force GC / page migration;
    5d. ATOMIC_WRITE — atomic-write ioctl path.

    Details: https://github.com/x-y-z/linux-dev/blob/b4/remove-pg_private/test_f2fs.md
    (I did not run xfstests)

6. MM selftests passed.

LLM use
===
Claude was used to form a concrete plan on what code needs to be changed
and how to change them. The plan was reviewed by Codex until no issue was
spotted.

Plan is at: https://github.com/x-y-z/linux-dev/blob/b4/remove-pg_private/plan.md

I then followed the plan to make code changes. I did bounce ideas with
Claude how to change fs/erofs, since I did not like the original idea.
After each change, I asked Claude to review my code and git commit message.
I also asked Claude to give me test plans (see above).

At last, Codex was used to review all patches.

Comments and suggestions are welcome. Thanks.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
Changes in v2:
1. removed is_first_zpdesc() in patch 1 and open coded the checks.
2. fixed wording in patch 2's commit message and clarified page_private()
   also works when ring buffer's AUX page order is 0.
3. removed the empty loop in 64-bit gnttab_pages_set_private().
4. clarified folio->private will be reset to NULL by
   fscrypt_free_bounce_page() in the commit message.
5. clarified why hugetlb needs to restore hugetlb_vmemmap_optimized.
6. renamed readahead_folio_reverse() readahead_folio_last() and
   reimplemented readahead_folio_last() by adding a new readahead_control
   private member, _forward, and a new helper __readahead_advance().
7. added a bias, 1, to erofs I/O counter, so that folio->private stays non
   NULL between folio_attach_private() and folio_detach_private().
8. converted more call sites to use folio_test_fs_private().
- Link to v1: https://lore.kernel.org/r/20260731-remove-pg_private-v1-0-142c97ba3562@nvidia.com

---
Zi Yan (14):
      mm/zsmalloc: replace PG_private with pointer comparison
      perf/ring_buffer: stop using PG_private as AUX page high-order marker
      xen/grant-table: stop setting PG_private on pages for grant mapping
      fscrypt: stop setting PG_private on bounce page
      mm/hugetlb: use direct assignment instead of folio_change_private()
      f2fs: stop using PG_private
      erofs: mm/pagemap: add readahead_folio_last() to avoid folio->private
      erofs: use folio_attach/detach_private() instead of direct assignment
      mm/page-flags: check page/folio->private instead of PG_private
      mm/page-flags: introduce folio_test_fs_private()
      treewide: remove folio_set/clear_private()
      treewide: replace PagePrivate() with page_private()
      treewide: adjust comments on PagePrivate and PG_private
      mm/page-flags: remove PG_private

 Documentation/admin-guide/kdump/vmcoreinfo.rst |  2 +-
 Documentation/filesystems/vfs.rst              |  6 +--
 arch/x86/events/intel/bts.c                    |  3 --
 arch/x86/events/intel/pt.c                     |  6 +--
 drivers/md/md-bitmap.c                         |  6 +--
 drivers/xen/balloon.c                          |  5 +++
 drivers/xen/grant-table.c                      | 11 +++--
 fs/ceph/addr.c                                 |  8 ++--
 fs/crypto/crypto.c                             |  2 -
 fs/erofs/data.c                                | 16 ++++---
 fs/erofs/zdata.c                               | 13 ++----
 fs/f2fs/f2fs.h                                 |  8 ++--
 fs/nfs/file.c                                  |  4 +-
 fs/nfs/write.c                                 |  2 -
 fs/proc/page.c                                 |  1 -
 fs/ubifs/file.c                                |  8 ++--
 include/linux/buffer_head.h                    |  6 ---
 include/linux/kernel-page-flags.h              |  1 -
 include/linux/mm.h                             | 35 +++++++++------
 include/linux/mm_types.h                       |  4 +-
 include/linux/page-flags.h                     | 38 +++++++++++-----
 include/linux/pagemap.h                        | 60 +++++++++++++++++++++-----
 include/trace/events/mmflags.h                 |  2 +-
 include/trace/events/pagemap.h                 |  2 +-
 kernel/events/ring_buffer.c                    |  7 ++-
 kernel/vmcore_info.c                           |  1 -
 mm/huge_memory.c                               |  2 +-
 mm/hugetlb.c                                   |  6 +--
 mm/migrate.c                                   |  3 +-
 mm/page-writeback.c                            |  2 +-
 mm/vmscan.c                                    |  2 +-
 mm/zpdesc.h                                    |  2 +-
 mm/zsmalloc.c                                  | 24 +++--------
 tools/mm/page-types.c                          |  2 -
 34 files changed, 163 insertions(+), 137 deletions(-)
---
base-commit: 443451c85ca8d6389d34b1299decada62128f1fe
change-id: 20260728-remove-pg_private-cfe926c7f83c

Best regards,
--  
Yan, Zi



^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v2 01/14] mm/zsmalloc: replace PG_private with pointer comparison
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 02/14] perf/ring_buffer: stop using PG_private as AUX page high-order marker Zi Yan
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Minchan Kim, Sergey Senozhatsky

zsmalloc uses PG_private to indicate first zpdesc in a zspage chain. It is
equivalent to check zpdesc == zspage->first_zpdesc. Replace
is_first_zpdesc() with zpdesc == zspage->first_zpdesc in obj_allocated().

For get_first_zpdesc(), first_zpdesc is from zspage->first_zpdesc, so
replace is_first_zpdesc() with first_zpdesc->zspage == zspage, the second
requirement of a zspage chain, where all zpdescs point to the same zspage.

is_first_zpdesc(), is only used in VM_BUG_ON_PAGE(), so performance impact
should be negligible. While at it, change VM_BUG_ON() to
VM_WARN_ON_ONCE_PAGE().

It prepares for a future commit that remove PG_private.

No functional change intended.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
To: Minchan Kim <minchan@kernel.org>
To: Sergey Senozhatsky <senozhatsky@chromium.org>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
 mm/zpdesc.h   |  2 +-
 mm/zsmalloc.c | 24 ++++++------------------
 2 files changed, 7 insertions(+), 19 deletions(-)

diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index b8258dc78548d..4fd81c2e80769 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -26,8 +26,8 @@
  * with memcg_data.
  *
  * Page flags used:
- * * PG_private identifies the first component page.
  * * PG_locked is used by page migration code.
+ * The first component page has zpdesc->zspage->first_zpdesc == zpdesc
  */
 struct zpdesc {
 	unsigned long flags;
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 825022a7a328f..24526185fd31f 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -290,11 +290,6 @@ struct zs_pool {
 	atomic_t compaction_in_progress;
 };
 
-static inline void zpdesc_set_first(struct zpdesc *zpdesc)
-{
-	SetPagePrivate(zpdesc_page(zpdesc));
-}
-
 static inline void zpdesc_inc_zone_page_state(struct zpdesc *zpdesc)
 {
 	inc_zone_page_state(zpdesc_page(zpdesc), NR_ZSPAGES);
@@ -476,11 +471,6 @@ static void record_obj(unsigned long handle, unsigned long obj)
 	WRITE_ONCE(*(unsigned long *)handle, obj);
 }
 
-static inline bool __maybe_unused is_first_zpdesc(struct zpdesc *zpdesc)
-{
-	return PagePrivate(zpdesc_page(zpdesc));
-}
-
 /* Protected by class->lock */
 static inline int get_zspage_inuse(struct zspage *zspage)
 {
@@ -496,7 +486,8 @@ static struct zpdesc *get_first_zpdesc(struct zspage *zspage)
 {
 	struct zpdesc *first_zpdesc = zspage->first_zpdesc;
 
-	VM_BUG_ON_PAGE(!is_first_zpdesc(first_zpdesc), zpdesc_page(first_zpdesc));
+	/* the first zpdesc must point back to this zspage */
+	VM_WARN_ON_ONCE_PAGE(first_zpdesc->zspage != zspage, zpdesc_page(first_zpdesc));
 	return first_zpdesc;
 }
 
@@ -838,7 +829,8 @@ static inline bool obj_allocated(struct zpdesc *zpdesc, void *obj,
 	struct zspage *zspage = get_zspage(zpdesc);
 
 	if (unlikely(ZsHugePage(zspage))) {
-		VM_BUG_ON_PAGE(!is_first_zpdesc(zpdesc), zpdesc_page(zpdesc));
+		/* only first zpdesc holds the handle */
+		VM_WARN_ON_ONCE_PAGE(zspage->first_zpdesc != zpdesc, zpdesc_page(zpdesc));
 		handle = zpdesc->handle;
 	} else
 		handle = *(unsigned long *)obj;
@@ -853,9 +845,6 @@ static inline bool obj_allocated(struct zpdesc *zpdesc, void *obj,
 
 static void reset_zpdesc(struct zpdesc *zpdesc)
 {
-	struct page *page = zpdesc_page(zpdesc);
-
-	ClearPagePrivate(page);
 	zpdesc->zspage = NULL;
 	zpdesc->next = NULL;
 	/* PageZsmalloc is sticky until the page is freed to the buddy. */
@@ -1006,8 +995,8 @@ static void create_page_chain(struct size_class *class, struct zspage *zspage,
 	 * 1. all pages are linked together using zpdesc->next
 	 * 2. each sub-page point to zspage using zpdesc->zspage
 	 *
-	 * we set PG_private to identify the first zpdesc (i.e. no other zpdesc
-	 * has this flag set).
+	 * The first zpdesc has its zspage->first_zpdesc set to itself, no
+	 * other zpdesc has this set.
 	 */
 	for (i = 0; i < nr_zpdescs; i++) {
 		zpdesc = zpdescs[i];
@@ -1015,7 +1004,6 @@ static void create_page_chain(struct size_class *class, struct zspage *zspage,
 		zpdesc->next = NULL;
 		if (i == 0) {
 			zspage->first_zpdesc = zpdesc;
-			zpdesc_set_first(zpdesc);
 			if (unlikely(class->objs_per_zspage == 1 &&
 					class->pages_per_zspage == 1))
 				SetZsHugePage(zspage);

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 02/14] perf/ring_buffer: stop using PG_private as AUX page high-order marker
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
  2026-08-31 19:25 ` [PATCH v2 01/14] mm/zsmalloc: replace PG_private with pointer comparison Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 03/14] xen/grant-table: stop setting PG_private on pages for grant mapping Zi Yan
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Namhyung Kim, Thomas Gleixner,
	Borislav Petkov, Dave Hansen, x86, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, H. Peter Anvin, linux-perf-users

A high-order AUX page sets PG_private on its first page and stores the
order in first_page->private. Stop using PG_private and check
first_page->private for AUX page order only in the ring buffer and its
users. This is fine because page->private is 0 for order-0 AUX pages,
matching the page order.

It prepares for a future commit that remove PG_private.

No functional change intended.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
To: Peter Zijlstra <peterz@infradead.org>
To: Ingo Molnar <mingo@redhat.com>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Namhyung Kim <namhyung@kernel.org>
To: Thomas Gleixner <tglx@kernel.org>
To: Borislav Petkov <bp@alien8.de>
To: Dave Hansen <dave.hansen@linux.intel.com>
To: x86@kernel.org
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: James Clark <james.clark@linaro.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: linux-perf-users@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Acked-by: Usama Arif <usama.arif@linux.dev>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
 arch/x86/events/intel/bts.c | 3 ---
 arch/x86/events/intel/pt.c  | 6 ++----
 kernel/events/ring_buffer.c | 7 +++----
 3 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c
index cbac54cb3a9ec..5849392cf26d5 100644
--- a/arch/x86/events/intel/bts.c
+++ b/arch/x86/events/intel/bts.c
@@ -66,9 +66,6 @@ static struct pmu bts_pmu;
 
 static int buf_nr_pages(struct page *page)
 {
-	if (!PagePrivate(page))
-		return 1;
-
 	return 1 << page_private(page);
 }
 
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 5754cd4055628..49349afee6119 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -781,8 +781,7 @@ static int topa_insert_pages(struct pt_buffer *buf, int cpu, gfp_t gfp)
 	struct page *p;
 
 	p = virt_to_page(buf->data_pages[buf->nr_pages]);
-	if (PagePrivate(p))
-		order = page_private(p);
+	order = page_private(p);
 
 	if (topa_table_full(topa)) {
 		topa = topa_alloc(cpu, gfp);
@@ -1296,8 +1295,7 @@ static int pt_buffer_try_single(struct pt_buffer *buf, int nr_pages)
 	if (!intel_pt_validate_hw_cap(PT_CAP_single_range_output))
 		goto out;
 
-	if (PagePrivate(p))
-		order = page_private(p);
+	order = page_private(p);
 
 	if (1 << order != nr_pages)
 		goto out;
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 9fe92161715e0..061b5cb222266 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -630,11 +630,10 @@ static struct page *rb_alloc_aux_page(int node, int order)
 		/*
 		 * Communicate the allocation size to the driver:
 		 * if we managed to secure a high-order allocation,
-		 * set its first page's private to this order;
-		 * !PagePrivate(page) means it's just a normal page.
+		 * set its first page's private to this order, otherwise page's
+		 * private remains zero.
 		 */
 		split_page(page, order);
-		SetPagePrivate(page);
 		set_page_private(page, order);
 	}
 
@@ -645,7 +644,7 @@ static void rb_free_aux_page(struct perf_buffer *rb, int idx)
 {
 	struct page *page = virt_to_page(rb->aux_pages[idx]);
 
-	ClearPagePrivate(page);
+	set_page_private(page, 0);
 	__free_page(page);
 }
 

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 03/14] xen/grant-table: stop setting PG_private on pages for grant mapping
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
  2026-08-31 19:25 ` [PATCH v2 01/14] mm/zsmalloc: replace PG_private with pointer comparison Zi Yan
  2026-08-31 19:25 ` [PATCH v2 02/14] perf/ring_buffer: stop using PG_private as AUX page high-order marker Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 04/14] fscrypt: stop setting PG_private on bounce page Zi Yan
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, xen-devel

gnttab_alloc_pages() stores xen_page_foreign in page->private. On 32-bit, a
pointer to an allocated xen_page_foreign is stored; on 64-bit,
xen_page_foreign is stored inline. Checking page->private != NULL is enough
to tell whether a xen_page_foreign needs to be freed on 32-bit and
page->private is zeroed unconditionally on 64-bit.

It prepares for a future commit that remove PG_private.

No functional change intended.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
Signed-off-by: Zi Yan <ziy@nvidia.com>
To: Juergen Gross <jgross@suse.com>
To: Stefano Stabellini <sstabellini@kernel.org>
Cc: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Cc: xen-devel@lists.xenproject.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/xen/balloon.c     |  5 +++++
 drivers/xen/grant-table.c | 11 +++++------
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index e7f74ea7cd5eb..fdb18348cfdfe 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -182,6 +182,11 @@ static struct page *balloon_retrieve(bool require_lowmem)
 
 	__ClearPageOffline(page);
 	dec_node_page_state(page, NR_BALLOON_PAGES);
+	/*
+	 * clear page->private before giving it out, since it might be used to
+	 * store xen_page_foreign info.
+	 */
+	set_page_private(page, 0);
 
 	return page;
 }
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 69922be28b54c..993f89f048e21 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -863,10 +863,10 @@ EXPORT_SYMBOL_GPL(gnttab_free_auto_xlat_frames);
 
 int gnttab_pages_set_private(int nr_pages, struct page **pages)
 {
+#if BITS_PER_LONG < 64
 	int i;
 
 	for (i = 0; i < nr_pages; i++) {
-#if BITS_PER_LONG < 64
 		struct xen_page_foreign *foreign;
 
 		foreign = kzalloc_obj(*foreign);
@@ -874,9 +874,9 @@ int gnttab_pages_set_private(int nr_pages, struct page **pages)
 			return -ENOMEM;
 
 		set_page_private(pages[i], (unsigned long)foreign);
-#endif
-		SetPagePrivate(pages[i]);
 	}
+#endif
+	/* Data is stored in page->private on 64-bit */
 
 	return 0;
 }
@@ -1031,12 +1031,11 @@ void gnttab_pages_clear_private(int nr_pages, struct page **pages)
 	int i;
 
 	for (i = 0; i < nr_pages; i++) {
-		if (PagePrivate(pages[i])) {
 #if BITS_PER_LONG < 64
+		if (page_private(pages[i]))
 			kfree((void *)page_private(pages[i]));
 #endif
-			ClearPagePrivate(pages[i]);
-		}
+		set_page_private(pages[i], 0);
 	}
 }
 EXPORT_SYMBOL_GPL(gnttab_pages_clear_private);

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 04/14] fscrypt: stop setting PG_private on bounce page
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (2 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 03/14] xen/grant-table: stop setting PG_private on pages for grant mapping Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 05/14] mm/hugetlb: use direct assignment instead of folio_change_private() Zi Yan
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Eric Biggers,
	Theodore Y. Ts'o, Jaegeuk Kim, linux-fscrypt

The pointer to a plain text folio is stored in bound_page->private and
cannot be NULL until the bounce_page is freed, making PG_private redundant.

It prepares for a future commit that remove PG_private.

No functional change intended.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
To: Eric Biggers <ebiggers@kernel.org>
To: "Theodore Y. Ts'o" <tytso@mit.edu>
To: Jaegeuk Kim <jaegeuk@kernel.org>
Cc: linux-fscrypt@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Acked-by: Eric Biggers <ebiggers@kernel.org>
Acked-by: Usama Arif <usama.arif@linux.dev>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
 fs/crypto/crypto.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 5286a124b0d98..aced5c50a4601 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -65,7 +65,6 @@ void fscrypt_free_bounce_page(struct page *bounce_page)
 	if (!bounce_page)
 		return;
 	set_page_private(bounce_page, (unsigned long)NULL);
-	ClearPagePrivate(bounce_page);
 	mempool_free(bounce_page, fscrypt_bounce_page_pool);
 }
 EXPORT_SYMBOL(fscrypt_free_bounce_page);
@@ -210,7 +209,6 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio,
 			return ERR_PTR(err);
 		}
 	}
-	SetPagePrivate(ciphertext_page);
 	set_page_private(ciphertext_page, (unsigned long)folio);
 	return ciphertext_page;
 }

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 05/14] mm/hugetlb: use direct assignment instead of folio_change_private()
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (3 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 04/14] fscrypt: stop setting PG_private on bounce page Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-09-03  0:05   ` Gregory Price
  2026-08-31 19:25 ` [PATCH v2 06/14] f2fs: stop using PG_private Zi Yan
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Oscar Salvador

folio_change_private() should be used along with folio_attach_private() and
folio_detach_private(), where adding and remove ->private content requires
folio refcount change. add_hugetlb_folio() simply sets folio->private to
NULL without refcount manipulation. Change it to direct assignment to avoid
semantic confusion.

It prepares for a future commit that remove PG_private.

No functional change intended.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
To: Muchun Song <muchun.song@linux.dev>
To: Oscar Salvador <osalvador@suse.de>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Acked-by: Usama Arif <usama.arif@linux.dev>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
 mm/hugetlb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 7857728457952..4b6753b87162d 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1433,10 +1433,10 @@ void add_hugetlb_folio(struct hstate *h, struct folio *folio,
 	}
 
 	__folio_set_hugetlb(folio);
-	folio_change_private(folio, NULL);
+	folio->private = NULL;
 	/*
-	 * We have to set hugetlb_vmemmap_optimized again as above
-	 * folio_change_private(folio, NULL) cleared it.
+	 * The hugetlb flags live in folio->private and are cleared by the above
+	 * assignment. Restore the hugetlb_vmemmap_optimized flag.
 	 */
 	folio_set_hugetlb_vmemmap_optimized(folio);
 

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 06/14] f2fs: stop using PG_private
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (4 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 05/14] mm/hugetlb: use direct assignment instead of folio_change_private() Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 07/14] erofs: mm/pagemap: add readahead_folio_last() to avoid folio->private Zi Yan
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Jaegeuk Kim, Chao Yu,
	linux-f2fs-devel

f2fs sets its PAGE_PRIVATE_* flags in page->private and checking
page->private != NULL is equivalent to checking PG_private. Change
PagePrivate() to page_private(). Meanwhile, in set_page_private_##name(),
page->private is first set to 0/NULL before an PAGE_PRIVATE_* flag is set,
but it can cause confusion when PG_private is removed and
page->private != NULL is used instead. Change it to initialize
page->private to PAGE_PRIVATE_NOT_POINTER instead and retain the original
semantics.

It prepares for a future commit that removes PG_private.

No functional change intended.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
To: Jaegeuk Kim <jaegeuk@kernel.org>
To: Chao Yu <chao@kernel.org>
Cc: linux-f2fs-devel@lists.sourceforge.net
Cc: linux-kernel@vger.kernel.org
Acked-by: Usama Arif <usama.arif@linux.dev>
Acked-by: Chao Yu <chao@kernel.org>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
 fs/f2fs/f2fs.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 9940a6cecf1a2..2f7ab5888b078 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2691,7 +2691,7 @@ static inline bool folio_test_f2fs_##name(const struct folio *folio)	\
 }									\
 static inline bool page_private_##name(struct page *page) \
 { \
-	return PagePrivate(page) && \
+	return page_private(page) && \
 		test_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)) && \
 		test_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \
 }
@@ -2710,9 +2710,9 @@ static inline void folio_set_f2fs_##name(struct folio *folio)		\
 }									\
 static inline void set_page_private_##name(struct page *page) \
 { \
-	if (!PagePrivate(page)) \
-		attach_page_private(page, (void *)0); \
-	set_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)); \
+	if (!page_private(page)) \
+		attach_page_private(page, \
+				(void *)BIT(PAGE_PRIVATE_NOT_POINTER)); \
 	set_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \
 }
 

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 07/14] erofs: mm/pagemap: add readahead_folio_last() to avoid folio->private
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (5 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 06/14] f2fs: stop using PG_private Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 08/14] erofs: use folio_attach/detach_private() instead of direct assignment Zi Yan
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Gao Xiang, Chao Yu, Jan Kara,
	Yue Hu, Jeffle Xu, Sandeep Dhavale, Hongbo Li, Chunhai Guo,
	linux-erofs, linux-fsdevel

erofs needs to traverse readahead folios in reverse order to achieve
maximum performance by
1. reading all folios from readahead_folio();
2. storing the prior folio pointer in folio->private;
3. traverse from the last folio to the first one.

Add readahead_folio_last() to achieve the same function without using
folio->private. __readahead_advance() helper shares readahead_control
adjustment code among __readahead_folio(), readahead_folio_last(), and
__readahead_batch() by checking new private member, _forward, of
readahead_control.

It prepares for a future commit that replaces PG_private checks with
!folio->private checks. After switching the checks, erofs's use of
folio->private without bumping folio refcount can cause unexpected
outcomes, e.g., in filemap_release_folio(), try_to_free_buffers() becomes
reachable.

No functional change intended.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
Signed-off-by: Zi Yan <ziy@nvidia.com>
To: Gao Xiang <xiang@kernel.org>
To: Chao Yu <chao@kernel.org>
To: "Matthew Wilcox (Oracle)" <willy@infradead.org>
To: Jan Kara <jack@suse.cz>
Cc: Yue Hu <zbestahu@gmail.com>
Cc: Jeffle Xu <jefflexu@linux.alibaba.com>
Cc: Sandeep Dhavale <dhavale@google.com>
Cc: Hongbo Li <hongbohbli@tencent.com>
Cc: Chunhai Guo <guochunhai@vivo.com>
Cc: linux-erofs@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-mm@kvack.org
---
 fs/erofs/zdata.c        | 13 +++---------
 include/linux/pagemap.h | 56 ++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
index e1e25ca0d1904..78fd7d980e957 100644
--- a/fs/erofs/zdata.c
+++ b/fs/erofs/zdata.c
@@ -1898,21 +1898,14 @@ static void z_erofs_readahead(struct readahead_control *rac)
 	struct inode *realinode = erofs_real_inode(sharedinode, &need_iput);
 	Z_EROFS_DEFINE_FRONTEND(f, realinode, sharedinode, readahead_pos(rac));
 	unsigned int nrpages = readahead_count(rac);
-	struct folio *head = NULL, *folio;
+	struct folio *folio;
 	int err;
 
 	trace_erofs_readahead(realinode, readahead_index(rac), nrpages, false);
 	z_erofs_pcluster_readmore(&f, rac, true);
-	while ((folio = readahead_folio(rac))) {
-		folio->private = head;
-		head = folio;
-	}
-
-	/* traverse in reverse order for best metadata I/O performance */
-	while (head) {
-		folio = head;
-		head = folio_get_private(folio);
 
+	/* traverse from last to first for best metadata I/O performance */
+	while ((folio = readahead_folio_last(rac))) {
 		err = z_erofs_scan_folio(&f, folio, true);
 		if (err && err != -EINTR)
 			erofs_err(realinode->i_sb, "readahead error at folio %lu @ nid %llu",
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 0adfa6605653d..546e987d5cda7 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -1416,6 +1416,7 @@ struct readahead_control {
 	bool dropbehind;
 	bool _workingset;
 	unsigned long _pflags;
+	bool _forward;
 };
 
 #define DEFINE_READAHEAD(ractl, f, r, m, i)				\
@@ -1480,18 +1481,25 @@ void page_cache_async_readahead(struct address_space *mapping,
 	page_cache_async_ra(&ractl, folio, req_count);
 }
 
+static inline void __readahead_advance(struct readahead_control *rac)
+{
+	if (rac->_forward)
+		rac->_index += rac->_batch_count;
+
+	rac->_nr_pages -= rac->_batch_count;
+	rac->_batch_count = 0;
+}
+
 static inline struct folio *__readahead_folio(struct readahead_control *ractl)
 {
 	struct folio *folio;
 
 	BUG_ON(ractl->_batch_count > ractl->_nr_pages);
-	ractl->_nr_pages -= ractl->_batch_count;
-	ractl->_index += ractl->_batch_count;
+	__readahead_advance(ractl);
+	ractl->_forward = true;
 
-	if (!ractl->_nr_pages) {
-		ractl->_batch_count = 0;
+	if (!ractl->_nr_pages)
 		return NULL;
-	}
 
 	folio = xa_load(&ractl->mapping->i_pages, ractl->_index);
 	VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
@@ -1517,6 +1525,39 @@ static inline struct folio *readahead_folio(struct readahead_control *ractl)
 	return folio;
 }
 
+/**
+ * readahead_folio_last - Get the next folio to read, from the tail.
+ * @ractl: The current readahead request.
+ *
+ * Like readahead_folio(), but walks the range back-to-front. The folio is
+ * returned locked with its refcount dropped; the caller unlocks it once I/O
+ * completes. Compound folios are returned once, at their head index.
+ *
+ * Context: The folio is locked.
+ * Return: A pointer to the next folio, or %NULL when done.
+ */
+static inline struct folio *readahead_folio_last(struct readahead_control *ractl)
+{
+	struct folio *folio;
+
+	/* Drop the previously returned batch from the remaining range. */
+	__readahead_advance(ractl);
+	ractl->_forward = false;
+
+	if (!ractl->_nr_pages)
+		return NULL;
+
+	/* xa_load() follows sibling entries, so a tail index returns the head */
+	folio = xa_load(&ractl->mapping->i_pages,
+			ractl->_index + ractl->_nr_pages - 1);
+	VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
+
+	ractl->_batch_count = folio_nr_pages(folio);
+
+	folio_put(folio);
+	return folio;
+}
+
 static inline unsigned int __readahead_batch(struct readahead_control *rac,
 		struct page **array, unsigned int array_sz)
 {
@@ -1525,9 +1566,8 @@ static inline unsigned int __readahead_batch(struct readahead_control *rac,
 	struct folio *folio;
 
 	BUG_ON(rac->_batch_count > rac->_nr_pages);
-	rac->_nr_pages -= rac->_batch_count;
-	rac->_index += rac->_batch_count;
-	rac->_batch_count = 0;
+	__readahead_advance(rac);
+	rac->_forward = true;
 
 	xas_set(&xas, rac->_index);
 	rcu_read_lock();

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 08/14] erofs: use folio_attach/detach_private() instead of direct assignment
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (6 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 07/14] erofs: mm/pagemap: add readahead_folio_last() to avoid folio->private Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 09/14] mm/page-flags: check page/folio->private instead of PG_private Zi Yan
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Gao Xiang, Chao Yu, Yue Hu,
	Jeffle Xu, Sandeep Dhavale, Hongbo Li, Chunhai Guo, linux-erofs

erofs_onlinefolio_init/split/end() use folio->private without setting
PG_private or increasing folio refcount and it works. But after PG_private
is replaced by checking folio->private in a future commit, it can break
folio_expected_ref_count(), since the folio has private data without
elevated refcount. Change them to use folio_attach/detach_private().

Furthermore, because folio->private is used to store in-flight I/O counter
and the counter reaches 0 when all I/O completes successfully without error
or being dirty, ->private=0 causes folio_detach_private() to not drop the
elevated folio refcount. Solve this issue by using bias=1 for the counter,
so that ->private stays non NULL throughout every attach-to-detach process.
Add a macro EROFS_ONLINEFOLIO_BIAS=1. While at it, fix the comment about
->private bit layout and add EROFS_ONLINEFOLIO_COUNT_MASK.

It prepares for a future commit that removes PG_private.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
To: Gao Xiang <xiang@kernel.org>
To: Chao Yu <chao@kernel.org>
Cc: Yue Hu <zbestahu@gmail.com>
Cc: Jeffle Xu <jefflexu@linux.alibaba.com>
Cc: Sandeep Dhavale <dhavale@google.com>
Cc: Hongbo Li <hongbohbli@tencent.com>
Cc: Chunhai Guo <guochunhai@vivo.com>
Cc: linux-erofs@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
Reviewed-by: Gao Xiang <xiang@kernel.org>
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
 fs/erofs/data.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/fs/erofs/data.c b/fs/erofs/data.c
index 0885b1f2fc925..f71c7b51bb720 100644
--- a/fs/erofs/data.c
+++ b/fs/erofs/data.c
@@ -239,19 +239,23 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
 /*
  * bit 30: I/O error occurred on this folio
  * bit 29: CPU has dirty data in D-cache (needs aliasing handling);
- * bit 0 - 29: remaining parts to complete this folio
+ * bit 0 - 28: remaining parts to complete this folio, biased by 1 so that
+ *	       ->private stays non-NULL while the folio is attached
  */
 #define EROFS_ONLINEFOLIO_EIO		30
 #define EROFS_ONLINEFOLIO_DIRTY		29
+#define EROFS_ONLINEFOLIO_COUNT_MASK	(BIT(EROFS_ONLINEFOLIO_DIRTY) - 1)
+#define EROFS_ONLINEFOLIO_BIAS		1
 
 void erofs_onlinefolio_init(struct folio *folio)
 {
 	union {
 		atomic_t o;
 		void *v;
-	} u = { .o = ATOMIC_INIT(1) };
+	} u = { .o = ATOMIC_INIT(1 + EROFS_ONLINEFOLIO_BIAS) };
 
-	folio->private = u.v;	/* valid only if file-backed folio is locked */
+	/* valid only if file-backed folio is locked */
+	folio_attach_private(folio, u.v);
 }
 
 void erofs_onlinefolio_split(struct folio *folio)
@@ -265,14 +269,14 @@ void erofs_onlinefolio_end(struct folio *folio, int err, bool dirty)
 
 	do {
 		orig = atomic_read((atomic_t *)&folio->private);
-		DBG_BUGON(orig <= 0);
+		DBG_BUGON((orig & EROFS_ONLINEFOLIO_COUNT_MASK) <= EROFS_ONLINEFOLIO_BIAS);
 		v = dirty << EROFS_ONLINEFOLIO_DIRTY;
 		v |= (orig - 1) | (!!err << EROFS_ONLINEFOLIO_EIO);
 	} while (atomic_cmpxchg((atomic_t *)&folio->private, orig, v) != orig);
 
-	if (v & (BIT(EROFS_ONLINEFOLIO_DIRTY) - 1))
+	if ((v & EROFS_ONLINEFOLIO_COUNT_MASK) != EROFS_ONLINEFOLIO_BIAS)
 		return;
-	folio->private = 0;
+	folio_detach_private(folio);
 	if (v & BIT(EROFS_ONLINEFOLIO_DIRTY))
 		flush_dcache_folio(folio);
 	folio_end_read(folio, !(v & BIT(EROFS_ONLINEFOLIO_EIO)));

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 09/14] mm/page-flags: check page/folio->private instead of PG_private
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (7 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 08/14] erofs: use folio_attach/detach_private() instead of direct assignment Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-09-01  2:11   ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 10/14] mm/page-flags: introduce folio_test_fs_private() Zi Yan
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Steven Rostedt, Masami Hiramatsu,
	Jan Kara, Mathieu Desnoyers, Matthew Brost, Joshua Hahn,
	Rakie Kim, Byungchul Park, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	linux-fsdevel, linux-trace-kernel

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.

folio_expected_ref_count() can be called without folio lock, so annotate
folio_test_private() with data_race() to avoid triggering race condition
checks. While at it, annotate folio->mapping too.

folio_set/clear_private() and Set/ClearPagePrivate() become no-ops.
PG_private is no longer checked at page free time.

Remove KPF_PRIVATE since PG_private is no longer used.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
Signed-off-by: Zi Yan <ziy@nvidia.com>
To: Andrew Morton <akpm@linux-foundation.org>
To: David Hildenbrand <david@kernel.org>
To: Steven Rostedt <rostedt@goodmis.org>
To: Masami Hiramatsu <mhiramat@kernel.org>
To: Lorenzo Stoakes <ljs@kernel.org>
To: "Matthew Wilcox (Oracle)" <willy@infradead.org>
To: Jan Kara <jack@suse.cz>
To: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Zi Yan <ziy@nvidia.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Nico Pache <nico.pache@linux.dev>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Usama Arif <usama.arif@linux.dev>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
Cc: Rakie Kim <rakie.kim@sk.com>
Cc: Byungchul Park <byungchul@sk.com>
Cc: Gregory Price <gourry@gourry.net>
Cc: Ying Huang <ying.huang@linux.alibaba.com>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: Qi Zheng <qi.zheng@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Kairui Song <kasong@tencent.com>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Yuanchu Xie <yuanchu@google.com>
Cc: Wei Xu <weixugc@google.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-mm@kvack.org
Cc: linux-trace-kernel@vger.kernel.org
---
 fs/proc/page.c                    |  1 -
 include/linux/kernel-page-flags.h |  1 -
 include/linux/mm.h                | 22 +++++++++++++++-------
 include/linux/page-flags.h        | 26 +++++++++++++++++++++-----
 include/trace/events/pagemap.h    |  4 +++-
 mm/huge_memory.c                  |  4 +++-
 mm/migrate.c                      |  3 ++-
 mm/page-writeback.c               |  5 ++++-
 mm/vmscan.c                       |  3 ++-
 tools/mm/page-types.c             |  2 --
 10 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/fs/proc/page.c b/fs/proc/page.c
index 260772b20bd99..f90e1030825e9 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -232,7 +232,6 @@ u64 stable_page_flags(const struct page *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);
diff --git a/include/linux/kernel-page-flags.h b/include/linux/kernel-page-flags.h
index 196778a087c4d..fe5ab6e50bd70 100644
--- a/include/linux/kernel-page-flags.h
+++ b/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
diff --git a/include/linux/mm.h b/include/linux/mm.h
index dd09c438fa23e..786f8a47cea6d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3022,9 +3022,9 @@ static inline bool folio_maybe_mapped_shared(struct folio *folio)
  * @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),
@@ -3062,10 +3062,18 @@ static inline int folio_expected_ref_count(const struct folio *folio)
 	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.
+		 * Use data_race() since folio might not be locked.
+		 */
+		ref_count += data_race(folio_test_private(folio)) &&
+			     !folio_test_hugetlb(folio) &&
+			     !folio_test_swapcache(folio);
 	}
 
 	/* One reference per page table mapping. */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 7a863572adce7..ee7abb3000c11 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -578,7 +578,23 @@ FOLIO_FLAG(swapbacked, FOLIO_HEAD_PAGE)
  * for its own purposes.
  * - PG_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)
+{
+	return folio->private;
+}
+
+static __always_inline int PagePrivate(const struct page *page)
+{
+	return !!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 */
@@ -1170,7 +1186,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
  */
 #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)
@@ -1194,8 +1210,6 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
 	(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_private - Determine if folio has private stuff
  * @folio: The folio to be checked
@@ -1205,7 +1219,9 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
  */
 static inline int folio_has_private(const struct folio *folio)
 {
-	return !!(folio->flags.f & PAGE_FLAGS_PRIVATE);
+	return (!!folio->private && !folio_test_swapcache(folio) &&
+		!folio_test_hugetlb(folio)) ||
+		folio_test_private_2(folio);
 }
 
 #undef PF_ANY
diff --git a/include/trace/events/pagemap.h b/include/trace/events/pagemap.h
index 36c3a90f0acca..fb9abec40ec79 100644
--- a/include/trace/events/pagemap.h
+++ b/include/trace/events/pagemap.h
@@ -22,7 +22,9 @@
 	(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_test_private(folio) && \
+	 !folio_test_swapcache(folio) && \
+	 !folio_test_hugetlb(folio)	? PAGEMAP_BUFFERS    : 0) \
 	)
 
 TRACE_EVENT(mm_lru_insertion,
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index ced400f72d43a..546b37ccce37f 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4810,7 +4810,9 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
 		 * 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_test_private(folio) &&
+		      !folio_test_swapcache(folio) &&
+		      !folio_test_hugetlb(folio)) &&
 		    folio_expected_ref_count(folio) != folio_ref_count(folio))
 			goto next;
 
diff --git a/mm/migrate.c b/mm/migrate.c
index 15b45832bcfa7..f14e7bfee14bd 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1327,7 +1327,8 @@ static int migrate_folio_unmap(new_folio_t get_new_folio,
 	 * free the metadata, so the page can be freed.
 	 */
 	if (!src->mapping) {
-		if (folio_test_private(src)) {
+		if (folio_test_private(src) && !folio_test_swapcache(src) &&
+		    !folio_test_hugetlb(src)) {
 			try_to_free_buffers(src);
 			goto out;
 		}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index eeab25d6ce364..4022d6c381896 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2705,7 +2705,10 @@ bool filemap_dirty_folio(struct address_space *mapping, struct folio *folio)
 	if (folio_test_set_dirty(folio))
 		return false;
 
-	__folio_mark_dirty(folio, mapping, !folio_test_private(folio));
+	__folio_mark_dirty(folio, mapping,
+			   !(folio_test_private(folio) &&
+			     !folio_test_swapcache(folio) &&
+			     !folio_test_hugetlb(folio)));
 
 	if (mapping->host) {
 		/* !PageAnon && !swapper_space */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index f11491ee9ed5c..ac275eec086b9 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -955,7 +955,8 @@ static void folio_check_dirty_writeback(struct folio *folio,
 	*writeback = folio_test_writeback(folio);
 
 	/* Verify dirty/writeback state if the filesystem supports it */
-	if (!folio_test_private(folio))
+	if (!(folio_test_private(folio) && !folio_test_swapcache(folio) &&
+	      !folio_test_hugetlb(folio)))
 		return;
 
 	mapping = folio_mapping(folio);
diff --git a/tools/mm/page-types.c b/tools/mm/page-types.c
index 7fc5a8be5997f..47e4781c5fc38 100644
--- a/tools/mm/page-types.c
+++ b/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_names[] = {
 	[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",

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 10/14] mm/page-flags: introduce folio_test_fs_private()
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (8 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 09/14] mm/page-flags: check page/folio->private instead of PG_private Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 11/14] treewide: remove folio_set/clear_private() Zi Yan
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Matthew Brost, Joshua Hahn, Rakie Kim,
	Byungchul Park, linux-fsdevel, linux-trace-kernel

folio_test_fs_private() wraps folio->private != NULL check and excludes
swapcache and hugetlb folios, since swapcache uses swp_entry_t overlapping
with folio->private and hugetlb sets its own flags in folio->private.
Replace open code with the helper, since core MM does this check
frequently.

No functional change intended.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
Signed-off-by: Zi Yan <ziy@nvidia.com>
To: Andrew Morton <akpm@linux-foundation.org>
To: David Hildenbrand <david@kernel.org>
To: Steven Rostedt <rostedt@goodmis.org>
To: Masami Hiramatsu <mhiramat@kernel.org>
To: Lorenzo Stoakes <ljs@kernel.org>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Zi Yan <ziy@nvidia.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Nico Pache <nico.pache@linux.dev>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Usama Arif <usama.arif@linux.dev>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
Cc: Rakie Kim <rakie.kim@sk.com>
Cc: Byungchul Park <byungchul@sk.com>
Cc: Gregory Price <gourry@gourry.net>
Cc: Ying Huang <ying.huang@linux.alibaba.com>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-mm@kvack.org
Cc: linux-trace-kernel@vger.kernel.org
---
 include/linux/mm.h             |  4 +---
 include/linux/page-flags.h     | 21 ++++++++++++++++++---
 include/trace/events/pagemap.h |  4 +---
 mm/huge_memory.c               |  4 +---
 mm/migrate.c                   |  3 +--
 mm/page-writeback.c            |  5 +----
 mm/vmscan.c                    |  3 +--
 7 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 786f8a47cea6d..b5b60f3ad58dc 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3071,9 +3071,7 @@ static inline int folio_expected_ref_count(const struct folio *folio)
 		 * One reference from filesystem private data.
 		 * Use data_race() since folio might not be locked.
 		 */
-		ref_count += data_race(folio_test_private(folio)) &&
-			     !folio_test_hugetlb(folio) &&
-			     !folio_test_swapcache(folio);
+		ref_count += data_race(folio_test_fs_private(folio));
 	}
 
 	/* One reference per page table mapping. */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index ee7abb3000c11..9b585e68127a2 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -1210,6 +1210,23 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
 	(0xffUL /* order */		| 1UL << PG_has_hwpoisoned |	\
 	 1UL << PG_large_rmappable	| 1UL << PG_partially_mapped)
 
+/**
+ * folio_test_fs_private - check if the folio has filesystem private data
+ * @folio: The folio to check.
+ *
+ * Use this in code that may encounter swapcache or hugetlb folios but only
+ * wants to detect filesystem private data. 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.
+ *
+ * Return: true if folio->private is set and the folio is neither swapcache
+ * nor hugetlb.
+ */
+static inline bool folio_test_fs_private(const struct folio *folio)
+{
+	return folio_test_private(folio) && !folio_test_swapcache(folio) &&
+	       !folio_test_hugetlb(folio);
+}
 /**
  * folio_has_private - Determine if folio has private stuff
  * @folio: The folio to be checked
@@ -1219,9 +1236,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
  */
 static inline int folio_has_private(const struct folio *folio)
 {
-	return (!!folio->private && !folio_test_swapcache(folio) &&
-		!folio_test_hugetlb(folio)) ||
-		folio_test_private_2(folio);
+	return folio_test_fs_private(folio) || folio_test_private_2(folio);
 }
 
 #undef PF_ANY
diff --git a/include/trace/events/pagemap.h b/include/trace/events/pagemap.h
index fb9abec40ec79..5425ef7bbae6e 100644
--- a/include/trace/events/pagemap.h
+++ b/include/trace/events/pagemap.h
@@ -22,9 +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) && \
-	 !folio_test_swapcache(folio) && \
-	 !folio_test_hugetlb(folio)	? PAGEMAP_BUFFERS    : 0) \
+	(folio_test_fs_private(folio)	? PAGEMAP_BUFFERS    : 0) \
 	)
 
 TRACE_EVENT(mm_lru_insertion,
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 546b37ccce37f..d085fd09466ef 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4810,9 +4810,7 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
 		 * 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) &&
-		      !folio_test_swapcache(folio) &&
-		      !folio_test_hugetlb(folio)) &&
+		if (!folio_test_fs_private(folio) &&
 		    folio_expected_ref_count(folio) != folio_ref_count(folio))
 			goto next;
 
diff --git a/mm/migrate.c b/mm/migrate.c
index f14e7bfee14bd..666a7365e16e8 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1327,8 +1327,7 @@ static int migrate_folio_unmap(new_folio_t get_new_folio,
 	 * free the metadata, so the page can be freed.
 	 */
 	if (!src->mapping) {
-		if (folio_test_private(src) && !folio_test_swapcache(src) &&
-		    !folio_test_hugetlb(src)) {
+		if (folio_test_fs_private(src)) {
 			try_to_free_buffers(src);
 			goto out;
 		}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 4022d6c381896..e03a1c46bce01 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2705,10 +2705,7 @@ bool filemap_dirty_folio(struct address_space *mapping, struct folio *folio)
 	if (folio_test_set_dirty(folio))
 		return false;
 
-	__folio_mark_dirty(folio, mapping,
-			   !(folio_test_private(folio) &&
-			     !folio_test_swapcache(folio) &&
-			     !folio_test_hugetlb(folio)));
+	__folio_mark_dirty(folio, mapping, !folio_test_fs_private(folio));
 
 	if (mapping->host) {
 		/* !PageAnon && !swapper_space */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index ac275eec086b9..29051c0f89881 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -955,8 +955,7 @@ static void folio_check_dirty_writeback(struct folio *folio,
 	*writeback = folio_test_writeback(folio);
 
 	/* Verify dirty/writeback state if the filesystem supports it */
-	if (!(folio_test_private(folio) && !folio_test_swapcache(folio) &&
-	      !folio_test_hugetlb(folio)))
+	if (!folio_test_fs_private(folio))
 		return;
 
 	mapping = folio_mapping(folio);

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 11/14] treewide: remove folio_set/clear_private()
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (9 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 10/14] mm/page-flags: introduce folio_test_fs_private() Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 12/14] treewide: replace PagePrivate() with page_private() Zi Yan
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Trond Myklebust, Anna Schumaker,
	Jan Kara, Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park,
	linux-nfs, linux-fsdevel

They are no-ops now. Remove them.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
Signed-off-by: Zi Yan <ziy@nvidia.com>
To: Trond Myklebust <trondmy@kernel.org>
To: Anna Schumaker <anna@kernel.org>
To: "Matthew Wilcox (Oracle)" <willy@infradead.org>
To: Jan Kara <jack@suse.cz>
To: Andrew Morton <akpm@linux-foundation.org>
To: David Hildenbrand <david@kernel.org>
Cc: Zi Yan <ziy@nvidia.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
Cc: Rakie Kim <rakie.kim@sk.com>
Cc: Byungchul Park <byungchul@sk.com>
Cc: Gregory Price <gourry@gourry.net>
Cc: Ying Huang <ying.huang@linux.alibaba.com>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: linux-nfs@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-mm@kvack.org
---
 fs/nfs/write.c          | 2 --
 include/linux/pagemap.h | 4 +---
 mm/migrate.c            | 1 -
 3 files changed, 1 insertion(+), 6 deletions(-)

diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 623e7ef1f73d5..b6967b5286691 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -717,7 +717,6 @@ static void nfs_inode_add_request(struct nfs_page *req)
 	nfs_lock_request(req);
 	spin_lock(&mapping->i_private_lock);
 	set_bit(PG_MAPPED, &req->wb_flags);
-	folio_set_private(folio);
 	folio->private = req;
 	spin_unlock(&mapping->i_private_lock);
 	atomic_long_inc(&nfsi->nrequests);
@@ -745,7 +744,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
 
 			spin_lock(&mapping->i_private_lock);
 			folio->private = NULL;
-			folio_clear_private(folio);
 			clear_bit(PG_MAPPED, &req->wb_head->wb_flags);
 			spin_unlock(&mapping->i_private_lock);
 
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 546e987d5cda7..88b4c92b43575 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -594,7 +594,6 @@ static inline void folio_attach_private(struct folio *folio, void *data)
 {
 	folio_get(folio);
 	folio->private = data;
-	folio_set_private(folio);
 }
 
 /**
@@ -629,9 +628,8 @@ static inline void *folio_detach_private(struct folio *folio)
 {
 	void *data = folio_get_private(folio);
 
-	if (!folio_test_private(folio))
+	if (!data)
 		return NULL;
-	folio_clear_private(folio);
 	folio->private = NULL;
 	folio_put(folio);
 
diff --git a/mm/migrate.c b/mm/migrate.c
index 666a7365e16e8..5ca1548ca6d61 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -835,7 +835,6 @@ void folio_migrate_flags(struct folio *newfolio, struct folio *folio)
 	 */
 	if (folio_test_swapcache(folio))
 		folio_clear_swapcache(folio);
-	folio_clear_private(folio);
 
 	/* page->private contains hugetlb specific flags */
 	if (!folio_test_hugetlb(folio))

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 12/14] treewide: replace PagePrivate() with page_private()
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (10 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 11/14] treewide: remove folio_set/clear_private() Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 13/14] treewide: adjust comments on PagePrivate and PG_private Zi Yan
  2026-08-31 19:25 ` [PATCH v2 14/14] mm/page-flags: remove PG_private Zi Yan
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Song Liu, Yu Kuai, Ilya Dryomov,
	Alex Markuze, Viacheslav Dubeyko, Li Nan, Xiao Ni, linux-raid,
	ceph-devel

PG_private is going to be removed and its check is replaced by checking
page->private != NULL.

Replace page_buffers() with page_private() and delete page_buffers(),
since only two users left and both can be converted to use page_private().

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
Signed-off-by: Zi Yan <ziy@nvidia.com>
To: Song Liu <song@kernel.org>
To: Yu Kuai <yukuai@fygo.io>
To: Ilya Dryomov <idryomov@gmail.com>
To: Alex Markuze <amarkuze@redhat.com>
To: Viacheslav Dubeyko <slava@dubeyko.com>
Cc: Li Nan <magiclinan@didiglobal.com>
Cc: Xiao Ni <xiao@kernel.org>
Cc: linux-raid@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: ceph-devel@vger.kernel.org
---
 drivers/md/md-bitmap.c      | 6 +++---
 fs/ceph/addr.c              | 4 +---
 include/linux/buffer_head.h | 6 ------
 3 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index b8325cb09a371..0cf14bc1cff32 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -516,7 +516,7 @@ static void end_bitmap_write(struct bio *bio)
 
 static void write_file_page(struct bitmap *bitmap, struct page *page, int wait)
 {
-	struct buffer_head *bh = page_buffers(page);
+	struct buffer_head *bh = (struct buffer_head *)page_private(page);
 
 	while (bh && bh->b_blocknr) {
 		atomic_inc(&bitmap->pending_writes);
@@ -535,10 +535,10 @@ static void free_buffers(struct page *page)
 {
 	struct buffer_head *bh;
 
-	if (!PagePrivate(page))
+	if (!page_private(page))
 		return;
 
-	bh = page_buffers(page);
+	bh = (struct buffer_head *)page_private(page);
 	while (bh) {
 		struct buffer_head *next = bh->b_this_page;
 		free_buffer_head(bh);
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 657c2cb0f8811..fad17df1d5082 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -70,9 +70,7 @@ static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned
 
 static inline struct ceph_snap_context *page_snap_context(struct page *page)
 {
-	if (PagePrivate(page))
-		return (void *)page->private;
-	return NULL;
+	return (void *)page->private;
 }
 
 /*
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index fd2c7115c0542..e47fbd0387b69 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -175,12 +175,6 @@ static inline unsigned long bh_offset(const struct buffer_head *bh)
 	return (unsigned long)(bh)->b_data & (page_size(bh->b_page) - 1);
 }
 
-/* If we *know* page->private refers to buffer_heads */
-#define page_buffers(page)					\
-	({							\
-		BUG_ON(!PagePrivate(page));			\
-		((struct buffer_head *)page_private(page));	\
-	})
 #define folio_buffers(folio)		folio_get_private(folio)
 
 void buffer_check_dirty_writeback(struct folio *folio,

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 13/14] treewide: adjust comments on PagePrivate and PG_private
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (11 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 12/14] treewide: replace PagePrivate() with page_private() Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-08-31 19:25 ` [PATCH v2 14/14] mm/page-flags: remove PG_private Zi Yan
  13 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Ilya Dryomov, Alex Markuze,
	Viacheslav Dubeyko, Trond Myklebust, Anna Schumaker,
	Richard Weinberger, Zhihao Cheng, ceph-devel, linux-nfs,
	linux-mtd

PG_private is going to be deleted. Adjust related comments to refer to
page/folio->private instead.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
Signed-off-by: Zi Yan <ziy@nvidia.com>
To: Ilya Dryomov <idryomov@gmail.com>
To: Alex Markuze <amarkuze@redhat.com>
To: Viacheslav Dubeyko <slava@dubeyko.com>
To: Trond Myklebust <trondmy@kernel.org>
To: Anna Schumaker <anna@kernel.org>
To: Richard Weinberger <richard@nod.at>
To: Andrew Morton <akpm@linux-foundation.org>
To: David Hildenbrand <david@kernel.org>
Cc: Zhihao Cheng <chengzhihao1@huawei.com>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: ceph-devel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-nfs@vger.kernel.org
Cc: linux-mtd@lists.infradead.org
Cc: linux-mm@kvack.org
---
 fs/ceph/addr.c           |  4 ++--
 fs/nfs/file.c            |  4 ++--
 fs/ubifs/file.c          |  8 ++++----
 include/linux/mm.h       | 15 ++++++++-------
 include/linux/mm_types.h |  4 ++--
 5 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index fad17df1d5082..f9b2ec9550481 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -122,8 +122,8 @@ static bool ceph_dirty_folio(struct address_space *mapping, struct folio *folio)
 	spin_unlock(&ci->i_ceph_lock);
 
 	/*
-	 * Reference snap context in folio->private.  Also set
-	 * PagePrivate so that we get invalidate_folio callback.
+	 * Reference snap context in folio->private. Setting folio->private is
+	 * what gets us the invalidate_folio callback.
 	 */
 	VM_WARN_ON_FOLIO(folio->private, folio);
 	folio_attach_private(folio, snapc);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index e1bdd10b35f10..38f830a6467c9 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -484,7 +484,7 @@ static int nfs_write_end(const struct kiocb *iocb,
  * Partially or wholly invalidate a page
  * - Release the private state associated with a page if undergoing complete
  *   page invalidation
- * - Called if either PG_private or PG_fscache is set on the page
+ * - Called if either folio->private or PG_fscache is set on the page
  * - Caller holds page lock
  */
 static void nfs_invalidate_folio(struct folio *folio, size_t offset,
@@ -555,7 +555,7 @@ static void nfs_check_dirty_writeback(struct folio *folio,
  * Attempt to clear the private state associated with a page when an error
  * occurs that requires the cached contents of an inode to be written back or
  * destroyed
- * - Called if either PG_private or fscache is set on the page
+ * - Called if either page->private or fscache is set on the page
  * - Caller holds page lock
  * - Return 0 if successful, -error otherwise
  */
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index e73c28b12f97f..aa0298ce451ef 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -12,14 +12,14 @@
  * This file implements VFS file and inode operations for regular files, device
  * nodes and symlinks as well as address space operations.
  *
- * UBIFS uses 2 page flags: @PG_private and @PG_checked. @PG_private is set if
+ * UBIFS uses folio->private and page flag @PG_checked. folio->private is set if
  * the page is dirty and is used for optimization purposes - dirty pages are
- * not budgeted so the flag shows that 'ubifs_write_end()' should not release
+ * not budgeted so it shows that 'ubifs_write_end()' should not release
  * the budget for this page. The @PG_checked flag is set if full budgeting is
  * required for the page e.g., when it corresponds to a file hole or it is
  * beyond the file size. The budgeting is done in 'ubifs_write_begin()', because
  * it is OK to fail in this function, and the budget is released in
- * 'ubifs_write_end()'. So the @PG_private and @PG_checked flags carry
+ * 'ubifs_write_end()'. So the folio->private and the @PG_checked flag carry
  * information about how the page was budgeted, to make it possible to release
  * the budget properly.
  *
@@ -1509,7 +1509,7 @@ static vm_fault_t ubifs_vm_page_mkwrite(struct vm_fault *vmf)
 	 *
 	 * At the moment we do not know whether the folio is dirty or not, so we
 	 * assume that it is not and budget for a new folio. We could look at
-	 * the @PG_private flag and figure this out, but we may race with write
+	 * folio->private and figure this out, but we may race with write
 	 * back and the folio state may change by the time we lock it, so this
 	 * would need additional care. We do not bother with this at the
 	 * moment, although it might be good idea to do. Instead, we allocate
diff --git a/include/linux/mm.h b/include/linux/mm.h
index b5b60f3ad58dc..2855739a0f379 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2075,20 +2075,21 @@ vm_fault_t finish_fault(struct vm_fault *vmf);
  *
  * A pagecache page contains an opaque `private' member, which belongs to the
  * page's address_space. Usually, this is the address of a circular list of
- * the page's disk buffers. PG_private must be set to tell the VM to call
- * into the filesystem to release these pages.
+ * the page's disk buffers. It tells the VM to call into the filesystem to
+ * release these pages.
  *
  * A folio may belong to an inode's memory mapping. In this case,
  * folio->mapping points to the inode, and folio->index is the file
  * offset of the folio, in units of PAGE_SIZE.
  *
- * If pagecache pages are not associated with an inode, they are said to be
- * anonymous pages. These may become associated with the swapcache, and in that
- * case PG_swapcache is set, and page->private is an offset into the swapcache.
+ * If pagecache folios are not associated with an inode, they are said to be
+ * anonymous folios. These may become associated with the swapcache, and in that
+ * case PG_swapcache is set, and folio->private is an offset into the swapcache.
  *
  * In either case (swapcache or inode backed), the pagecache itself holds one
- * reference to the page. Setting PG_private should also increment the
- * refcount. The each user mapping also has a reference to the page.
+ * reference to the folio. Attaching filesystem private data via
+ * folio_attach_private() also increments the refcount. Each user mapping also
+ * has a reference to the folio.
  *
  * The pagecache pages are stored in a per-mapping radix tree, which is
  * rooted at mapping->i_pages, and indexed by offset.
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 6d815f6440c94..e35aece38b933 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -108,7 +108,7 @@ struct page {
 			};
 			/**
 			 * @private: Mapping-private opaque data.
-			 * Usually used for buffer_heads if PagePrivate.
+			 * Usually used for buffer_heads.
 			 * Used for swp_entry_t if swapcache flag set.
 			 * Indicates order in the buddy system if PageBuddy
 			 * or on pcp_llist.
@@ -675,7 +675,7 @@ static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc)
 #define STRUCT_PAGE_MAX_SHIFT	(order_base_2(sizeof(struct page)))
 
 /*
- * page_private can be used on tail pages.  However, PagePrivate is only
+ * page_private can be used on tail pages.  However, it is only
  * checked by the VM on the head page.  So page_private on the tail pages
  * should be used for data that's ancillary to the head page (eg attaching
  * buffer heads to tail pages after attaching buffer heads to the head page)

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 14/14] mm/page-flags: remove PG_private
  2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
                   ` (12 preceding siblings ...)
  2026-08-31 19:25 ` [PATCH v2 13/14] treewide: adjust comments on PagePrivate and PG_private Zi Yan
@ 2026-08-31 19:25 ` Zi Yan
  2026-09-01  2:17   ` Zi Yan
                     ` (2 more replies)
  13 siblings, 3 replies; 23+ messages in thread
From: Zi Yan @ 2026-08-31 19:25 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Baoquan He, Pasha Tatashin,
	Pratyush Yadav, Jonathan Corbet, Jan Kara, Steven Rostedt,
	Masami Hiramatsu, Dave Young, Shuah Khan, Mathieu Desnoyers,
	kexec, linux-doc, linux-fsdevel, linux-trace-kernel

folio->private != NULL indicates a folio carries private data, replacing
PG_private. All PG_private users are converted. Remove PG_private and
reserve the space as __PG_folio for future use.

Also update files in Documentation. hugetlbfs_reserv.rst is outdated and
left unchanged. It should be rewritten.

Assisted-by: Claude:claude-opus-4-8
Assisted-by: Codex:gpt-5
Signed-off-by: Zi Yan <ziy@nvidia.com>
To: Andrew Morton <akpm@linux-foundation.org>
To: Baoquan He <baoquan.he@linux.dev>
To: Mike Rapoport <rppt@kernel.org>
To: Pasha Tatashin <pasha.tatashin@soleen.com>
To: Pratyush Yadav <pratyush@kernel.org>
To: Jonathan Corbet <corbet@lwn.net>
To: "Matthew Wilcox (Oracle)" <willy@infradead.org>
To: Jan Kara <jack@suse.cz>
To: David Hildenbrand <david@kernel.org>
To: Steven Rostedt <rostedt@goodmis.org>
To: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Dave Young <ruirui.yang@linux.dev>
Cc: Shuah Khan <skhan@linuxfoundation.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: kexec@lists.infradead.org
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-mm@kvack.org
Cc: linux-trace-kernel@vger.kernel.org
---
 Documentation/admin-guide/kdump/vmcoreinfo.rst |  2 +-
 Documentation/filesystems/vfs.rst              |  6 +++---
 include/linux/page-flags.h                     | 19 ++-----------------
 include/trace/events/mmflags.h                 |  2 +-
 kernel/vmcore_info.c                           |  1 -
 5 files changed, 7 insertions(+), 23 deletions(-)

diff --git a/Documentation/admin-guide/kdump/vmcoreinfo.rst b/Documentation/admin-guide/kdump/vmcoreinfo.rst
index 7663c610fe901..5f1df6d080508 100644
--- a/Documentation/admin-guide/kdump/vmcoreinfo.rst
+++ b/Documentation/admin-guide/kdump/vmcoreinfo.rst
@@ -325,7 +325,7 @@ NR_FREE_PAGES
 On linux-2.6.21 or later, the number of free pages is in
 vm_stat[NR_FREE_PAGES]. Used to get the number of free pages.
 
-PG_lru|PG_private|PG_swapcache|PG_swapbacked|PG_hwpoison|PG_head_mask
+PG_lru|PG_swapcache|PG_swapbacked|PG_hwpoison|PG_head_mask
 --------------------------------------------------------------------------
 
 Page attributes. These flags are used to filter various unnecessary for
diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
index d3a93eec3945f..dec7816303c6a 100644
--- a/Documentation/filesystems/vfs.rst
+++ b/Documentation/filesystems/vfs.rst
@@ -649,8 +649,8 @@ Writeback.
 
 The first can be used independently to the others.  The VM can try to
 release clean pages in order to reuse them.  To do this it can call
-->release_folio on clean folios with the private
-flag set.  Clean pages without PagePrivate and with no external references
+->release_folio on clean folios with folio->private set. Clean pages
+without folio->private set and with no external references
 will be released without notice being given to the address_space.
 
 To achieve this functionality, pages need to be placed on an LRU with
@@ -674,7 +674,7 @@ filemap_fdatawait_range, to wait for all writeback to complete.
 
 An address_space handler may attach extra information to a page,
 typically using the 'private' field in the 'struct page'.  If such
-information is attached, the PG_Private flag should be set.  This will
+information is attached, non-NULL 'private' field will
 cause various VM routines to make extra calls into the address_space
 handler to deal with that data.
 
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 9b585e68127a2..eb2961ed61018 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -44,10 +44,6 @@
  * Consequently, PG_reserved for a page mapped into user space can indicate
  * the zero page, the vDSO, MMIO pages or device memory.
  *
- * The PG_private bitflag is set on pagecache pages if they contain filesystem
- * specific data (which is normally at page->private). It can be used by
- * private allocations for its own usage.
- *
  * During initiation of disk I/O, PG_locked is set. This bit is set before I/O
  * and cleared when writeback _starts_ or when read _completes_. PG_writeback
  * is set before writeback starts and cleared when it finishes.
@@ -105,7 +101,7 @@ enum pageflags {
 	PG_owner_2,		/* Owner use. If pagecache, fs may use */
 	PG_arch_1,
 	PG_reserved,
-	PG_private,		/* If pagecache, has fs-private data */
+	__PG_folio,		/* Do not use: reserved for folio identification */
 	PG_private_2,		/* If pagecache, has fs aux data */
 	PG_reclaim,		/* To be reclaimed asap */
 	PG_swapbacked,		/* Page is backed by RAM/swap */
@@ -576,7 +572,7 @@ 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
  */
 
 static __always_inline bool folio_test_private(const struct folio *folio)
@@ -584,17 +580,6 @@ static __always_inline bool folio_test_private(const struct folio *folio)
 	return folio->private;
 }
 
-static __always_inline int PagePrivate(const struct page *page)
-{
-	return !!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 */
diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
index 935893e5ea53b..caf090cd6f85e 100644
--- a/include/trace/events/mmflags.h
+++ b/include/trace/events/mmflags.h
@@ -144,7 +144,7 @@ TRACE_DEFINE_ENUM(___GFP_LAST_BIT);
 	DEF_PAGEFLAG_NAME(owner_2),					\
 	DEF_PAGEFLAG_NAME(arch_1),					\
 	DEF_PAGEFLAG_NAME(reserved),					\
-	DEF_PAGEFLAG_NAME(private),					\
+	{ 1UL << __PG_folio, "folio" },					\
 	DEF_PAGEFLAG_NAME(private_2),					\
 	DEF_PAGEFLAG_NAME(writeback),					\
 	DEF_PAGEFLAG_NAME(head),					\
diff --git a/kernel/vmcore_info.c b/kernel/vmcore_info.c
index 8614430ca212a..5a417f8a922ab 100644
--- a/kernel/vmcore_info.c
+++ b/kernel/vmcore_info.c
@@ -216,7 +216,6 @@ static int __init crash_save_vmcoreinfo_init(void)
 	VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);
 	VMCOREINFO_NUMBER(NR_FREE_PAGES);
 	VMCOREINFO_NUMBER(PG_lru);
-	VMCOREINFO_NUMBER(PG_private);
 	VMCOREINFO_NUMBER(PG_swapcache);
 	VMCOREINFO_NUMBER(PG_swapbacked);
 #define PAGE_SLAB_MAPCOUNT_VALUE	(PGTY_slab << 24)

-- 
2.53.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 09/14] mm/page-flags: check page/folio->private instead of PG_private
  2026-08-31 19:25 ` [PATCH v2 09/14] mm/page-flags: check page/folio->private instead of PG_private Zi Yan
@ 2026-09-01  2:11   ` Zi Yan
  0 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-09-01  2:11 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Steven Rostedt, Masami Hiramatsu,
	Jan Kara, Mathieu Desnoyers, Matthew Brost, Joshua Hahn,
	Rakie Kim, Byungchul Park, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	linux-fsdevel, linux-trace-kernel

On Mon Aug 31, 2026 at 3:25 PM EDT, Zi Yan wrote:
> 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.
>
> folio_expected_ref_count() can be called without folio lock, so annotate
> folio_test_private() with data_race() to avoid triggering race condition
> checks. While at it, annotate folio->mapping too.
>
> folio_set/clear_private() and Set/ClearPagePrivate() become no-ops.
> PG_private is no longer checked at page free time.
>
> Remove KPF_PRIVATE since PG_private is no longer used.
>
<snip>

> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index dd09c438fa23e..786f8a47cea6d 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -3022,9 +3022,9 @@ static inline bool folio_maybe_mapped_shared(struct folio *folio)
>   * @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),
> @@ -3062,10 +3062,18 @@ static inline int folio_expected_ref_count(const struct folio *folio)
>  	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.
> +		 * Use data_race() since folio might not be locked.
> +		 */
> +		ref_count += data_race(folio_test_private(folio)) &&
> +			     !folio_test_hugetlb(folio) &&
> +			     !folio_test_swapcache(folio);

Sashiko said [Severity: High]:

Could this lockless evaluation of folio->private and PG_swapcache lead to a
TOCTOU race for shmem folios during swap cache removal?

During __delete_from_swap_cache, folio->swap.val (which aliases
folio->private) is cleared before PG_swapcache. Without memory barriers, a
lockless reader like memfd_tag_pins calling folio_expected_ref_count could
observe the stale non-zero folio->private and the newly cleared PG_swapcache.

This would evaluate the condition above as true, falsely inflating the
expected refcount by 1. If the folio has exactly one extra GUP pin, the
inflated expected refcount would match the actual refcount, bypassing the
F_SEAL_WRITE protections.

Answer:

Yes, it is a problem, since folio->swap.val and PG_swapcache cannot be
read as a whole, when __swap_cache_do_del_folio() (was
__delete_from_swap_cache()) clears folio->swap.val first then
PG_swapcache.

Fortunately, PG_swapbacked is stable during the process. So the code can
exclude swapcache folios by checking PG_swapbacked instead.

In the next patch, folio_test_fs_private() will be changed to replace the
new check: folio_test_private() && !folio_test_hugetlb(folio) &&
!folio_test_swapbacked().

<snip>

> diff --git a/include/trace/events/pagemap.h b/include/trace/events/pagemap.h
> index 36c3a90f0acca..fb9abec40ec79 100644
> --- a/include/trace/events/pagemap.h
> +++ b/include/trace/events/pagemap.h
> @@ -22,7 +22,9 @@
>  	(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_test_private(folio) && \
> +	 !folio_test_swapcache(folio) && \
> +	 !folio_test_hugetlb(folio)	? PAGEMAP_BUFFERS    : 0) \

Sashiko said:
hould this lockless read of folio->private be annotated with data_race() or
READ_ONCE()?

Since tracepoints like TRACE_EVENT(mm_lru_insertion) are often executed
without the folio lock, concurrent modifications to folio->private could
trigger KCSAN data race warnings here.

Answer:

Yes, will annotate with data_race() here.

>  	)
>  
>  TRACE_EVENT(mm_lru_insertion,
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index ced400f72d43a..546b37ccce37f 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -4810,7 +4810,9 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
>  		 * 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_test_private(folio) &&
> +		      !folio_test_swapcache(folio) &&
> +		      !folio_test_hugetlb(folio)) &&
>  		    folio_expected_ref_count(folio) != folio_ref_count(folio))
>  			goto next;

This is another lockless check and data_race() annotation is needed.


>  
> diff --git a/mm/migrate.c b/mm/migrate.c
> index 15b45832bcfa7..f14e7bfee14bd 100644
> --- a/mm/migrate.c
> +++ b/mm/migrate.c
> @@ -1327,7 +1327,8 @@ static int migrate_folio_unmap(new_folio_t get_new_folio,
>  	 * free the metadata, so the page can be freed.
>  	 */
>  	if (!src->mapping) {
> -		if (folio_test_private(src)) {
> +		if (folio_test_private(src) && !folio_test_swapcache(src) &&
> +		    !folio_test_hugetlb(src)) {
>  			try_to_free_buffers(src);
>  			goto out;
>  		}

Sashiko said [Severity: High]:
This is a pre-existing issue, but does this generic migration code blindly
assume all private data on an orphaned folio corresponds to buffer heads?

If a folio is orphaned after truncation (src->mapping is NULL) but retains
private data because an earlier release failed, try_to_free_buffers is
unconditionally called. For filesystems like iomap, folio->private contains
custom structures (like iomap_folio_state), not a linked list of buffer
heads. Calling try_to_free_buffers here could lead to type confusion and a
kernel panic when accessing what it expects to be bh->b_this_page.


Answer:

Not an issue. With the help of gpt-5.6-sol, this issue only affects
buffer heads. Folios using iomap always clears folio->private before
folio->mapping is cleared.

> diff --git a/mm/page-writeback.c b/mm/page-writeback.c
> index eeab25d6ce364..4022d6c381896 100644
> --- a/mm/page-writeback.c
> +++ b/mm/page-writeback.c
> @@ -2705,7 +2705,10 @@ bool filemap_dirty_folio(struct address_space *mapping, struct folio *folio)
>  	if (folio_test_set_dirty(folio))
>  		return false;
>  
> -	__folio_mark_dirty(folio, mapping, !folio_test_private(folio));
> +	__folio_mark_dirty(folio, mapping,
> +			   !(folio_test_private(folio) &&
> +			     !folio_test_swapcache(folio) &&
> +			     !folio_test_hugetlb(folio)));
>  

Another place needs data_race() annotation since filemap_dirty_folio()
can be called locklessly (e.g., zap_pte_range()).


-- 
Best Regards,
Yan, Zi



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 14/14] mm/page-flags: remove PG_private
  2026-08-31 19:25 ` [PATCH v2 14/14] mm/page-flags: remove PG_private Zi Yan
@ 2026-09-01  2:17   ` Zi Yan
  2026-09-01 15:55   ` Steven Rostedt
  2026-09-02 17:09   ` Usama Arif
  2 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-09-01  2:17 UTC (permalink / raw)
  To: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song
  Cc: linux-mm, linux-kernel, Zi Yan, Baoquan He, Pasha Tatashin,
	Pratyush Yadav, Jonathan Corbet, Jan Kara, Steven Rostedt,
	Masami Hiramatsu, Dave Young, Shuah Khan, Mathieu Desnoyers,
	kexec, linux-doc, linux-fsdevel, linux-trace-kernel

On Mon Aug 31, 2026 at 3:25 PM EDT, Zi Yan wrote:
> folio->private != NULL indicates a folio carries private data, replacing
> PG_private. All PG_private users are converted. Remove PG_private and
> reserve the space as __PG_folio for future use.
>
> Also update files in Documentation. hugetlbfs_reserv.rst is outdated and
> left unchanged. It should be rewritten.
>
<snip>

>  
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 9b585e68127a2..eb2961ed61018 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -44,10 +44,6 @@
>   * Consequently, PG_reserved for a page mapped into user space can indicate
>   * the zero page, the vDSO, MMIO pages or device memory.
>   *
> - * The PG_private bitflag is set on pagecache pages if they contain filesystem
> - * specific data (which is normally at page->private). It can be used by
> - * private allocations for its own usage.
> - *
>   * During initiation of disk I/O, PG_locked is set. This bit is set before I/O
>   * and cleared when writeback _starts_ or when read _completes_. PG_writeback
>   * is set before writeback starts and cleared when it finishes.
> @@ -105,7 +101,7 @@ enum pageflags {
>  	PG_owner_2,		/* Owner use. If pagecache, fs may use */
>  	PG_arch_1,
>  	PG_reserved,
> -	PG_private,		/* If pagecache, has fs-private data */
> +	__PG_folio,		/* Do not use: reserved for folio identification */

Sashiko asked how to detect leaked filesystem private data during page
free time after PG_private is removed.

Answer copied from RFC:

After the conversion, folio/page should have an elevated refcount whenever
->private is set. That would help detect leaked private data. I tried to
enforce ->private needs to be NULL at page free time[1], but that might
cause trouble for certain use cases.

[1] https://lore.kernel.org/all/20260223032641.1859381-1-ziy@nvidia.com/


-- 
Best Regards,
Yan, Zi



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 14/14] mm/page-flags: remove PG_private
  2026-08-31 19:25 ` [PATCH v2 14/14] mm/page-flags: remove PG_private Zi Yan
  2026-09-01  2:17   ` Zi Yan
@ 2026-09-01 15:55   ` Steven Rostedt
  2026-09-01 16:01     ` Zi Yan
  2026-09-02 17:09   ` Usama Arif
  2 siblings, 1 reply; 23+ messages in thread
From: Steven Rostedt @ 2026-09-01 15:55 UTC (permalink / raw)
  To: Zi Yan
  Cc: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song, linux-mm,
	linux-kernel, Baoquan He, Pasha Tatashin, Pratyush Yadav,
	Jonathan Corbet, Jan Kara, Masami Hiramatsu, Dave Young,
	Shuah Khan, Mathieu Desnoyers, kexec, linux-doc, linux-fsdevel,
	linux-trace-kernel

On Mon, 31 Aug 2026 15:25:37 -0400
Zi Yan <ziy@nvidia.com> wrote:

> diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
> index 935893e5ea53b..caf090cd6f85e 100644
> --- a/include/trace/events/mmflags.h
> +++ b/include/trace/events/mmflags.h
> @@ -144,7 +144,7 @@ TRACE_DEFINE_ENUM(___GFP_LAST_BIT);
>  	DEF_PAGEFLAG_NAME(owner_2),					\
>  	DEF_PAGEFLAG_NAME(arch_1),					\
>  	DEF_PAGEFLAG_NAME(reserved),					\
> -	DEF_PAGEFLAG_NAME(private),					\
> +	{ 1UL << __PG_folio, "folio" },					\
>  	DEF_PAGEFLAG_NAME(private_2),					\
>  	DEF_PAGEFLAG_NAME(writeback),					\
>  	DEF_PAGEFLAG_NAME(head),					\

Hmm, just for consistency sake, can we create a:

 #define __DEF_PAGEFLAG_NAME(_name) { 1UL <<  __PG_##_name, __stringify(_name) }

Which is similar to:

 #define DEF_PAGEFLAG_NAME(_name) { 1UL <<  PG_##_name, __stringify(_name) }

But adds the "__" to the name. Then the above would look like:

	DEF_PAGEFLAG_NAME(reserved),					\
	__DEF_PAGEFLAG_NAME(folio),					\
	DEF_PAGEFLAG_NAME(private_2),					\
	DEF_PAGEFLAG_NAME(writeback),					\

Where the __DEF_PAGEFLAG_NAME() with the "__" still stands out, but the
code looks better than open coding it in the middle and making one wonder
why it was open coded. (It took me a bit to noticed the "__" difference.)

-- Steve


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 14/14] mm/page-flags: remove PG_private
  2026-09-01 15:55   ` Steven Rostedt
@ 2026-09-01 16:01     ` Zi Yan
  2026-09-01 17:50       ` Steven Rostedt
  0 siblings, 1 reply; 23+ messages in thread
From: Zi Yan @ 2026-09-01 16:01 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song, linux-mm,
	linux-kernel, Baoquan He, Pasha Tatashin, Pratyush Yadav,
	Jonathan Corbet, Jan Kara, Masami Hiramatsu, Dave Young,
	Shuah Khan, Mathieu Desnoyers, kexec, linux-doc, linux-fsdevel,
	linux-trace-kernel

On 1 Sep 2026, at 11:55, Steven Rostedt wrote:

> On Mon, 31 Aug 2026 15:25:37 -0400
> Zi Yan <ziy@nvidia.com> wrote:
>
>> diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
>> index 935893e5ea53b..caf090cd6f85e 100644
>> --- a/include/trace/events/mmflags.h
>> +++ b/include/trace/events/mmflags.h
>> @@ -144,7 +144,7 @@ TRACE_DEFINE_ENUM(___GFP_LAST_BIT);
>>  	DEF_PAGEFLAG_NAME(owner_2),					\
>>  	DEF_PAGEFLAG_NAME(arch_1),					\
>>  	DEF_PAGEFLAG_NAME(reserved),					\
>> -	DEF_PAGEFLAG_NAME(private),					\
>> +	{ 1UL << __PG_folio, "folio" },					\
>>  	DEF_PAGEFLAG_NAME(private_2),					\
>>  	DEF_PAGEFLAG_NAME(writeback),					\
>>  	DEF_PAGEFLAG_NAME(head),					\
>
> Hmm, just for consistency sake, can we create a:
>
>  #define __DEF_PAGEFLAG_NAME(_name) { 1UL <<  __PG_##_name, __stringify(_name) }
>
> Which is similar to:
>
>  #define DEF_PAGEFLAG_NAME(_name) { 1UL <<  PG_##_name, __stringify(_name) }
>
> But adds the "__" to the name. Then the above would look like:
>
> 	DEF_PAGEFLAG_NAME(reserved),					\
> 	__DEF_PAGEFLAG_NAME(folio),					\
> 	DEF_PAGEFLAG_NAME(private_2),					\
> 	DEF_PAGEFLAG_NAME(writeback),					\
>
> Where the __DEF_PAGEFLAG_NAME() with the "__" still stands out, but the
> code looks better than open coding it in the middle and making one wonder
> why it was open coded. (It took me a bit to noticed the "__" difference.)
>

No problem.

BTW, the plan is to add PG_folio after this series is picked up by Andrew/David.
So the new __DEF_PAGEFLAG_NAME() will have no user then and can be deleted.
It should be fine, right?

Best Regards,
Yan, Zi


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 14/14] mm/page-flags: remove PG_private
  2026-09-01 16:01     ` Zi Yan
@ 2026-09-01 17:50       ` Steven Rostedt
  0 siblings, 0 replies; 23+ messages in thread
From: Steven Rostedt @ 2026-09-01 17:50 UTC (permalink / raw)
  To: Zi Yan
  Cc: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song, linux-mm,
	linux-kernel, Baoquan He, Pasha Tatashin, Pratyush Yadav,
	Jonathan Corbet, Jan Kara, Masami Hiramatsu, Dave Young,
	Shuah Khan, Mathieu Desnoyers, kexec, linux-doc, linux-fsdevel,
	linux-trace-kernel

On Tue, 01 Sep 2026 12:01:24 -0400
Zi Yan <ziy@nvidia.com> wrote:

> No problem.
> 
> BTW, the plan is to add PG_folio after this series is picked up by Andrew/David.
> So the new __DEF_PAGEFLAG_NAME() will have no user then and can be deleted.
> It should be fine, right?

Yeah, then we just remove that macro and change the one user of
__DEF_PAGEFLAG_NAME() to DEF_PAGEFLAG_NAME().

It will make that patch even easier ;-)

-- Steve


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 14/14] mm/page-flags: remove PG_private
  2026-08-31 19:25 ` [PATCH v2 14/14] mm/page-flags: remove PG_private Zi Yan
  2026-09-01  2:17   ` Zi Yan
  2026-09-01 15:55   ` Steven Rostedt
@ 2026-09-02 17:09   ` Usama Arif
  2026-09-02 17:57     ` Zi Yan
  2 siblings, 1 reply; 23+ messages in thread
From: Usama Arif @ 2026-09-02 17:09 UTC (permalink / raw)
  To: Zi Yan
  Cc: Usama Arif, David Hildenbrand, Matthew Wilcox (Oracle),
	Andrew Morton, Muchun Song, Lorenzo Stoakes, Liam R. Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Baolin Wang, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
	Lance Yang, Gregory Price, Ying Huang, Alistair Popple,
	Johannes Weiner, Qi Zheng, Shakeel Butt, Kairui Song, bhe, vgoyal,
	dyoung, linux-mm, linux-kernel, Baoquan He, Pasha Tatashin,
	Pratyush Yadav, Jonathan Corbet, Jan Kara, Steven Rostedt,
	Masami Hiramatsu, Dave Young, Shuah Khan, Mathieu Desnoyers,
	kexec, linux-doc, linux-fsdevel, linux-trace-kernel

On Mon, 31 Aug 2026 15:25:37 -0400 Zi Yan <ziy@nvidia.com> wrote:

> folio->private != NULL indicates a folio carries private data, replacing
> PG_private. All PG_private users are converted. Remove PG_private and
> reserve the space as __PG_folio for future use.
> 
> Also update files in Documentation. hugetlbfs_reserv.rst is outdated and
> left unchanged. It should be rewritten.
> 
> Assisted-by: Claude:claude-opus-4-8
> Assisted-by: Codex:gpt-5
> Signed-off-by: Zi Yan <ziy@nvidia.com>
> To: Andrew Morton <akpm@linux-foundation.org>
> To: Baoquan He <baoquan.he@linux.dev>
> To: Mike Rapoport <rppt@kernel.org>
> To: Pasha Tatashin <pasha.tatashin@soleen.com>
> To: Pratyush Yadav <pratyush@kernel.org>
> To: Jonathan Corbet <corbet@lwn.net>
> To: "Matthew Wilcox (Oracle)" <willy@infradead.org>
> To: Jan Kara <jack@suse.cz>
> To: David Hildenbrand <david@kernel.org>
> To: Steven Rostedt <rostedt@goodmis.org>
> To: Masami Hiramatsu <mhiramat@kernel.org>
> Cc: Dave Young <ruirui.yang@linux.dev>
> Cc: Shuah Khan <skhan@linuxfoundation.org>
> Cc: Lorenzo Stoakes <ljs@kernel.org>
> Cc: "Liam R. Howlett" <liam@infradead.org>
> Cc: Vlastimil Babka <vbabka@kernel.org>
> Cc: Suren Baghdasaryan <surenb@google.com>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> Cc: kexec@lists.infradead.org
> Cc: linux-doc@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-fsdevel@vger.kernel.org
> Cc: linux-mm@kvack.org
> Cc: linux-trace-kernel@vger.kernel.org
> ---
>  Documentation/admin-guide/kdump/vmcoreinfo.rst |  2 +-
>  Documentation/filesystems/vfs.rst              |  6 +++---
>  include/linux/page-flags.h                     | 19 ++-----------------
>  include/trace/events/mmflags.h                 |  2 +-
>  kernel/vmcore_info.c                           |  1 -
>  5 files changed, 7 insertions(+), 23 deletions(-)
> 
> diff --git a/Documentation/admin-guide/kdump/vmcoreinfo.rst b/Documentation/admin-guide/kdump/vmcoreinfo.rst
> index 7663c610fe901..5f1df6d080508 100644
> --- a/Documentation/admin-guide/kdump/vmcoreinfo.rst
> +++ b/Documentation/admin-guide/kdump/vmcoreinfo.rst
> @@ -325,7 +325,7 @@ NR_FREE_PAGES
>  On linux-2.6.21 or later, the number of free pages is in
>  vm_stat[NR_FREE_PAGES]. Used to get the number of free pages.
>  
> -PG_lru|PG_private|PG_swapcache|PG_swapbacked|PG_hwpoison|PG_head_mask
> +PG_lru|PG_swapcache|PG_swapbacked|PG_hwpoison|PG_head_mask
>  --------------------------------------------------------------------------
>  
>  Page attributes. These flags are used to filter various unnecessary for
> diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
> index d3a93eec3945f..dec7816303c6a 100644
> --- a/Documentation/filesystems/vfs.rst
> +++ b/Documentation/filesystems/vfs.rst
> @@ -649,8 +649,8 @@ Writeback.
>  
>  The first can be used independently to the others.  The VM can try to
>  release clean pages in order to reuse them.  To do this it can call
> -->release_folio on clean folios with the private
> -flag set.  Clean pages without PagePrivate and with no external references
> +->release_folio on clean folios with folio->private set. Clean pages
> +without folio->private set and with no external references
>  will be released without notice being given to the address_space.
>  
>  To achieve this functionality, pages need to be placed on an LRU with
> @@ -674,7 +674,7 @@ filemap_fdatawait_range, to wait for all writeback to complete.
>  
>  An address_space handler may attach extra information to a page,
>  typically using the 'private' field in the 'struct page'.  If such
> -information is attached, the PG_Private flag should be set.  This will
> +information is attached, non-NULL 'private' field will
>  cause various VM routines to make extra calls into the address_space
>  handler to deal with that data.
>  
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 9b585e68127a2..eb2961ed61018 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -44,10 +44,6 @@
>   * Consequently, PG_reserved for a page mapped into user space can indicate
>   * the zero page, the vDSO, MMIO pages or device memory.
>   *
> - * The PG_private bitflag is set on pagecache pages if they contain filesystem
> - * specific data (which is normally at page->private). It can be used by
> - * private allocations for its own usage.
> - *
>   * During initiation of disk I/O, PG_locked is set. This bit is set before I/O
>   * and cleared when writeback _starts_ or when read _completes_. PG_writeback
>   * is set before writeback starts and cleared when it finishes.
> @@ -105,7 +101,7 @@ enum pageflags {
>  	PG_owner_2,		/* Owner use. If pagecache, fs may use */
>  	PG_arch_1,
>  	PG_reserved,
> -	PG_private,		/* If pagecache, has fs-private data */
> +	__PG_folio,		/* Do not use: reserved for folio identification */
>  	PG_private_2,		/* If pagecache, has fs aux data */
>  	PG_reclaim,		/* To be reclaimed asap */
>  	PG_swapbacked,		/* Page is backed by RAM/swap */
> @@ -576,7 +572,7 @@ 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
>   */
>  
>  static __always_inline bool folio_test_private(const struct folio *folio)
> @@ -584,17 +580,6 @@ static __always_inline bool folio_test_private(const struct folio *folio)
>  	return folio->private;
>  }
>  
> -static __always_inline int PagePrivate(const struct page *page)
> -{
> -	return !!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 */
> diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
> index 935893e5ea53b..caf090cd6f85e 100644
> --- a/include/trace/events/mmflags.h
> +++ b/include/trace/events/mmflags.h
> @@ -144,7 +144,7 @@ TRACE_DEFINE_ENUM(___GFP_LAST_BIT);
>  	DEF_PAGEFLAG_NAME(owner_2),					\
>  	DEF_PAGEFLAG_NAME(arch_1),					\
>  	DEF_PAGEFLAG_NAME(reserved),					\
> -	DEF_PAGEFLAG_NAME(private),					\
> +	{ 1UL << __PG_folio, "folio" },					\
>  	DEF_PAGEFLAG_NAME(private_2),					\
>  	DEF_PAGEFLAG_NAME(writeback),					\
>  	DEF_PAGEFLAG_NAME(head),					\
> diff --git a/kernel/vmcore_info.c b/kernel/vmcore_info.c
> index 8614430ca212a..5a417f8a922ab 100644
> --- a/kernel/vmcore_info.c
> +++ b/kernel/vmcore_info.c
> @@ -216,7 +216,6 @@ static int __init crash_save_vmcoreinfo_init(void)
>  	VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);
>  	VMCOREINFO_NUMBER(NR_FREE_PAGES);
>  	VMCOREINFO_NUMBER(PG_lru);
> -	VMCOREINFO_NUMBER(PG_private);
>  	VMCOREINFO_NUMBER(PG_swapcache);
>  	VMCOREINFO_NUMBER(PG_swapbacked);
>  #define PAGE_SLAB_MAPCOUNT_VALUE	(PGTY_slab << 24)

+ kdump maintainers and reviewers.

I believe makedumpfile reads VMCOREINFO. Removing it here, might cause issues
for older makedumpfile versions at crashdump?

Hopefully kdump folks will be able to comment better.

> 
> -- 
> 2.53.0
> 
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 14/14] mm/page-flags: remove PG_private
  2026-09-02 17:09   ` Usama Arif
@ 2026-09-02 17:57     ` Zi Yan
  0 siblings, 0 replies; 23+ messages in thread
From: Zi Yan @ 2026-09-02 17:57 UTC (permalink / raw)
  To: Usama Arif
  Cc: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Gregory Price, Ying Huang, Alistair Popple, Johannes Weiner,
	Qi Zheng, Shakeel Butt, Kairui Song, bhe, vgoyal, dyoung,
	linux-mm, linux-kernel, Baoquan He, Pasha Tatashin,
	Pratyush Yadav, Jonathan Corbet, Jan Kara, Steven Rostedt,
	Masami Hiramatsu, Dave Young, Shuah Khan, Mathieu Desnoyers,
	kexec, linux-doc, linux-fsdevel, linux-trace-kernel

On 2 Sep 2026, at 13:09, Usama Arif wrote:

> On Mon, 31 Aug 2026 15:25:37 -0400 Zi Yan <ziy@nvidia.com> wrote:
>
>> folio->private != NULL indicates a folio carries private data, replacing
>> PG_private. All PG_private users are converted. Remove PG_private and
>> reserve the space as __PG_folio for future use.
>>
>> Also update files in Documentation. hugetlbfs_reserv.rst is outdated and
>> left unchanged. It should be rewritten.
>>
>> Assisted-by: Claude:claude-opus-4-8
>> Assisted-by: Codex:gpt-5
>> Signed-off-by: Zi Yan <ziy@nvidia.com>
>> To: Andrew Morton <akpm@linux-foundation.org>
>> To: Baoquan He <baoquan.he@linux.dev>
>> To: Mike Rapoport <rppt@kernel.org>
>> To: Pasha Tatashin <pasha.tatashin@soleen.com>
>> To: Pratyush Yadav <pratyush@kernel.org>
>> To: Jonathan Corbet <corbet@lwn.net>
>> To: "Matthew Wilcox (Oracle)" <willy@infradead.org>
>> To: Jan Kara <jack@suse.cz>
>> To: David Hildenbrand <david@kernel.org>
>> To: Steven Rostedt <rostedt@goodmis.org>
>> To: Masami Hiramatsu <mhiramat@kernel.org>
>> Cc: Dave Young <ruirui.yang@linux.dev>
>> Cc: Shuah Khan <skhan@linuxfoundation.org>
>> Cc: Lorenzo Stoakes <ljs@kernel.org>
>> Cc: "Liam R. Howlett" <liam@infradead.org>
>> Cc: Vlastimil Babka <vbabka@kernel.org>
>> Cc: Suren Baghdasaryan <surenb@google.com>
>> Cc: Michal Hocko <mhocko@suse.com>
>> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
>> Cc: kexec@lists.infradead.org
>> Cc: linux-doc@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: linux-fsdevel@vger.kernel.org
>> Cc: linux-mm@kvack.org
>> Cc: linux-trace-kernel@vger.kernel.org
>> ---
>>  Documentation/admin-guide/kdump/vmcoreinfo.rst |  2 +-
>>  Documentation/filesystems/vfs.rst              |  6 +++---
>>  include/linux/page-flags.h                     | 19 ++-----------------
>>  include/trace/events/mmflags.h                 |  2 +-
>>  kernel/vmcore_info.c                           |  1 -
>>  5 files changed, 7 insertions(+), 23 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/kdump/vmcoreinfo.rst b/Documentation/admin-guide/kdump/vmcoreinfo.rst
>> index 7663c610fe901..5f1df6d080508 100644
>> --- a/Documentation/admin-guide/kdump/vmcoreinfo.rst
>> +++ b/Documentation/admin-guide/kdump/vmcoreinfo.rst
>> @@ -325,7 +325,7 @@ NR_FREE_PAGES
>>  On linux-2.6.21 or later, the number of free pages is in
>>  vm_stat[NR_FREE_PAGES]. Used to get the number of free pages.
>>
>> -PG_lru|PG_private|PG_swapcache|PG_swapbacked|PG_hwpoison|PG_head_mask
>> +PG_lru|PG_swapcache|PG_swapbacked|PG_hwpoison|PG_head_mask
>>  --------------------------------------------------------------------------
>>
>>  Page attributes. These flags are used to filter various unnecessary for
>> diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
>> index d3a93eec3945f..dec7816303c6a 100644
>> --- a/Documentation/filesystems/vfs.rst
>> +++ b/Documentation/filesystems/vfs.rst
>> @@ -649,8 +649,8 @@ Writeback.
>>
>>  The first can be used independently to the others.  The VM can try to
>>  release clean pages in order to reuse them.  To do this it can call
>> -->release_folio on clean folios with the private
>> -flag set.  Clean pages without PagePrivate and with no external references
>> +->release_folio on clean folios with folio->private set. Clean pages
>> +without folio->private set and with no external references
>>  will be released without notice being given to the address_space.
>>
>>  To achieve this functionality, pages need to be placed on an LRU with
>> @@ -674,7 +674,7 @@ filemap_fdatawait_range, to wait for all writeback to complete.
>>
>>  An address_space handler may attach extra information to a page,
>>  typically using the 'private' field in the 'struct page'.  If such
>> -information is attached, the PG_Private flag should be set.  This will
>> +information is attached, non-NULL 'private' field will
>>  cause various VM routines to make extra calls into the address_space
>>  handler to deal with that data.
>>
>> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
>> index 9b585e68127a2..eb2961ed61018 100644
>> --- a/include/linux/page-flags.h
>> +++ b/include/linux/page-flags.h
>> @@ -44,10 +44,6 @@
>>   * Consequently, PG_reserved for a page mapped into user space can indicate
>>   * the zero page, the vDSO, MMIO pages or device memory.
>>   *
>> - * The PG_private bitflag is set on pagecache pages if they contain filesystem
>> - * specific data (which is normally at page->private). It can be used by
>> - * private allocations for its own usage.
>> - *
>>   * During initiation of disk I/O, PG_locked is set. This bit is set before I/O
>>   * and cleared when writeback _starts_ or when read _completes_. PG_writeback
>>   * is set before writeback starts and cleared when it finishes.
>> @@ -105,7 +101,7 @@ enum pageflags {
>>  	PG_owner_2,		/* Owner use. If pagecache, fs may use */
>>  	PG_arch_1,
>>  	PG_reserved,
>> -	PG_private,		/* If pagecache, has fs-private data */
>> +	__PG_folio,		/* Do not use: reserved for folio identification */
>>  	PG_private_2,		/* If pagecache, has fs aux data */
>>  	PG_reclaim,		/* To be reclaimed asap */
>>  	PG_swapbacked,		/* Page is backed by RAM/swap */
>> @@ -576,7 +572,7 @@ 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
>>   */
>>
>>  static __always_inline bool folio_test_private(const struct folio *folio)
>> @@ -584,17 +580,6 @@ static __always_inline bool folio_test_private(const struct folio *folio)
>>  	return folio->private;
>>  }
>>
>> -static __always_inline int PagePrivate(const struct page *page)
>> -{
>> -	return !!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 */
>> diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
>> index 935893e5ea53b..caf090cd6f85e 100644
>> --- a/include/trace/events/mmflags.h
>> +++ b/include/trace/events/mmflags.h
>> @@ -144,7 +144,7 @@ TRACE_DEFINE_ENUM(___GFP_LAST_BIT);
>>  	DEF_PAGEFLAG_NAME(owner_2),					\
>>  	DEF_PAGEFLAG_NAME(arch_1),					\
>>  	DEF_PAGEFLAG_NAME(reserved),					\
>> -	DEF_PAGEFLAG_NAME(private),					\
>> +	{ 1UL << __PG_folio, "folio" },					\
>>  	DEF_PAGEFLAG_NAME(private_2),					\
>>  	DEF_PAGEFLAG_NAME(writeback),					\
>>  	DEF_PAGEFLAG_NAME(head),					\
>> diff --git a/kernel/vmcore_info.c b/kernel/vmcore_info.c
>> index 8614430ca212a..5a417f8a922ab 100644
>> --- a/kernel/vmcore_info.c
>> +++ b/kernel/vmcore_info.c
>> @@ -216,7 +216,6 @@ static int __init crash_save_vmcoreinfo_init(void)
>>  	VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);
>>  	VMCOREINFO_NUMBER(NR_FREE_PAGES);
>>  	VMCOREINFO_NUMBER(PG_lru);
>> -	VMCOREINFO_NUMBER(PG_private);
>>  	VMCOREINFO_NUMBER(PG_swapcache);
>>  	VMCOREINFO_NUMBER(PG_swapbacked);
>>  #define PAGE_SLAB_MAPCOUNT_VALUE	(PGTY_slab << 24)
>
> + kdump maintainers and reviewers.

Thanks.

>
> I believe makedumpfile reads VMCOREINFO. Removing it here, might cause issues
> for older makedumpfile versions at crashdump?

The expectation is that kdump userspace tools will adapt to this change.
Later, PG_folio will be added to identify folios and has the same value
of PG_private, so preserving PG_private will not work then.
>
> Hopefully kdump folks will be able to comment better.



Best Regards,
Yan, Zi


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 05/14] mm/hugetlb: use direct assignment instead of folio_change_private()
  2026-08-31 19:25 ` [PATCH v2 05/14] mm/hugetlb: use direct assignment instead of folio_change_private() Zi Yan
@ 2026-09-03  0:05   ` Gregory Price
  0 siblings, 0 replies; 23+ messages in thread
From: Gregory Price @ 2026-09-03  0:05 UTC (permalink / raw)
  To: Zi Yan
  Cc: David Hildenbrand, Matthew Wilcox (Oracle), Andrew Morton,
	Muchun Song, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Baolin Wang,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Usama Arif, Ying Huang, Alistair Popple, Johannes Weiner,
	Qi Zheng, Shakeel Butt, Kairui Song, linux-mm, linux-kernel,
	Oscar Salvador

On Mon, Aug 31, 2026 at 03:25:28PM -0400, Zi Yan wrote:
> folio_change_private() should be used along with folio_attach_private() and
> folio_detach_private(), where adding and remove ->private content requires
> folio refcount change. add_hugetlb_folio() simply sets folio->private to
> NULL without refcount manipulation. Change it to direct assignment to avoid
> semantic confusion.
> 
> It prepares for a future commit that remove PG_private.
> 
> No functional change intended.
> 
> Assisted-by: Claude:claude-opus-4-8
> Assisted-by: Codex:gpt-5
> To: Muchun Song <muchun.song@linux.dev>
> To: Oscar Salvador <osalvador@suse.de>
> To: Andrew Morton <akpm@linux-foundation.org>
> Cc: David Hildenbrand <david@kernel.org>
> Cc: linux-mm@kvack.org
> Cc: linux-kernel@vger.kernel.org
> Acked-by: Usama Arif <usama.arif@linux.dev>
> Signed-off-by: Zi Yan <ziy@nvidia.com>

Reviewed-by: Gregory Price (Meta) <gourry@gourry.net>



^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2026-09-03  0:05 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 19:25 [PATCH v2 00/14] Remove PG_private by using page/folio->private checks instead Zi Yan
2026-08-31 19:25 ` [PATCH v2 01/14] mm/zsmalloc: replace PG_private with pointer comparison Zi Yan
2026-08-31 19:25 ` [PATCH v2 02/14] perf/ring_buffer: stop using PG_private as AUX page high-order marker Zi Yan
2026-08-31 19:25 ` [PATCH v2 03/14] xen/grant-table: stop setting PG_private on pages for grant mapping Zi Yan
2026-08-31 19:25 ` [PATCH v2 04/14] fscrypt: stop setting PG_private on bounce page Zi Yan
2026-08-31 19:25 ` [PATCH v2 05/14] mm/hugetlb: use direct assignment instead of folio_change_private() Zi Yan
2026-09-03  0:05   ` Gregory Price
2026-08-31 19:25 ` [PATCH v2 06/14] f2fs: stop using PG_private Zi Yan
2026-08-31 19:25 ` [PATCH v2 07/14] erofs: mm/pagemap: add readahead_folio_last() to avoid folio->private Zi Yan
2026-08-31 19:25 ` [PATCH v2 08/14] erofs: use folio_attach/detach_private() instead of direct assignment Zi Yan
2026-08-31 19:25 ` [PATCH v2 09/14] mm/page-flags: check page/folio->private instead of PG_private Zi Yan
2026-09-01  2:11   ` Zi Yan
2026-08-31 19:25 ` [PATCH v2 10/14] mm/page-flags: introduce folio_test_fs_private() Zi Yan
2026-08-31 19:25 ` [PATCH v2 11/14] treewide: remove folio_set/clear_private() Zi Yan
2026-08-31 19:25 ` [PATCH v2 12/14] treewide: replace PagePrivate() with page_private() Zi Yan
2026-08-31 19:25 ` [PATCH v2 13/14] treewide: adjust comments on PagePrivate and PG_private Zi Yan
2026-08-31 19:25 ` [PATCH v2 14/14] mm/page-flags: remove PG_private Zi Yan
2026-09-01  2:17   ` Zi Yan
2026-09-01 15:55   ` Steven Rostedt
2026-09-01 16:01     ` Zi Yan
2026-09-01 17:50       ` Steven Rostedt
2026-09-02 17:09   ` Usama Arif
2026-09-02 17:57     ` Zi Yan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox