Current behavior is to move to next PAGE_SIZE and split, but that makes it
hard to check after-split folio orders. This is a preparation patch to
allow more precise split_huge_page_test check in an upcoming commit.
split_folio_to_order() part is not changed, since split_pte_mapped_thp test
relies on its current behavior.
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
mm/huge_memory.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 8a11c2d402d4..b2ce8ac0c5a9 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4341,6 +4341,7 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
struct folio *folio;
struct address_space *mapping;
unsigned int target_order = new_order;
+ long nr_pages;
if (!vma)
break;
@@ -4358,6 +4359,8 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
if (!is_transparent_hugepage(folio))
goto next;
+ nr_pages = folio_nr_pages(folio);
+
if (!folio_test_anon(folio)) {
mapping = folio->mapping;
target_order = max(new_order,
@@ -4385,15 +4388,16 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
if (!folio_test_anon(folio) && folio->mapping != mapping)
goto unlock;
- if (in_folio_offset < 0 ||
- in_folio_offset >= folio_nr_pages(folio)) {
+ if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
if (!split_folio_to_order(folio, target_order))
split++;
} else {
- struct page *split_at = folio_page(folio,
- in_folio_offset);
- if (!folio_split(folio, target_order, split_at, NULL))
+ struct page *split_at =
+ folio_page(folio, in_folio_offset);
+ if (!folio_split(folio, target_order, split_at, NULL)) {
split++;
+ addr += PAGE_SIZE * nr_pages;
+ }
}
unlock:
@@ -4438,8 +4442,8 @@ static int split_huge_pages_in_file(const char *file_path, pgoff_t off_start,
if (IS_ERR(candidate))
goto out;
- pr_debug("split file-backed THPs in file: %s, page offset: [0x%lx - 0x%lx]\n",
- file_path, off_start, off_end);
+ pr_debug("split file-backed THPs in file: %s, page offset: [0x%lx - 0x%lx], new_order %u in_folio_offset %ld\n",
+ file_path, off_start, off_end, new_order, in_folio_offset);
mapping = candidate->f_mapping;
min_order = mapping_min_folio_order(mapping);
--
2.47.2
On Tue, Aug 05, 2025 at 10:20:43PM -0400, Zi Yan wrote:
[...]
>
>- if (in_folio_offset < 0 ||
>- in_folio_offset >= folio_nr_pages(folio)) {
>+ if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
> if (!split_folio_to_order(folio, target_order))
> split++;
> } else {
>- struct page *split_at = folio_page(folio,
>- in_folio_offset);
>- if (!folio_split(folio, target_order, split_at, NULL))
>+ struct page *split_at =
>+ folio_page(folio, in_folio_offset);
>+ if (!folio_split(folio, target_order, split_at, NULL)) {
> split++;
>+ addr += PAGE_SIZE * nr_pages;
>+ }
Are we sure addr points to the folio start?
--
Wei Yang
Help you, Help me
On 7 Aug 2025, at 4:55, Wei Yang wrote:
> On Tue, Aug 05, 2025 at 10:20:43PM -0400, Zi Yan wrote:
> [...]
>>
>> - if (in_folio_offset < 0 ||
>> - in_folio_offset >= folio_nr_pages(folio)) {
>> + if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
>> if (!split_folio_to_order(folio, target_order))
>> split++;
>> } else {
>> - struct page *split_at = folio_page(folio,
>> - in_folio_offset);
>> - if (!folio_split(folio, target_order, split_at, NULL))
>> + struct page *split_at =
>> + folio_page(folio, in_folio_offset);
>> + if (!folio_split(folio, target_order, split_at, NULL)) {
>> split++;
>> + addr += PAGE_SIZE * nr_pages;
>> + }
>
> Are we sure addr points to the folio start?
David pointed it out. Will use addr += PAGE_SIZE * (nr_pages - 1).
--
Best Regards,
Yan, Zi
On Thu, Aug 07, 2025 at 01:05:09PM -0400, Zi Yan wrote:
>On 7 Aug 2025, at 4:55, Wei Yang wrote:
>
>> On Tue, Aug 05, 2025 at 10:20:43PM -0400, Zi Yan wrote:
>> [...]
>>>
>>> - if (in_folio_offset < 0 ||
>>> - in_folio_offset >= folio_nr_pages(folio)) {
>>> + if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
>>> if (!split_folio_to_order(folio, target_order))
>>> split++;
>>> } else {
>>> - struct page *split_at = folio_page(folio,
>>> - in_folio_offset);
>>> - if (!folio_split(folio, target_order, split_at, NULL))
>>> + struct page *split_at =
>>> + folio_page(folio, in_folio_offset);
>>> + if (!folio_split(folio, target_order, split_at, NULL)) {
>>> split++;
>>> + addr += PAGE_SIZE * nr_pages;
>>> + }
>>
>> Are we sure addr points to the folio start?
>
>David pointed it out. Will use addr += PAGE_SIZE * (nr_pages - 1).
>
No, let me be more clear. I am talking about the addr in next iteration. I am
talking about the addr in this round.
For an addr in the middle of 2M, we still could get the large folio if my
understanding is correct. Then (addr + whole folio size) seems wrong.
addr
|
v
+-------------------+
| |
+-------------------+
Not sure this would be the case.
>--
>Best Regards,
>Yan, Zi
--
Wei Yang
Help you, Help me
On 7 Aug 2025, at 23:15, Wei Yang wrote:
> On Thu, Aug 07, 2025 at 01:05:09PM -0400, Zi Yan wrote:
>> On 7 Aug 2025, at 4:55, Wei Yang wrote:
>>
>>> On Tue, Aug 05, 2025 at 10:20:43PM -0400, Zi Yan wrote:
>>> [...]
>>>>
>>>> - if (in_folio_offset < 0 ||
>>>> - in_folio_offset >= folio_nr_pages(folio)) {
>>>> + if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
>>>> if (!split_folio_to_order(folio, target_order))
>>>> split++;
>>>> } else {
>>>> - struct page *split_at = folio_page(folio,
>>>> - in_folio_offset);
>>>> - if (!folio_split(folio, target_order, split_at, NULL))
>>>> + struct page *split_at =
>>>> + folio_page(folio, in_folio_offset);
>>>> + if (!folio_split(folio, target_order, split_at, NULL)) {
>>>> split++;
>>>> + addr += PAGE_SIZE * nr_pages;
>>>> + }
>>>
>>> Are we sure addr points to the folio start?
>>
>> David pointed it out. Will use addr += PAGE_SIZE * (nr_pages - 1).
>>
>
> No, let me be more clear. I am talking about the addr in next iteration. I am
> talking about the addr in this round.
>
> For an addr in the middle of 2M, we still could get the large folio if my
> understanding is correct. Then (addr + whole folio size) seems wrong.
>
> addr
> |
> v
> +-------------------+
> | |
> +-------------------+
>
> Not sure this would be the case.
Got it. addr should be aligned up to PAGE_SIZE * nr_pages to get to the next
folio. Thanks.
--
Best Regards,
Yan, Zi
On 8 Aug 2025, at 11:24, Zi Yan wrote:
> On 7 Aug 2025, at 23:15, Wei Yang wrote:
>
>> On Thu, Aug 07, 2025 at 01:05:09PM -0400, Zi Yan wrote:
>>> On 7 Aug 2025, at 4:55, Wei Yang wrote:
>>>
>>>> On Tue, Aug 05, 2025 at 10:20:43PM -0400, Zi Yan wrote:
>>>> [...]
>>>>>
>>>>> - if (in_folio_offset < 0 ||
>>>>> - in_folio_offset >= folio_nr_pages(folio)) {
>>>>> + if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
>>>>> if (!split_folio_to_order(folio, target_order))
>>>>> split++;
>>>>> } else {
>>>>> - struct page *split_at = folio_page(folio,
>>>>> - in_folio_offset);
>>>>> - if (!folio_split(folio, target_order, split_at, NULL))
>>>>> + struct page *split_at =
>>>>> + folio_page(folio, in_folio_offset);
>>>>> + if (!folio_split(folio, target_order, split_at, NULL)) {
>>>>> split++;
>>>>> + addr += PAGE_SIZE * nr_pages;
>>>>> + }
>>>>
>>>> Are we sure addr points to the folio start?
>>>
>>> David pointed it out. Will use addr += PAGE_SIZE * (nr_pages - 1).
>>>
>>
>> No, let me be more clear. I am talking about the addr in next iteration. I am
>> talking about the addr in this round.
>>
>> For an addr in the middle of 2M, we still could get the large folio if my
>> understanding is correct. Then (addr + whole folio size) seems wrong.
>>
>> addr
>> |
>> v
>> +-------------------+
>> | |
>> +-------------------+
>>
>> Not sure this would be the case.
>
> Got it. addr should be aligned up to PAGE_SIZE * nr_pages to get to the next
> folio. Thanks.
On a second thought, this new stepping would mess up with PTE-mapped folio split.
I will drop this patch (pr_debug part will be moved to Patch 1) and change
split_huge_page_test.c instead.
--
Best Regards,
Yan, Zi
On Tue, Aug 05, 2025 at 10:20:43PM -0400, Zi Yan wrote:
>Current behavior is to move to next PAGE_SIZE and split, but that makes it
>hard to check after-split folio orders. This is a preparation patch to
>allow more precise split_huge_page_test check in an upcoming commit.
>
>split_folio_to_order() part is not changed, since split_pte_mapped_thp test
>relies on its current behavior.
>
>Signed-off-by: Zi Yan <ziy@nvidia.com>
>---
> mm/huge_memory.c | 18 +++++++++++-------
> 1 file changed, 11 insertions(+), 7 deletions(-)
>
>diff --git a/mm/huge_memory.c b/mm/huge_memory.c
>index 8a11c2d402d4..b2ce8ac0c5a9 100644
>--- a/mm/huge_memory.c
>+++ b/mm/huge_memory.c
>@@ -4341,6 +4341,7 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
> struct folio *folio;
> struct address_space *mapping;
> unsigned int target_order = new_order;
>+ long nr_pages;
>
> if (!vma)
> break;
>@@ -4358,6 +4359,8 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
> if (!is_transparent_hugepage(folio))
> goto next;
>
>+ nr_pages = folio_nr_pages(folio);
>+
Could be folio_large_nr_pages()?
> if (!folio_test_anon(folio)) {
> mapping = folio->mapping;
> target_order = max(new_order,
>@@ -4385,15 +4388,16 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
> if (!folio_test_anon(folio) && folio->mapping != mapping)
> goto unlock;
>
>- if (in_folio_offset < 0 ||
>- in_folio_offset >= folio_nr_pages(folio)) {
>+ if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
> if (!split_folio_to_order(folio, target_order))
> split++;
> } else {
>- struct page *split_at = folio_page(folio,
>- in_folio_offset);
>- if (!folio_split(folio, target_order, split_at, NULL))
>+ struct page *split_at =
>+ folio_page(folio, in_folio_offset);
>+ if (!folio_split(folio, target_order, split_at, NULL)) {
> split++;
>+ addr += PAGE_SIZE * nr_pages;
>+ }
> }
>
> unlock:
>@@ -4438,8 +4442,8 @@ static int split_huge_pages_in_file(const char *file_path, pgoff_t off_start,
> if (IS_ERR(candidate))
> goto out;
>
>- pr_debug("split file-backed THPs in file: %s, page offset: [0x%lx - 0x%lx]\n",
>- file_path, off_start, off_end);
>+ pr_debug("split file-backed THPs in file: %s, page offset: [0x%lx - 0x%lx], new_order %u in_folio_offset %ld\n",
>+ file_path, off_start, off_end, new_order, in_folio_offset);
>
How about move this part into patch 1?
> mapping = candidate->f_mapping;
> min_order = mapping_min_folio_order(mapping);
>--
>2.47.2
>
--
Wei Yang
Help you, Help me
On 7 Aug 2025, at 4:45, Wei Yang wrote:
> On Tue, Aug 05, 2025 at 10:20:43PM -0400, Zi Yan wrote:
>> Current behavior is to move to next PAGE_SIZE and split, but that makes it
>> hard to check after-split folio orders. This is a preparation patch to
>> allow more precise split_huge_page_test check in an upcoming commit.
>>
>> split_folio_to_order() part is not changed, since split_pte_mapped_thp test
>> relies on its current behavior.
>>
>> Signed-off-by: Zi Yan <ziy@nvidia.com>
>> ---
>> mm/huge_memory.c | 18 +++++++++++-------
>> 1 file changed, 11 insertions(+), 7 deletions(-)
>>
>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
>> index 8a11c2d402d4..b2ce8ac0c5a9 100644
>> --- a/mm/huge_memory.c
>> +++ b/mm/huge_memory.c
>> @@ -4341,6 +4341,7 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
>> struct folio *folio;
>> struct address_space *mapping;
>> unsigned int target_order = new_order;
>> + long nr_pages;
>>
>> if (!vma)
>> break;
>> @@ -4358,6 +4359,8 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
>> if (!is_transparent_hugepage(folio))
>> goto next;
>>
>> + nr_pages = folio_nr_pages(folio);
>> +
>
> Could be folio_large_nr_pages()?
Sure.
>
>> if (!folio_test_anon(folio)) {
>> mapping = folio->mapping;
>> target_order = max(new_order,
>> @@ -4385,15 +4388,16 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
>> if (!folio_test_anon(folio) && folio->mapping != mapping)
>> goto unlock;
>>
>> - if (in_folio_offset < 0 ||
>> - in_folio_offset >= folio_nr_pages(folio)) {
>> + if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
>> if (!split_folio_to_order(folio, target_order))
>> split++;
>> } else {
>> - struct page *split_at = folio_page(folio,
>> - in_folio_offset);
>> - if (!folio_split(folio, target_order, split_at, NULL))
>> + struct page *split_at =
>> + folio_page(folio, in_folio_offset);
>> + if (!folio_split(folio, target_order, split_at, NULL)) {
>> split++;
>> + addr += PAGE_SIZE * nr_pages;
>> + }
>> }
>>
>> unlock:
>> @@ -4438,8 +4442,8 @@ static int split_huge_pages_in_file(const char *file_path, pgoff_t off_start,
>> if (IS_ERR(candidate))
>> goto out;
>>
>> - pr_debug("split file-backed THPs in file: %s, page offset: [0x%lx - 0x%lx]\n",
>> - file_path, off_start, off_end);
>> + pr_debug("split file-backed THPs in file: %s, page offset: [0x%lx - 0x%lx], new_order %u in_folio_offset %ld\n",
>> + file_path, off_start, off_end, new_order, in_folio_offset);
>>
>
> How about move this part into patch 1?
Sure. I missed it. Thanks.
>
>> mapping = candidate->f_mapping;
>> min_order = mapping_min_folio_order(mapping);
>> --
>> 2.47.2
>>
>
> --
> Wei Yang
> Help you, Help me
--
Best Regards,
Yan, Zi
On 06.08.25 04:20, Zi Yan wrote:
> Current behavior is to move to next PAGE_SIZE and split, but that makes it
> hard to check after-split folio orders. This is a preparation patch to
> allow more precise split_huge_page_test check in an upcoming commit.
>
> split_folio_to_order() part is not changed, since split_pte_mapped_thp test
> relies on its current behavior.
>
> Signed-off-by: Zi Yan <ziy@nvidia.com>
> ---
[...]
>
> + nr_pages = folio_nr_pages(folio);
> +
> if (!folio_test_anon(folio)) {
> mapping = folio->mapping;
> target_order = max(new_order,
> @@ -4385,15 +4388,16 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
> if (!folio_test_anon(folio) && folio->mapping != mapping)
> goto unlock;
>
> - if (in_folio_offset < 0 ||
> - in_folio_offset >= folio_nr_pages(folio)) {
> + if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
> if (!split_folio_to_order(folio, target_order))
> split++;
> } else {
> - struct page *split_at = folio_page(folio,
> - in_folio_offset);
> - if (!folio_split(folio, target_order, split_at, NULL))
> + struct page *split_at =
> + folio_page(folio, in_folio_offset);
Can we add an empty line here, and just have this in a single line,
please (feel free to exceed 80chars if it makes the code look less ugly).
> + if (!folio_split(folio, target_order, split_at, NULL)) {
> split++;
> + addr += PAGE_SIZE * nr_pages;
Hm, but won't we do another "addr += PAGE_SIZE" in the for loop?
--
Cheers,
David / dhildenb
On 6 Aug 2025, at 8:47, David Hildenbrand wrote:
> On 06.08.25 04:20, Zi Yan wrote:
>> Current behavior is to move to next PAGE_SIZE and split, but that makes it
>> hard to check after-split folio orders. This is a preparation patch to
>> allow more precise split_huge_page_test check in an upcoming commit.
>>
>> split_folio_to_order() part is not changed, since split_pte_mapped_thp test
>> relies on its current behavior.
>>
>> Signed-off-by: Zi Yan <ziy@nvidia.com>
>> ---
>
> [...]
>
>> + nr_pages = folio_nr_pages(folio);
>> +
>> if (!folio_test_anon(folio)) {
>> mapping = folio->mapping;
>> target_order = max(new_order,
>> @@ -4385,15 +4388,16 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
>> if (!folio_test_anon(folio) && folio->mapping != mapping)
>> goto unlock;
>> - if (in_folio_offset < 0 ||
>> - in_folio_offset >= folio_nr_pages(folio)) {
>> + if (in_folio_offset < 0 || in_folio_offset >= nr_pages) {
>> if (!split_folio_to_order(folio, target_order))
>> split++;
>> } else {
>> - struct page *split_at = folio_page(folio,
>> - in_folio_offset);
>> - if (!folio_split(folio, target_order, split_at, NULL))
>> + struct page *split_at =
>> + folio_page(folio, in_folio_offset);
>
> Can we add an empty line here, and just have this in a single line, please (feel free to exceed 80chars if it makes the code look less ugly).
Sure.
>
>> + if (!folio_split(folio, target_order, split_at, NULL)) {
>> split++;
>> + addr += PAGE_SIZE * nr_pages;
>
> Hm, but won't we do another "addr += PAGE_SIZE" in the for loop?
You are right. Will fix it with addr += PAGE_SIZE * (nr_pages - 1);
Thanks.
Best Regards,
Yan, Zi
© 2016 - 2026 Red Hat, Inc.