[PATCH v4 00/16] Remove PG_private by using page/folio->private checks instead

Zi Yan posted 16 patches 1 week, 4 days ago
There is a newer version of this series
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                         |  7 +-
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/compress.c                             | 35 +++++----
fs/f2fs/data.c                                 |  2 +-
fs/f2fs/f2fs.h                                 | 99 ++++++++++----------------
fs/f2fs/segment.c                              |  2 +-
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                     | 43 ++++++++---
include/linux/pagemap.h                        | 64 ++++++++++++++---
include/trace/events/mmflags.h                 |  2 +-
include/trace/events/pagemap.h                 |  3 +-
kernel/events/ring_buffer.c                    |  7 +-
kernel/vmcore_info.c                           |  1 -
mm/huge_memory.c                               |  3 +-
mm/hugetlb.c                                   |  7 +-
mm/migrate.c                                   |  3 +-
mm/page-writeback.c                            |  3 +-
mm/vmscan.c                                    |  2 +-
mm/zpdesc.h                                    |  2 +-
mm/zsmalloc.c                                  | 24 ++-----
tools/mm/page-types.c                          |  2 -
36 files changed, 228 insertions(+), 211 deletions(-)
[PATCH v4 00/16] Remove PG_private by using page/folio->private checks instead
Posted by Zi Yan 1 week, 4 days ago
Hi all,

This patchset removes PG_private to make space for upcoming 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.

Patch 6 is picked up separately in f2fs tree, but since mm-new does not
have it yet, it is sent for MM testing.

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_has_attached_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, but not order-0
   folios) can be identified. Then vm_insert_*() can correctly reject all
   folios and rmap code will only see 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 need
   to 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: LLM
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
Changes in v4:
1. dropped set_page_private(0) in balloon_retrieve(), since page->private
   is cleared at that point.
2. simplified the comment in add_hugetlb_folio().
3. additional cleanup for f2fs to remove fio->page uses and convert
   PAGE_PRIVATE_* flags and helper to folio-only.
4. added a comment for __readahead_advance().
5. added core-mm split/migration interaction information on newly added
   folio_attach/detach_private() for erofs.
6. renamed folio_test_fs_private() to folio_has_attached_private() and
   merged the commit introducing folio_test_fs_private() into its prior
   commit.
7. adjusted the patch subject: "treewide: remove folio_set/clear_private()
   *usage*"
8. split "treewide: replace PagePrivate() with page_private()" into three.
9. moved some comments in "treewide: remove PagePrivate() and PG_private
   from comments and docs" to prior patches along with code changes.
10. used PG_folio instead of __PG_folio to avoid additional
    code change in __def_pageflag_names().
- Link to v3: https://patch.msgid.link/20260907-remove-pg_private-v3-0-6ae22f9d9272@nvidia.com

Changes in v3:
1. changed folio_test_fs_private() to check PG_swapbacked instead of
   PG_swapcache for excluding swapcache folios. Because folio->private and
   PG_swapcache are not set as a whole, making folio_test_fs_private() give
   false positive, whereas PG_swapbacked is always set for swapcache
   folios.
2. added __DEF_PAGEFLAG_NAME() to show __PG_folio instead of open code.
3. f2fs change is picked up at
   https://git.kernel.org/jaegeuk/f2fs/c/5ad9409a9533, mm-new currently
   does not have it, so the patch is sent for MM testing purpose.
- Link to v2: https://patch.msgid.link/20260831-remove-pg_private-v2-0-3668159cd9e8@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 (16):
      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
      f2fs: convert the ->private flag helpers to folio-only
      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
      treewide: remove folio_set/clear_private() usage
      ceph: replace PagePrivate() with page_private()
      md/md-bitmap: replace PagePrivate() with page_private()
      buffer: replace page_buffer() with page_private() and delete it
      treewide: remove PagePrivate() and PG_private from comments and docs
      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                         |  7 +-
 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/compress.c                             | 35 +++++----
 fs/f2fs/data.c                                 |  2 +-
 fs/f2fs/f2fs.h                                 | 99 ++++++++++----------------
 fs/f2fs/segment.c                              |  2 +-
 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                     | 43 ++++++++---
 include/linux/pagemap.h                        | 64 ++++++++++++++---
 include/trace/events/mmflags.h                 |  2 +-
 include/trace/events/pagemap.h                 |  3 +-
 kernel/events/ring_buffer.c                    |  7 +-
 kernel/vmcore_info.c                           |  1 -
 mm/huge_memory.c                               |  3 +-
 mm/hugetlb.c                                   |  7 +-
 mm/migrate.c                                   |  3 +-
 mm/page-writeback.c                            |  3 +-
 mm/vmscan.c                                    |  2 +-
 mm/zpdesc.h                                    |  2 +-
 mm/zsmalloc.c                                  | 24 ++-----
 tools/mm/page-types.c                          |  2 -
 36 files changed, 228 insertions(+), 211 deletions(-)
---
base-commit: 3833e2f6aa6bf6af169f78a27843dfa2804be5a6
change-id: 20260728-remove-pg_private-cfe926c7f83c

Best regards,
--  
Yan, Zi

Re: [f2fs-dev] [PATCH v4 00/16] Remove PG_private by using page/folio->private checks instead
Posted by patchwork-bot+f2fs@kernel.org 1 week, 3 days ago
Hello:

This series was applied to jaegeuk/f2fs.git (dev)
by Jaegeuk Kim <jaegeuk@kernel.org>:

On Sun, 13 Sep 2026 22:23:58 -0400 you wrote:
> Hi all,
> 
> This patchset removes PG_private to make space for upcoming 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.
> 
> [...]

Here is the summary with links:
  - [f2fs-dev,v4,06/16] f2fs: stop using PG_private
    https://git.kernel.org/jaegeuk/f2fs/c/60105162524e
  - [f2fs-dev,v4,07/16] f2fs: convert the ->private flag helpers to folio-only
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
Re: [PATCH v4 00/16] Remove PG_private by using page/folio->private checks instead
Posted by Andrew Morton 1 week, 4 days ago
On Sun, 13 Sep 2026 22:23:58 -0400 Zi Yan <ziy@nvidia.com> wrote:

> This patchset removes PG_private to make space for upcoming 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.
> 
> Patch 6 is picked up separately in f2fs tree, but since mm-new does not
> have it yet, it is sent for MM testing.

AI review claims to have found a pre-existing critical level deadlock
in f2fs:

	https://sashiko.dev/#/patchset/20260913-remove-pg_private-v4-0-848550f7574e@nvidia.com

it also had a few things to say about this patchset and, as always,
hugetlb.c.


Thanks, The MM bits appear adequately reviewed and review of the non-MM
bits are, as usual:

  Great to have but I won't permit lack of other-than-MM review to
  block MM improvements.

So I'll queue it all up and shall push it into -next after a few days.

Acks from non-MM maintainers are appreciated.

If a non-MM patch appears in linux-next I'll autodrop the mm.git copy
of that patch.
Re: [PATCH v4 00/16] Remove PG_private by using page/folio->private checks instead
Posted by Zi Yan 1 week, 2 days ago
On 13 Sep 2026, at 23:39, Andrew Morton wrote:

> On Sun, 13 Sep 2026 22:23:58 -0400 Zi Yan <ziy@nvidia.com> wrote:
>
>> This patchset removes PG_private to make space for upcoming 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.
>>
>> Patch 6 is picked up separately in f2fs tree, but since mm-new does not
>> have it yet, it is sent for MM testing.
>
> AI review claims to have found a pre-existing critical level deadlock
> in f2fs:
>
> 	https://sashiko.dev/#/patchset/20260913-remove-pg_private-v4-0-848550f7574e@nvidia.com
>

drop non f2fs people and lists

Hi Chao, Jaegeuk, and Daeho,

I used LLM locally and discovered the deadlock issue in f2fs (sashiko's report
is overwritten. The fix is below, let me know your thoughts. Thanks.

It applies on top of my other f2fs patches.


From f0c1e94d229a97614738d5c317187bf42a3ff2b2 Mon Sep 17 00:00:00 2001
From: Zi Yan <ziy@nvidia.com>
Date: Tue, 15 Sep 2026 13:43:35 -0400
Subject: [PATCH] f2fs: fix potential deadlocks in cancel_cluster_writeback()

When f2fs_write_compressed_pages() fails to submit a compressed page, it
calls cancel_cluster_writeback() to end writeback and lock all pages.

cancel_cluster_writeback() relocks unlocked folios in [0, submitted), while
still holding the locks of the folios in [submitted, cluster_size).
The folio locks are no longer held in order of ascending index, violating
the requirement of folio_lock().

cancel_cluster_writeback() also ends folio writeback after taking its lock
for folios in [0, submitted). A deadlock can happen if one like
truncate_inode_pages_range() takes the folio lock and is waiting for the
completion of folio writeback forever.

Fix both by ending writeback and dropping all folio locks first, then
retaking them in ascending index order.

Fixes: 2174035a7f11 ("f2fs: clear writeback when compression failed")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Zi Yan <ziy@nvidia.com>
To: Jaegeuk Kim <jaegeuk@kernel.org>
To: Chao Yu <chao@kernel.org>
To: Daeho Jeong <daehojeong@google.com>
Cc: linux-f2fs-devel@lists.sourceforge.net
Cc: linux-kernel@vger.kernel.org
---
 fs/f2fs/compress.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 09d9b8d0fdcce..88797dedc96bf 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -1062,18 +1062,28 @@ static void cancel_cluster_writeback(struct compress_ctx *cc,
 			f2fs_io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT);
 	}

-	/* Cancel writeback and stay locked. */
+	/*
+	 * Cancel writeback and lock every folio in the cluster.
+	 * Drop the locks on [submitted, cluster_size) before retaking dropped
+	 * locks on [0, submitted) to prevent deadlocks.
+	 */
 	for (i = 0; i < cc->cluster_size; i++) {
 		struct folio *folio = page_folio(cc->rpages[i]);

-		if (i < submitted) {
+		if (i < submitted)
 			inode_inc_dirty_pages(cc->inode);
-			folio_lock(folio);
-		}
-		folio_clear_f2fs_gcing(folio);
+		else
+			folio_unlock(folio);
 		if (folio_test_writeback(folio))
 			folio_end_writeback(folio);
 	}
+	/* Retake all folio locks in ascending order */
+	for (i = 0; i < cc->cluster_size; i++) {
+		struct folio *folio = page_folio(cc->rpages[i]);
+
+		folio_lock(folio);
+		folio_clear_f2fs_gcing(folio);
+	}
 }

 static void set_cluster_dirty(struct compress_ctx *cc)
-- 
2.53.0



Best Regards,
Yan, Zi
Re: [PATCH v4 00/16] Remove PG_private by using page/folio->private checks instead
Posted by Zi Yan 1 week, 2 days ago
On 13 Sep 2026, at 23:39, Andrew Morton wrote:

> On Sun, 13 Sep 2026 22:23:58 -0400 Zi Yan <ziy@nvidia.com> wrote:
>
>> This patchset removes PG_private to make space for upcoming 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.
>>
>> Patch 6 is picked up separately in f2fs tree, but since mm-new does not
>> have it yet, it is sent for MM testing.
>
> AI review claims to have found a pre-existing critical level deadlock
> in f2fs:
>
> 	https://sashiko.dev/#/patchset/20260913-remove-pg_private-v4-0-848550f7574e@nvidia.com
>
> it also had a few things to say about this patchset and, as always,
> hugetlb.c.

It seems that Sashiko overwrote my patch reviews with the reviews to
Matthew’s md patches. :/ I wonder if there is a way of recovering them.

>
>
> Thanks, The MM bits appear adequately reviewed and review of the non-MM
> bits are, as usual:
>
>   Great to have but I won't permit lack of other-than-MM review to
>   block MM improvements.
>
> So I'll queue it all up and shall push it into -next after a few days.
>
> Acks from non-MM maintainers are appreciated.
>
> If a non-MM patch appears in linux-next I'll autodrop the mm.git copy
> of that patch.

Thanks.

Best Regards,
Yan, Zi
Re: [PATCH v4 00/16] Remove PG_private by using page/folio->private checks instead
Posted by Matthew Wilcox 1 week, 4 days ago
On Sun, Sep 13, 2026 at 10:23:58PM -0400, Zi Yan wrote:
>       md/md-bitmap: replace PagePrivate() with page_private()
>       buffer: replace page_buffer() with page_private() and delete it

Sorry, looks like I screwed up git send-email usage.  I'm proposing
replacing these two patches wth the three I sent.
Re: [PATCH v4 00/16] Remove PG_private by using page/folio->private checks instead
Posted by David Hildenbrand (Arm) 1 week, 3 days ago
On 9/14/26 06:21, Matthew Wilcox wrote:
> On Sun, Sep 13, 2026 at 10:23:58PM -0400, Zi Yan wrote:
>>       md/md-bitmap: replace PagePrivate() with page_private()
>>       buffer: replace page_buffer() with page_private() and delete it
> 
> Sorry, looks like I screwed up git send-email usage.  I'm proposing
> replacing these two patches wth the three I sent.

For everybody CCed wondering "which patches":

https://lore.kernel.org/r/20260914041830.2072626-1-willy@infradead.org
https://lore.kernel.org/r/20260914041830.2072626-2-willy@infradead.org
https://lore.kernel.org/r/20260914041830.2072626-3-willy@infradead.org

-- 
Cheers,

David