From: "Zi Yan" <ziy@nvidia.com>
To: "Fang Xieyan" <fangxy@xiaopeng.com>,
"Andrew Morton" <akpm@linux-foundation.org>,
"David Hildenbrand" <david@kernel.org>,
"Matthew Wilcox" <willy@infradead.org>, "Jan Kara" <jack@suse.cz>,
"Hugh Dickins" <hughd@google.com>,
"Carlos Maiolino" <cem@kernel.org>,
"Pankaj Raghav" <p.raghav@samsung.com>
Cc: "Baolin Wang" <baolin.wang@linux.alibaba.com>,
"Liam R . Howlett" <liam@infradead.org>,
"Nico Pache" <nico.pache@linux.dev>,
"Ryan Roberts" <ryan.roberts@arm.com>,
"Dev Jain" <dev.jain@arm.com>, "Barry Song" <baohua@kernel.org>,
"Lance Yang" <lance.yang@linux.dev>,
"Usama Arif" <usama.arif@linux.dev>,
"Kiryl Shutsemau" <kas@kernel.org>,
"Lorenzo Stoakes" <ljs@kernel.org>,
"Vlastimil Babka" <vbabka@kernel.org>,
"Mike Rapoport" <rppt@kernel.org>,
"Suren Baghdasaryan" <surenb@google.com>,
"Michal Hocko" <mhocko@suse.com>,
"Muchun Song" <muchun.song@linux.dev>,
"Kairui Song" <kasong@tencent.com>, <linux-mm@kvack.org>,
<linux-kernel@vger.kernel.org>, <linux-fsdevel@vger.kernel.org>,
<linux-xfs@vger.kernel.org>
Subject: Re: [RFC PATCH 0/3] mm: enable filesystem page-cache large folios without THP
Date: Mon, 09 Nov 2026 23:01:46 -0500 [thread overview]
Message-ID: <DMR8CJLIMPDY.2NOHDSE107FBK@nvidia.com> (raw)
In-Reply-To: <20261110035205.3036-1-fangxy@xiaopeng.com>
+Pankaj, since he was working on this[1].
[1] https://lore.kernel.org/all/20251206030858.1418814-1-p.raghav@samsung.com/
On Mon Nov 9, 2026 at 10:52 PM EST, Fang Xieyan wrote:
> This series makes filesystem page-cache large folios work on kernels
> built with CONFIG_TRANSPARENT_HUGEPAGE=n, and keeps them splittable
> there.
>
> 1. Why this is needed
>
> TRANSPARENT_HUGEPAGE depends on !PREEMPT_RT (mm/Kconfig), so a
> PREEMPT_RT kernel always has THP off. Today that also removes
> file-backed large folios entirely: the helpers that split them live in
> mm/huge_memory.c under CONFIG_TRANSPARENT_HUGEPAGE, and the order
> accessors in include/linux/pagemap.h short-circuit to "no large
> folios" when THP is off, so every filesystem that opts in silently
> ends up with order-0 folios.
>
> The consequence is not only throughput. XFS allows block sizes up to
> 64K and fs/xfs/xfs_super.c refuses to mount anything larger than
> mapping_max_folio_size_supported(). With THP=n that helper reports
> PAGE_SIZE, so a 64K-block filesystem cannot be mounted at all:
>
> XFS (vda): block size (65536 bytes) not supported; Only block size (4096) or less is supported
>
> There is no degraded mode to fall back to, because a block has to fit
> in a single page-cache folio - which is why
> fs/xfs/libxfs/xfs_ialloc.c derives min_folio_order from
> sb_blocklog - PAGE_SHIFT. Either page-cache large folios work without
> THP, or the filesystem is unusable.
>
> 2. What the series does
>
> The anon and file split helpers were already separated by Kairui
> Song's "mm/huge_memory: clean up and decouple the anon and file split
> helpers" (v6 04/17, in mm-unstable); that is the base this series
> starts from.
>
> 1/3 moves the folio-splitting implementation out of mm/huge_memory.c
> into mm/folio_split.c without changing any behaviour. The new object
> is still built by CONFIG_TRANSPARENT_HUGEPAGE, so a THP build keeps
> exactly the code it had before; a pure move is also the easiest thing
> to rebase on top of further churn in this area.
>
> 2/3 builds that object for CONFIG_LARGE_FOLIO instead, and drops the
> anon, PMD and khugepaged dependencies a file-only build cannot have.
> The symbol comes from Matthew Wilcox's "[PATCH v9 12/15]"; if that
> series is in first, this patch shrinks to its Kconfig default and the
> accessors it already rewrites.
>
> 3/3 enables filesystem page-cache large folios when THP is off. It
> lifts the compile-time short circuits in pagemap.h for
> mapping_max_folio_size_supported(), mapping_set_folio_order_range(),
> mapping_max_folio_order() and mapping_min_folio_order().
> PREFERRED_MAX_PAGECACHE_ORDER is left alone: an LF-only build keeps
> the existing cap of order 8 instead of following HPAGE_PMD_ORDER.
> Without THP such folios cannot be PMD-mapped, so raising the ceiling
> would mainly increase the maximum page-cache allocation size. The
> changelog has the arm64 64K-page arithmetic, which is a calculation
> and not a measurement.
>
> The split side is not rewritten: truncate, migration and memory-failure
> already call the helpers outside any THP ifdef, so with 2/3 in place
> they simply stop resolving to the -EINVAL stubs once 3/3 turns
> allocation on. madvise is inside a THP ifdef and does not take part.
>
> 3/3 also makes the XFS mount failure above say why it failed: when
> CONFIG_LARGE_FOLIO is not set, the warning now names the missing
> option instead of only reporting the block size as unsupported. With
> LF=y the added warning is compiled out completely.
>
> 3. Testing
>
> Six configurations build clean as full kernels, bzImage and the
> vmlinux link included, with no new warnings: A (THP=y), B (THP=n,
> LF=y), C (B plus HUGETLBFS), D (THP=n, LF=n), and RT-B and RT-C with
> PREEMPT_RT=y. The PREEMPT_RT configurations were build-tested only.
> No runtime PREEMPT_RT stress test or livelock validation was
> performed.
>
> THP=y is unchanged: the .text sections of mm/filemap.o,
> mm/readahead.o and mm/shmem.o are byte-identical before and after the
> series (md5 equal, 45896, 7139 and 35314 bytes). With THP=n and LF=n
> mm/filemap.o and mm/readahead.o stay identical (44584 and 6259 bytes)
> and every function in mm/shmem.o keeps its size; the only difference
> there is one dead argument load that the folded-out
> mapping_set_large_folios() call leaves behind, so the section keeps
> its 29778 bytes while its md5 does not match.
>
> In the new LF=y, THP=n configuration mm/shmem.o keeps its size as well,
> 48 bytes shorter at 29730. That difference is not from 3/3: 40 of the
> bytes are shmem_writeout(), which shrinks because 2/3 turns
> split_folio_to_list() from an inline -EINVAL stub into a real call, and
> the other 8 are the padding in front of the following function; the
> same 29730 bytes appear with 2/3 alone, and 3/3's own shmem hunk
> changes no function size. The new call is unreachable in this
> configuration anyway, since shmem_alloc_and_add_folio() still forces
> order 0 without THP.
>
> Where the generated code really changes is the allocation policy:
> mm/readahead.o grows by 880 bytes of .text (6259 to 7139) and
> mm/filemap.o by 134 (44584 to 44718). nm -u mm/folio_split.o lists no
> anon, pmd or khugepaged symbols.
>
> Runtime, x86_64, 4K pages, THP=n, QEMU/KVM, on a 64K-block XFS image
> (mkfs.xfs -b size=64k -s size=4k), with kprobes on
> filemap_alloc_folio, filemap_add_folio and __folio_split:
>
> - writing 64M: 84 allocations - 59 at order-8, 5 at order-7, 5 at
> order-6, 5 at order-5, 10 at order-4, i.e. exactly 64M;
> - reading the same 64M back after drop_caches: 72 allocations,
> 62 at order-8, 1 at order-7, 5 at order-6, 4 at order-4;
> - truncating 1M to 700K: one __folio_split, landing at order-4,
> which is the min_folio_order XFS asked for; order-0 never appears
> in any of the three phases;
> - tmpfs writing 32M: 8192 shmem_alloc_folio calls, all order-0;
> - shmem write vs F_SEAL_GROW, reproducible as: memfd_create(),
> ftruncate() to exactly 4096 bytes, F_ADD_SEALS with F_SEAL_GROW,
> then a single pwrite() of 8192 bytes at offset 0, comparing the
> syscall's return value. It returns 4096, the same as the
> pre-series THP=n kernel. A THP=y kernel returns -EPERM here, and
> so did the LF-only build before shmem's mapping was put back
> behind THP; that -EPERM is pre-existing behaviour of THP kernels,
> this series neither introduces it nor extends it to other
> configurations.
>
> Same image on the pre-series kernel, for reference: it fails to mount
> with -ENOSYS before any of the above can run. The whole probe was
> re-run on the final revision of the series with identical numbers.
>
> 4. What this turns on for existing filesystems
>
> LF=y makes the existing opt-in take effect for every filesystem that
> already asks for large folios, and that list is not ext4 only: ext4,
> xfs, btrfs, f2fs, fuse, afs, erofs, nfs, cifs and zonefs all call
> mapping_set_folio_order_range() or mapping_set_large_folios() from
> their inode or superblock setup, unconditionally, today. Those paths
> run on any THP=y kernel; the new configuration is only THP=n with
> LF=y. With THP off the ceiling is PREFERRED_MAX_PAGECACHE_ORDER,
> which stays at order 8.
>
> On the tested 4K-page configuration, 4K-block ext4 gets min order 0
> and max order 8, while 64K-block XFS gets min order 4. Btrfs derives
> both ends from the mkfs sectorsize and nodesize. A THP=y kernel keeps
> the order-9 ceiling (HPAGE_PMD_ORDER) it has today on 4K pages.
>
> shmem keeps its THP dependency: its mapping is only marked large-folio
> capable when THP is enabled, because shmem_alloc_and_add_folio() still
> forces orders to zero without it. This matters beyond cosmetics.
> generic_perform_write() sizes its write chunk from
> mapping_max_folio_size() and passes that length to ->write_begin()
> before clamping it to folio_size(), and shmem_write_begin() rejects
> pos + len > i_size for F_SEAL_GROW. On a 4K memfd sealed with
> F_SEAL_GROW, an 8K write at offset 0 returns 4096 on the pre-series
> THP=n kernel and -EPERM on a THP=y kernel; advertising order 8 while
> allocating order 0 reproduced the -EPERM on an LF-only build. Tying
> shmem's policy to LARGE_FOLIO means the allocation, swap and split
> sides together, which is a separate series.
>
> 5. What is not covered
>
> Since PREEMPT_RT is the motivation, the RT side needs to be explicit.
> The freeze-to-xarray-update window in __folio_freeze_split_file() is
> the fourth freeze site named by Matthew Wilcox in the RT livelock
> thread started by Dong Hui
> (<c2ff0c66422c4e2d869499a1186ff0ae@xiaomi.com>):
>
> There's also __folio_freeze_split_file(). I know PREEMPT_RT
> disables TRANSPARENT_HUGEPAGE at the moment, but hopefully that
> restriction will be lifted.
>
> This series does not fix that problem and does not claim to be
> RT-safe. It only makes a code path that already exists on THP kernels
> reachable in a configuration that has no THP, which is the same
> exposure Kairui described in 06/17 as "should be fixed generically".
> One detail that may matter if a reader-side fix is chosen: the
> function already holds the xarray lock until the folio is no longer
> frozen and visible, since folio_ref_unfreeze() happens before
> xas_unlock_irq(), so a generic fix of that shape would cover this path
> without touching it.
>
> Also not tested here: the migration, memory-failure and madvise split
> entries at runtime (only truncate was exercised end to end), arm64
> with 64K pages, nommu, KASAN and lockdep, xfstests, and the btrfs
> order range.
>
> 6. Questions
>
> (a) Non-THP split accounting. count_mthp_stat() is a no-op without
> THP, so in an LF-only build a file split updates no counter at all and
> THP_SPLIT_PAGE does not even appear in /proc/vmstat. I have a
> follow-up patch that gives the file path its own counter. Would you
> rather see a new vmstat item, an existing one reused, or nothing?
>
> (b) Should XFS select LARGE_FOLIO itself? Three lines of
> "select LARGE_FOLIO if MMU" in fs/xfs/Kconfig make 64K-block XFS
> mountable on a THP=n kernel with no manual configuration; I built such
> a kernel and mounted the 64K image. The cost is mm/folio_split.o: 3.2K
> of .text in a THP=n build, code that every THP=y build already carries,
> paid also by XFS builds that will never use a block size above the page
> size. Kconfig cannot express "only when a 64K filesystem is mounted".
> I left it out because it changes default coverage for a decision XFS
> maintainers should make, but I can add it as 4/4 if that is preferred.
>
> Comments welcome.
>
> Fang Xieyan (3):
> mm: move folio split code into mm/folio_split.c
> mm: build file-backed folio splitting with CONFIG_LARGE_FOLIO
> mm: enable filesystem page-cache large folios without THP
>
> MAINTAINERS | 1 +
> fs/xfs/xfs_super.c | 2 +
> include/linux/huge_mm.h | 60 ++-
> include/linux/page-flags.h | 5 +-
> include/linux/pagemap.h | 17 +-
> mm/Kconfig | 19 +
> mm/Makefile | 1 +
> mm/folio_split.c | 969 +++++++++++++++++++++++++++++++++++++
> mm/huge_memory.c | 920 -----------------------------------
> mm/internal.h | 1 +
> mm/shmem.c | 11 +-
> 11 files changed, 1054 insertions(+), 952 deletions(-)
> create mode 100644 mm/folio_split.c
>
>
> base-commit: b024a51b0184b1efb6f55b11aaf7b15a490a6307
--
Best Regards,
Yan, Zi
next prev parent reply other threads:[~2026-11-10 4:01 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 3:52 Fang Xieyan
2026-11-10 3:52 ` [RFC PATCH 1/3] mm: move folio split code into mm/folio_split.c Fang Xieyan
2026-11-10 3:52 ` [RFC PATCH 2/3] mm: build file-backed folio splitting with CONFIG_LARGE_FOLIO Fang Xieyan
2026-11-10 3:52 ` [RFC PATCH 3/3] mm: enable filesystem page-cache large folios without THP Fang Xieyan
2026-11-10 4:01 ` Zi Yan [this message]
2026-11-10 4:10 ` [RFC PATCH 0/3] " Zi Yan
2026-11-10 4:11 ` Zi Yan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DMR8CJLIMPDY.2NOHDSE107FBK@nvidia.com \
--to=ziy@nvidia.com \
--cc=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=cem@kernel.org \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=fangxy@xiaopeng.com \
--cc=hughd@google.com \
--cc=jack@suse.cz \
--cc=kas@kernel.org \
--cc=kasong@tencent.com \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-xfs@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=muchun.song@linux.dev \
--cc=nico.pache@linux.dev \
--cc=p.raghav@samsung.com \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=surenb@google.com \
--cc=usama.arif@linux.dev \
--cc=vbabka@kernel.org \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®