On 11 Feb 2025, at 10:50, Zi Yan wrote: > This is a preparation patch, both added functions are not used yet. > > The added __split_unmapped_folio() is able to split a folio with > its mapping removed in two manners: 1) uniform split (the existing way), > and 2) buddy allocator like split. > > The added __split_folio_to_order() can split a folio into any lower order. > For uniform split, __split_unmapped_folio() calls it once to split > the given folio to the new order. For buddy allocator split, > __split_unmapped_folio() calls it (folio_order - new_order) times > and each time splits the folio containing the given page to one lower > order. > > Signed-off-by: Zi Yan <z...@nvidia.com> > --- > mm/huge_memory.c | 349 ++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 348 insertions(+), 1 deletion(-) >
Hi Andrew, Can you fold the patch below into this one? It addresses the error reported by syzbot at: https://lore.kernel.org/all/67af65cb.050a0220.21dd3.004a....@google.com/ and the concern raised by David Hildenbrand at: https://lore.kernel.org/linux-mm/db77d017-4a1e-4a47-9064-e335cb031...@redhat.com/. Let me know if you prefer a new version of the whole series. Thanks. From a6bd83dfbb1143f1614ede4817cccb1e8cc6290d Mon Sep 17 00:00:00 2001 From: Zi Yan <z...@nvidia.com> Date: Fri, 14 Feb 2025 16:18:24 -0500 Subject: [PATCH] mm/huge_memory: do not drop the original folio during truncate. The caller expects to handle the original folio itself. also make __split_unmapped_folio() never fail, per discussion with David Hildenbrand. Signed-off-by: Zi Yan <z...@nvidia.com> --- mm/huge_memory.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 2eda2a9ec8fc..87cb62c81bf3 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3292,16 +3292,12 @@ bool can_split_folio(struct folio *folio, int caller_pins, int *pextra_pins) * It splits @folio into @new_order folios and copies the @folio metadata to * all the resulting folios. */ -static int __split_folio_to_order(struct folio *folio, int new_order) +static void __split_folio_to_order(struct folio *folio, int new_order) { - int curr_order = folio_order(folio); long nr_pages = folio_nr_pages(folio); long new_nr_pages = 1 << new_order; long index; - if (curr_order <= new_order) - return -EINVAL; - /* * Skip the first new_nr_pages, since the new folio from them have all * the flags from the original folio. @@ -3396,8 +3392,6 @@ static int __split_folio_to_order(struct folio *folio, int new_order) if (!new_order) ClearPageCompound(&folio->page); - - return 0; } /* @@ -3491,7 +3485,6 @@ static int __split_unmapped_folio(struct folio *folio, int new_order, int old_order = folio_order(folio); struct folio *release; struct folio *end_folio = folio_next(folio); - int status; /* order-1 anonymous folio is not supported */ if (folio_test_anon(folio) && split_order == 1) @@ -3524,12 +3517,7 @@ static int __split_unmapped_folio(struct folio *folio, int new_order, split_page_owner(&folio->page, old_order, split_order); pgalloc_tag_split(folio, old_order, split_order); - status = __split_folio_to_order(folio, split_order); - - if (status < 0) { - stop_split = true; - ret = -EINVAL; - } + __split_folio_to_order(folio, split_order); after_split: /* @@ -3567,8 +3555,10 @@ static int __split_unmapped_folio(struct folio *folio, int new_order, folio_test_swapcache(origin_folio)) ? folio_nr_pages(release) : 0)); - if (release != origin_folio) - lru_add_page_tail(origin_folio, &release->page, + if (release == origin_folio) + continue; + + lru_add_page_tail(origin_folio, &release->page, lruvec, list); /* Some pages can be beyond EOF: drop them from page cache */ -- 2.47.2 Best Regards, Yan, Zi