On 26 Feb 2025, at 16:00, Zi Yan wrote:
Instead of splitting the large folio uniformly during truncation, try to use buddy allocator like split at the start of truncation range to minimize the number of resulting folios if it is supported. try_folio_split() is introduced to use folio_split() if supported and fall back to uniform split otherwise.
For example, to truncate a order-4 folio [0, 1, 2, 3, 4, 5, ..., 15] between [3, 10] (inclusive), folio_split() splits the folio to [0,1], [2], [3], [4..7], [8..15] and [3], [4..7] can be dropped and [8..15] is kept with zeros in [8..10], then another folio_split() is done at 10, so [8..10] can be dropped.
One possible optimization is to make folio_split() to split a folio based on a given range, like [3..10] above. But that complicates folio_split(), so it will be investigated when necessary.
Signed-off-by: Zi Yan ziy@nvidia.com Cc: Baolin Wang baolin.wang@linux.alibaba.com Cc: David Hildenbrand david@redhat.com Cc: Hugh Dickins hughd@google.com Cc: John Hubbard jhubbard@nvidia.com Cc: Kefeng Wang wangkefeng.wang@huawei.com Cc: Kirill A. Shuemov kirill.shutemov@linux.intel.com Cc: Matthew Wilcox willy@infradead.org Cc: Miaohe Lin linmiaohe@huawei.com Cc: Ryan Roberts ryan.roberts@arm.com Cc: Yang Shi yang@os.amperecomputing.com Cc: Yu Zhao yuzhao@google.com Cc: Kairui Song kasong@tencent.com
include/linux/huge_mm.h | 36 ++++++++++++++++++++++++++++++++++++ mm/huge_memory.c | 6 +++--- mm/truncate.c | 31 ++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 4 deletions(-)
Hi Andrew,
Can you fold the patch below to this one? I find the issue based on the syzbot report[1].
Thanks.
[1] https://lore.kernel.org/linux-mm/67c38d10.050a0220.dc10f.016d.GAE@google.com...
From 48cef9263cda2ea7a7a80219113c5c044eb31c0c Mon Sep 17 00:00:00 2001 From: Zi Yan ziy@nvidia.com Date: Sat, 1 Mar 2025 22:34:24 -0500 Subject: [PATCH] mm/truncate: make sure folio2 is large and has the same mapping after lock
It is possible that folio2 no longer belongs to the original mapping.
Signed-off-by: Zi Yan ziy@nvidia.com --- mm/truncate.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/mm/truncate.c b/mm/truncate.c index 031d0be19f42..0790b6227512 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -244,8 +244,14 @@ bool truncate_inode_partial_folio(struct folio *folio, loff_t start, loff_t end) if (!folio_trylock(folio2)) goto out;
- /* split result does not matter here */ - try_folio_split(folio2, split_at2, NULL); + /* + * make sure folio2 is large and does not change its mapping. + * Its split result does not matter here. + */ + if (folio_test_large(folio2) && + folio2->mapping == folio->mapping) + try_folio_split(folio2, split_at2, NULL); + folio_unlock(folio2); out: folio_put(folio2);