* [PATCH 0/4] Better split_huge_page_test result check
@ 2025-08-06 2:20 Zi Yan
2025-08-06 2:20 ` [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug Zi Yan
` (3 more replies)
0 siblings, 4 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-06 2:20 UTC (permalink / raw)
To: David Hildenbrand, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Zi Yan, Baolin Wang,
Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-kernel, linux-kselftest
David asked me if there is a way of checking split_huge_page_test
results instead of the existing smap check[1]. This patchset uses
kpageflags to get after-split folio orders for a better
split_huge_page_test result check. The added gather_folio_orders() scans
through a VPN range and collects the numbers of folios at different orders.
check_folio_orders() compares the result of gather_folio_orders() to
a given list of numbers of different orders.
split_huge_page_test needs the FORCE_READ fix in [2] to work correctly.
This patchset also:
1. added new order and in folio offset to the split huge page debugfs's
pr_debug()s;
2. changed split_huge_pages_pid() to skip the rest of a folio if it is
split by folio_split() (not changing split_folio_to_order() part
since split_pte_mapped_thp test relies on its behavior).
[1] https://lore.kernel.org/linux-mm/e2f32bdb-e4a4-447c-867c-31405cbba151@redhat.com/
[2] https://lore.kernel.org/linux-mm/20250805175140.241656-1-ziy@nvidia.com/
Zi Yan (4):
mm/huge_memory: add new_order and offset to split_huge_pages*()
pr_debug.
mm/huge_memory: move to next folio after folio_split() succeeds.
selftests/mm: add check_folio_orders() helper.
selftests/mm: check after-split folio orders in split_huge_page_test.
mm/huge_memory.c | 22 +--
.../selftests/mm/split_huge_page_test.c | 67 ++++++---
tools/testing/selftests/mm/vm_util.c | 139 ++++++++++++++++++
tools/testing/selftests/mm/vm_util.h | 2 +
4 files changed, 200 insertions(+), 30 deletions(-)
--
2.47.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug.
2025-08-06 2:20 [PATCH 0/4] Better split_huge_page_test result check Zi Yan
@ 2025-08-06 2:20 ` Zi Yan
2025-08-06 12:42 ` David Hildenbrand
` (2 more replies)
2025-08-06 2:20 ` [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds Zi Yan
` (2 subsequent siblings)
3 siblings, 3 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-06 2:20 UTC (permalink / raw)
To: David Hildenbrand, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Zi Yan, Baolin Wang,
Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-kernel, linux-kselftest
They are useful information for debugging split huge page tests.
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
mm/huge_memory.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 2b4ea5a2ce7d..8a11c2d402d4 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4327,8 +4327,8 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
goto out;
}
- pr_debug("Split huge pages in pid: %d, vaddr: [0x%lx - 0x%lx]\n",
- pid, vaddr_start, vaddr_end);
+ pr_debug("Split huge pages in pid: %d, vaddr: [0x%lx - 0x%lx], new_order: %u, in_folio_offset %ld\n",
+ pid, vaddr_start, vaddr_end, new_order, in_folio_offset);
mmap_read_lock(mm);
/*
--
2.47.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-06 2:20 [PATCH 0/4] Better split_huge_page_test result check Zi Yan
2025-08-06 2:20 ` [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug Zi Yan
@ 2025-08-06 2:20 ` Zi Yan
2025-08-06 12:47 ` David Hildenbrand
` (2 more replies)
2025-08-06 2:20 ` [PATCH 3/4] selftests/mm: add check_folio_orders() helper Zi Yan
2025-08-06 2:20 ` [PATCH 4/4] selftests/mm: check after-split folio orders in split_huge_page_test Zi Yan
3 siblings, 3 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-06 2:20 UTC (permalink / raw)
To: David Hildenbrand, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Zi Yan, Baolin Wang,
Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-kernel, linux-kselftest
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
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 3/4] selftests/mm: add check_folio_orders() helper.
2025-08-06 2:20 [PATCH 0/4] Better split_huge_page_test result check Zi Yan
2025-08-06 2:20 ` [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug Zi Yan
2025-08-06 2:20 ` [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds Zi Yan
@ 2025-08-06 2:20 ` Zi Yan
2025-08-07 3:00 ` wang lian
2025-08-07 6:49 ` Baolin Wang
2025-08-06 2:20 ` [PATCH 4/4] selftests/mm: check after-split folio orders in split_huge_page_test Zi Yan
3 siblings, 2 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-06 2:20 UTC (permalink / raw)
To: David Hildenbrand, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Zi Yan, Baolin Wang,
Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-kernel, linux-kselftest
The helper gathers an folio order statistics of folios within a virtual
address range and checks it against a given order list. It aims to provide
a more precise folio order check instead of just checking the existence of
PMD folios.
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
tools/testing/selftests/mm/vm_util.c | 139 +++++++++++++++++++++++++++
tools/testing/selftests/mm/vm_util.h | 2 +
2 files changed, 141 insertions(+)
diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
index 9dafa7669ef9..373621145b2a 100644
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -17,6 +17,12 @@
#define STATUS_FILE_PATH "/proc/self/status"
#define MAX_LINE_LENGTH 500
+#define PGMAP_PRESENT (1UL << 63)
+#define KPF_COMPOUND_HEAD (1UL << 15)
+#define KPF_COMPOUND_TAIL (1UL << 16)
+#define KPF_THP (1UL << 22)
+#define PFN_MASK ((1UL<<55)-1)
+
unsigned int __page_size;
unsigned int __page_shift;
@@ -338,6 +344,139 @@ int detect_hugetlb_page_sizes(size_t sizes[], int max)
return count;
}
+static int get_page_flags(uint64_t vpn, int pagemap_file, int kpageflags_file,
+ uint64_t *flags)
+{
+ uint64_t pfn;
+ size_t count;
+
+ count = pread(pagemap_file, &pfn, sizeof(pfn),
+ vpn * sizeof(pfn));
+
+ if (count != sizeof(pfn))
+ return -1;
+
+ /*
+ * Treat non-present page as a page without any flag, so that
+ * gather_folio_orders() just record the current folio order.
+ */
+ if (!(pfn & PGMAP_PRESENT)) {
+ *flags = 0;
+ return 0;
+ }
+
+ count = pread(kpageflags_file, flags, sizeof(*flags),
+ (pfn & PFN_MASK) * sizeof(*flags));
+
+ if (count != sizeof(*flags))
+ return -1;
+
+ return 0;
+}
+
+static int gather_folio_orders(uint64_t vpn_start, size_t nr_pages,
+ int pagemap_file, int kpageflags_file,
+ int orders[], int nr_orders)
+{
+ uint64_t page_flags = 0;
+ int cur_order = -1;
+ uint64_t vpn;
+
+ if (!pagemap_file || !kpageflags_file)
+ return -1;
+ if (nr_orders <= 0)
+ return -1;
+
+ for (vpn = vpn_start; vpn < vpn_start + nr_pages; ) {
+ uint64_t next_folio_vpn;
+ int status;
+
+ if (get_page_flags(vpn, pagemap_file, kpageflags_file, &page_flags))
+ return -1;
+
+ /* all order-0 pages with possible false postive (non folio) */
+ if (!(page_flags & (KPF_COMPOUND_HEAD | KPF_COMPOUND_TAIL))) {
+ orders[0]++;
+ vpn++;
+ continue;
+ }
+
+ /* skip non thp compound pages */
+ if (!(page_flags & KPF_THP)) {
+ vpn++;
+ continue;
+ }
+
+ /* vpn points to part of a THP at this point */
+ if (page_flags & KPF_COMPOUND_HEAD)
+ cur_order = 1;
+ else {
+ /* not a head nor a tail in a THP? */
+ if (!(page_flags & KPF_COMPOUND_TAIL))
+ return -1;
+ continue;
+ }
+
+ next_folio_vpn = vpn + (1 << cur_order);
+
+ if (next_folio_vpn >= vpn_start + nr_pages)
+ break;
+
+ while (!(status = get_page_flags(next_folio_vpn, pagemap_file,
+ kpageflags_file,
+ &page_flags))) {
+ /* next compound head page or order-0 page */
+ if ((page_flags & KPF_COMPOUND_HEAD) ||
+ !(page_flags & (KPF_COMPOUND_HEAD |
+ KPF_COMPOUND_TAIL))) {
+ if (cur_order < nr_orders) {
+ orders[cur_order]++;
+ cur_order = -1;
+ vpn = next_folio_vpn;
+ }
+ break;
+ }
+
+ /* not a head nor a tail in a THP? */
+ if (!(page_flags & KPF_COMPOUND_TAIL))
+ return -1;
+
+ cur_order++;
+ next_folio_vpn = vpn + (1 << cur_order);
+ }
+
+ if (status)
+ return status;
+ }
+ if (cur_order > 0 && cur_order < nr_orders)
+ orders[cur_order]++;
+ return 0;
+}
+
+int check_folio_orders(uint64_t vpn_start, size_t nr_pages, int pagemap_file,
+ int kpageflags_file, int orders[], int nr_orders)
+{
+ int vpn_orders[nr_orders];
+ int status;
+ int i;
+
+ memset(vpn_orders, 0, sizeof(int) * nr_orders);
+ status = gather_folio_orders(vpn_start, nr_pages, pagemap_file,
+ kpageflags_file, vpn_orders, nr_orders);
+ if (status)
+ return status;
+
+ status = 0;
+ for (i = 0; i < nr_orders; i++)
+ if (vpn_orders[i] != orders[i]) {
+ ksft_print_msg("order %d: expected: %d got %d\n", i,
+ orders[i], vpn_orders[i]);
+ status = -1;
+ }
+
+ return status;
+}
+
/* If `ioctls' non-NULL, the allowed ioctls will be returned into the var */
int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len,
bool miss, bool wp, bool minor, uint64_t *ioctls)
diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
index b55d1809debc..dee9504a6129 100644
--- a/tools/testing/selftests/mm/vm_util.h
+++ b/tools/testing/selftests/mm/vm_util.h
@@ -85,6 +85,8 @@ bool check_huge_shmem(void *addr, int nr_hpages, uint64_t hpage_size);
int64_t allocate_transhuge(void *ptr, int pagemap_fd);
unsigned long default_huge_page_size(void);
int detect_hugetlb_page_sizes(size_t sizes[], int max);
+int check_folio_orders(uint64_t vpn_start, size_t nr_pages, int pagemap_file,
+ int kpageflags_file, int orders[], int nr_orders);
int uffd_register(int uffd, void *addr, uint64_t len,
bool miss, bool wp, bool minor);
--
2.47.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 4/4] selftests/mm: check after-split folio orders in split_huge_page_test.
2025-08-06 2:20 [PATCH 0/4] Better split_huge_page_test result check Zi Yan
` (2 preceding siblings ...)
2025-08-06 2:20 ` [PATCH 3/4] selftests/mm: add check_folio_orders() helper Zi Yan
@ 2025-08-06 2:20 ` Zi Yan
3 siblings, 0 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-06 2:20 UTC (permalink / raw)
To: David Hildenbrand, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Zi Yan, Baolin Wang,
Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-kernel, linux-kselftest
Instead of just checking the existence of PMD folios before and after folio
split tests, use check_folio_orders() to check after-split folio orders.
The following tests are not changed:
1. split_pte_mapped_thp: the test already uses kpageflags to check;
2. split_file_backed_thp: no vaddr available.
Signed-off-by: Zi Yan <ziy@nvidia.com>
---
.../selftests/mm/split_huge_page_test.c | 67 +++++++++++++------
1 file changed, 46 insertions(+), 21 deletions(-)
diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c
index 3c761228e451..cd34000279fe 100644
--- a/tools/testing/selftests/mm/split_huge_page_test.c
+++ b/tools/testing/selftests/mm/split_huge_page_test.c
@@ -25,6 +25,10 @@
uint64_t pagesize;
unsigned int pageshift;
uint64_t pmd_pagesize;
+unsigned int pmd_order;
+unsigned int max_order;
+
+#define NR_ORDERS (max_order + 1)
#define SPLIT_DEBUGFS "/sys/kernel/debug/split_huge_pages"
#define SMAP_PATH "/proc/self/smaps"
@@ -38,6 +42,11 @@ uint64_t pmd_pagesize;
#define KPF_THP (1UL<<22)
#define GET_ORDER(nr_pages) (31 - __builtin_clz(nr_pages))
+const char *pagemap_proc = "/proc/self/pagemap";
+const char *kpageflags_proc = "/proc/kpageflags";
+int pagemap_fd;
+int kpageflags_fd;
+
int is_backed_by_thp(char *vaddr, int pagemap_file, int kpageflags_file)
{
uint64_t paddr;
@@ -153,6 +162,7 @@ void split_pmd_thp_to_order(int order)
char *one_page;
size_t len = 4 * pmd_pagesize;
size_t i;
+ int orders[NR_ORDERS];
one_page = memalign(pmd_pagesize, len);
if (!one_page)
@@ -174,6 +184,12 @@ void split_pmd_thp_to_order(int order)
if (one_page[i] != (char)i)
ksft_exit_fail_msg("%ld byte corrupted\n", i);
+ memset(orders, 0, sizeof(int) * NR_ORDERS);
+ orders[order] = 4 << (pmd_order - order);
+ if (check_folio_orders((uint64_t)one_page >> pageshift,
+ len >> pageshift, pagemap_fd, kpageflags_fd,
+ orders, NR_ORDERS))
+ ksft_exit_fail_msg("Unexpected THP split\n");
if (!check_huge_anon(one_page, 0, pmd_pagesize))
ksft_exit_fail_msg("Still AnonHugePages not split\n");
@@ -188,22 +204,6 @@ void split_pte_mapped_thp(void)
size_t len = 4 * pmd_pagesize;
uint64_t thp_size;
size_t i;
- const char *pagemap_template = "/proc/%d/pagemap";
- const char *kpageflags_proc = "/proc/kpageflags";
- char pagemap_proc[255];
- int pagemap_fd;
- int kpageflags_fd;
-
- if (snprintf(pagemap_proc, 255, pagemap_template, getpid()) < 0)
- ksft_exit_fail_msg("get pagemap proc error: %s\n", strerror(errno));
-
- pagemap_fd = open(pagemap_proc, O_RDONLY);
- if (pagemap_fd == -1)
- ksft_exit_fail_msg("read pagemap: %s\n", strerror(errno));
-
- kpageflags_fd = open(kpageflags_proc, O_RDONLY);
- if (kpageflags_fd == -1)
- ksft_exit_fail_msg("read kpageflags: %s\n", strerror(errno));
one_page = mmap((void *)(1UL << 30), len, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
@@ -261,8 +261,6 @@ void split_pte_mapped_thp(void)
ksft_test_result_pass("Split PTE-mapped huge pages successful\n");
munmap(one_page, len);
- close(pagemap_fd);
- close(kpageflags_fd);
}
void split_file_backed_thp(int order)
@@ -471,6 +469,7 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc,
size_t i;
char testfile[INPUT_MAX];
int err = 0;
+ int orders[NR_ORDERS];
err = snprintf(testfile, INPUT_MAX, "%s/test", fs_loc);
@@ -482,12 +481,21 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc,
return;
err = 0;
- if (offset == -1)
+ memset(orders, 0, sizeof(int) * NR_ORDERS);
+ if (offset == -1) {
write_debugfs(PID_FMT, getpid(), (uint64_t)addr,
(uint64_t)addr + fd_size, order);
- else
+ orders[order] = fd_size / (pagesize << order);
+ } else {
+ int times = fd_size / pmd_pagesize;
+
write_debugfs(PID_FMT_OFFSET, getpid(), (uint64_t)addr,
(uint64_t)addr + fd_size, order, offset);
+ for (i = order + 1; i < pmd_order; i++)
+ orders[i] = times;
+
+ orders[order] = 2 * times;
+ }
for (i = 0; i < fd_size; i++)
if (*(addr + i) != (char)i) {
@@ -496,6 +504,12 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc,
goto out;
}
+ if (check_folio_orders((uint64_t)addr >> pageshift,
+ fd_size >> pageshift, pagemap_fd, kpageflags_fd,
+ orders, NR_ORDERS))
+ ksft_exit_fail_msg("Unexpected THP split\n");
+
+
if (!check_huge_file(addr, 0, pmd_pagesize)) {
ksft_print_msg("Still FilePmdMapped not split\n");
err = EXIT_FAILURE;
@@ -526,7 +540,6 @@ int main(int argc, char **argv)
const char *fs_loc;
bool created_tmp;
int offset;
- unsigned int max_order;
unsigned int nr_pages;
unsigned int tests;
@@ -543,6 +556,7 @@ int main(int argc, char **argv)
pagesize = getpagesize();
pageshift = ffs(pagesize) - 1;
pmd_pagesize = read_pmd_pagesize();
+ pmd_order = GET_ORDER(pmd_pagesize / pagesize);
if (!pmd_pagesize)
ksft_exit_fail_msg("Reading PMD pagesize failed\n");
@@ -551,6 +565,14 @@ int main(int argc, char **argv)
tests = 2 + (max_order - 1) + (2 * max_order) + (max_order - 1) * 4 + 2;
ksft_set_plan(tests);
+ pagemap_fd = open(pagemap_proc, O_RDONLY);
+ if (pagemap_fd == -1)
+ ksft_exit_fail_msg("read pagemap: %s\n", strerror(errno));
+
+ kpageflags_fd = open(kpageflags_proc, O_RDONLY);
+ if (kpageflags_fd == -1)
+ ksft_exit_fail_msg("read kpageflags: %s\n", strerror(errno));
+
fd_size = 2 * pmd_pagesize;
split_pmd_zero_pages();
@@ -575,6 +597,9 @@ int main(int argc, char **argv)
split_thp_in_pagecache_to_order_at(fd_size, fs_loc, i, offset);
cleanup_thp_fs(fs_loc, created_tmp);
+ close(pagemap_fd);
+ close(kpageflags_fd);
+
ksft_finished();
return 0;
--
2.47.2
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug.
2025-08-06 2:20 ` [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug Zi Yan
@ 2025-08-06 12:42 ` David Hildenbrand
2025-08-06 16:51 ` Lorenzo Stoakes
2025-08-07 6:50 ` Baolin Wang
2 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2025-08-06 12:42 UTC (permalink / raw)
To: Zi Yan, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Baolin Wang, Liam R. Howlett,
Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Shuah Khan,
linux-kernel, linux-kselftest
On 06.08.25 04:20, Zi Yan wrote:
> They are useful information for debugging split huge page tests.
>
> Signed-off-by: Zi Yan <ziy@nvidia.com>
> ---
Acked-by: David Hildenbrand <david@redhat.com>
--
Cheers,
David / dhildenb
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-06 2:20 ` [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds Zi Yan
@ 2025-08-06 12:47 ` David Hildenbrand
2025-08-06 14:29 ` Zi Yan
2025-08-07 8:45 ` Wei Yang
2025-08-07 8:55 ` Wei Yang
2 siblings, 1 reply; 21+ messages in thread
From: David Hildenbrand @ 2025-08-06 12:47 UTC (permalink / raw)
To: Zi Yan, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Baolin Wang, Liam R. Howlett,
Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Shuah Khan,
linux-kernel, linux-kselftest
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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-06 12:47 ` David Hildenbrand
@ 2025-08-06 14:29 ` Zi Yan
0 siblings, 0 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-06 14:29 UTC (permalink / raw)
To: David Hildenbrand
Cc: linux-mm, Andrew Morton, Lorenzo Stoakes, Baolin Wang,
Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-kernel, linux-kselftest
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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug.
2025-08-06 2:20 ` [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug Zi Yan
2025-08-06 12:42 ` David Hildenbrand
@ 2025-08-06 16:51 ` Lorenzo Stoakes
2025-08-07 6:50 ` Baolin Wang
2 siblings, 0 replies; 21+ messages in thread
From: Lorenzo Stoakes @ 2025-08-06 16:51 UTC (permalink / raw)
To: Zi Yan
Cc: David Hildenbrand, linux-mm, Andrew Morton, Baolin Wang,
Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-kernel, linux-kselftest
On Tue, Aug 05, 2025 at 10:20:42PM -0400, Zi Yan wrote:
> They are useful information for debugging split huge page tests.
>
> Signed-off-by: Zi Yan <ziy@nvidia.com>
Seems reasonable, so:
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> ---
> mm/huge_memory.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 2b4ea5a2ce7d..8a11c2d402d4 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -4327,8 +4327,8 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
> goto out;
> }
>
> - pr_debug("Split huge pages in pid: %d, vaddr: [0x%lx - 0x%lx]\n",
> - pid, vaddr_start, vaddr_end);
> + pr_debug("Split huge pages in pid: %d, vaddr: [0x%lx - 0x%lx], new_order: %u, in_folio_offset %ld\n",
> + pid, vaddr_start, vaddr_end, new_order, in_folio_offset);
>
> mmap_read_lock(mm);
> /*
> --
> 2.47.2
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* RE:[PATCH 3/4] selftests/mm: add check_folio_orders() helper.
2025-08-06 2:20 ` [PATCH 3/4] selftests/mm: add check_folio_orders() helper Zi Yan
@ 2025-08-07 3:00 ` wang lian
2025-08-07 17:00 ` [PATCH " Zi Yan
2025-08-07 6:49 ` Baolin Wang
1 sibling, 1 reply; 21+ messages in thread
From: wang lian @ 2025-08-07 3:00 UTC (permalink / raw)
To: ziy
Cc: Liam.Howlett, akpm, baohua, baolin.wang, david, dev.jain,
linux-kernel, linux-kselftest, linux-mm, lorenzo.stoakes, mhocko,
npache, rppt, ryan.roberts, shuah, surenb, vbabka, wang lian
Hi Zi,
Thanks for the patch.
I have a nit suggestion to centralize some of the macro definitions
for better consistency and reusability.
On [Date of patch], Zi Yan wrote:
> diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
> ...
> +#define PGMAP_PRESENT (1UL << 63)
> +#define KPF_COMPOUND_HEAD (1UL << 15)
> +#define KPF_COMPOUND_TAIL (1UL << 16)
> +#define KPF_THP (1UL << 22)
> +#define PFN_MASK ((1UL<<55)-1)
Currently, these macros and `PGMAP_PRESENT` are defined locally in
`vm_util.c`. It would be cleaner to move them to the shared header
`vm_util.h`.
This would also allow us to consistently use `PM_PRESENT` (from the
header) instead of the local `PGMAP_PRESENT` duplicate. I noticed the
patch is already moving in this direction, and we can complete this
cleanup.
How about a change like this?
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -17,17 +17,6 @@
#define STATUS_FILE_PATH "/proc/self/status"
#define MAX_LINE_LENGTH 500
-#define PGMAP_PRESENT (1UL << 63)
-#define KPF_COMPOUND_HEAD (1UL << 15)
-#define KPF_COMPOUND_TAIL (1UL << 16)
-#define KPF_THP (1UL << 22)
-#define PFN_MASK ((1UL<<55)-1)
-
unsigned int __page_size;
unsigned int __page_shift;
@@ -360,7 +349,7 @@ static int get_page_flags(uint64_t vpn, int pagemap_file, int kpageflags_file,
* Treat non-present page as a page without any flag, so that
* gather_folio_orders() just record the current folio order.
*/
- if (!(pfn & PGMAP_PRESENT)) {
+ if (!(pfn & PM_PRESENT)) {
*flags = 0;
return 0;
}
--- a/tools/testing/selftests/mm/vm_util.h
+++ b/tools/testing/selftests/mm/vm_util.h
@@ -17,6 +17,11 @@
#define PM_FILE BIT_ULL(61)
#define PM_SWAP BIT_ULL(62)
#define PM_PRESENT BIT_ULL(63)
+#define KPF_COMPOUND_HEAD (1UL << 15)
+#define KPF_COMPOUND_TAIL (1UL << 16)
+#define KPF_THP (1UL << 22)
+#define PFN_MASK ((1UL<<55)-1)
extern unsigned int __page_size;
extern unsigned int __page_shift;
Best regards,
wang lian
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/4] selftests/mm: add check_folio_orders() helper.
2025-08-06 2:20 ` [PATCH 3/4] selftests/mm: add check_folio_orders() helper Zi Yan
2025-08-07 3:00 ` wang lian
@ 2025-08-07 6:49 ` Baolin Wang
2025-08-07 17:02 ` Zi Yan
1 sibling, 1 reply; 21+ messages in thread
From: Baolin Wang @ 2025-08-07 6:49 UTC (permalink / raw)
To: Zi Yan, David Hildenbrand, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Shuah Khan,
linux-kernel, linux-kselftest
On 2025/8/6 10:20, Zi Yan wrote:
> The helper gathers an folio order statistics of folios within a virtual
> address range and checks it against a given order list. It aims to provide
> a more precise folio order check instead of just checking the existence of
> PMD folios.
>
> Signed-off-by: Zi Yan <ziy@nvidia.com>
> ---
> tools/testing/selftests/mm/vm_util.c | 139 +++++++++++++++++++++++++++
> tools/testing/selftests/mm/vm_util.h | 2 +
> 2 files changed, 141 insertions(+)
>
> diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
> index 9dafa7669ef9..373621145b2a 100644
> --- a/tools/testing/selftests/mm/vm_util.c
> +++ b/tools/testing/selftests/mm/vm_util.c
> @@ -17,6 +17,12 @@
> #define STATUS_FILE_PATH "/proc/self/status"
> #define MAX_LINE_LENGTH 500
>
> +#define PGMAP_PRESENT (1UL << 63)
> +#define KPF_COMPOUND_HEAD (1UL << 15)
> +#define KPF_COMPOUND_TAIL (1UL << 16)
> +#define KPF_THP (1UL << 22)
> +#define PFN_MASK ((1UL<<55)-1)
> +
> unsigned int __page_size;
> unsigned int __page_shift;
>
> @@ -338,6 +344,139 @@ int detect_hugetlb_page_sizes(size_t sizes[], int max)
> return count;
> }
>
> +static int get_page_flags(uint64_t vpn, int pagemap_file, int kpageflags_file,
> + uint64_t *flags)
> +{
> + uint64_t pfn;
> + size_t count;
> +
> + count = pread(pagemap_file, &pfn, sizeof(pfn),
> + vpn * sizeof(pfn));
> +
> + if (count != sizeof(pfn))
> + return -1;
> +
> + /*
> + * Treat non-present page as a page without any flag, so that
> + * gather_folio_orders() just record the current folio order.
> + */
> + if (!(pfn & PGMAP_PRESENT)) {
> + *flags = 0;
> + return 0;
> + }
It looks like you can reuse the helper pagemap_get_pfn() in this file?
> +
> + count = pread(kpageflags_file, flags, sizeof(*flags),
> + (pfn & PFN_MASK) * sizeof(*flags));
> +
> + if (count != sizeof(*flags))
> + return -1;
> +
> + return 0;
> +}
> +
> +static int gather_folio_orders(uint64_t vpn_start, size_t nr_pages,
In this file, other helper functions use userspace virtual address as
parameters, so can we consistently use virtual address for calculations
instead of the 'vpn_start'?
> + int pagemap_file, int kpageflags_file,
> + int orders[], int nr_orders)
> +{
> + uint64_t page_flags = 0;
> + int cur_order = -1;
> + uint64_t vpn;
> +
> + if (!pagemap_file || !kpageflags_file)
> + return -1;
> + if (nr_orders <= 0)
> + return -1;
> +
> + for (vpn = vpn_start; vpn < vpn_start + nr_pages; ) {
> + uint64_t next_folio_vpn;
> + int status;
> +
> + if (get_page_flags(vpn, pagemap_file, kpageflags_file, &page_flags))
> + return -1;
> +
> + /* all order-0 pages with possible false postive (non folio) */
> + if (!(page_flags & (KPF_COMPOUND_HEAD | KPF_COMPOUND_TAIL))) {
> + orders[0]++;
> + vpn++;
> + continue;
> + }
> +
> + /* skip non thp compound pages */
> + if (!(page_flags & KPF_THP)) {
> + vpn++;
> + continue;
> + }
> +
> + /* vpn points to part of a THP at this point */
> + if (page_flags & KPF_COMPOUND_HEAD)
> + cur_order = 1;
> + else {
> + /* not a head nor a tail in a THP? */
> + if (!(page_flags & KPF_COMPOUND_TAIL))
> + return -1;
> + continue;
> + }
> +
> + next_folio_vpn = vpn + (1 << cur_order);
> +
> + if (next_folio_vpn >= vpn_start + nr_pages)
> + break;
> +
> + while (!(status = get_page_flags(next_folio_vpn, pagemap_file,
> + kpageflags_file,
> + &page_flags))) {
> + /* next compound head page or order-0 page */
> + if ((page_flags & KPF_COMPOUND_HEAD) ||
> + !(page_flags & (KPF_COMPOUND_HEAD |
> + KPF_COMPOUND_TAIL))) {
> + if (cur_order < nr_orders) {
> + orders[cur_order]++;
> + cur_order = -1;
> + vpn = next_folio_vpn;
> + }
> + break;
> + }
> +
> + /* not a head nor a tail in a THP? */
> + if (!(page_flags & KPF_COMPOUND_TAIL))
> + return -1;
> +
> + cur_order++;
> + next_folio_vpn = vpn + (1 << cur_order);
> + }
> +
> + if (status)
> + return status;
> + }
> + if (cur_order > 0 && cur_order < nr_orders)
> + orders[cur_order]++;
> + return 0;
> +}
> +
> +int check_folio_orders(uint64_t vpn_start, size_t nr_pages, int pagemap_file,
> + int kpageflags_file, int orders[], int nr_orders)
> +{
> + int vpn_orders[nr_orders];
IIRC, we should avoid using VLA (variable length arrays)?
> + int status;
> + int i;
> +
> + memset(vpn_orders, 0, sizeof(int) * nr_orders);
> + status = gather_folio_orders(vpn_start, nr_pages, pagemap_file,
> + kpageflags_file, vpn_orders, nr_orders);
> + if (status)
> + return status;
> +
> + status = 0;
> + for (i = 0; i < nr_orders; i++)
> + if (vpn_orders[i] != orders[i]) {
> + ksft_print_msg("order %d: expected: %d got %d\n", i,
> + orders[i], vpn_orders[i]);
> + status = -1;
> + }
> +
> + return status;
> +}
> +
> /* If `ioctls' non-NULL, the allowed ioctls will be returned into the var */
> int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len,
> bool miss, bool wp, bool minor, uint64_t *ioctls)
> diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
> index b55d1809debc..dee9504a6129 100644
> --- a/tools/testing/selftests/mm/vm_util.h
> +++ b/tools/testing/selftests/mm/vm_util.h
> @@ -85,6 +85,8 @@ bool check_huge_shmem(void *addr, int nr_hpages, uint64_t hpage_size);
> int64_t allocate_transhuge(void *ptr, int pagemap_fd);
> unsigned long default_huge_page_size(void);
> int detect_hugetlb_page_sizes(size_t sizes[], int max);
> +int check_folio_orders(uint64_t vpn_start, size_t nr_pages, int pagemap_file,
> + int kpageflags_file, int orders[], int nr_orders);
>
> int uffd_register(int uffd, void *addr, uint64_t len,
> bool miss, bool wp, bool minor);
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug.
2025-08-06 2:20 ` [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug Zi Yan
2025-08-06 12:42 ` David Hildenbrand
2025-08-06 16:51 ` Lorenzo Stoakes
@ 2025-08-07 6:50 ` Baolin Wang
2 siblings, 0 replies; 21+ messages in thread
From: Baolin Wang @ 2025-08-07 6:50 UTC (permalink / raw)
To: Zi Yan, David Hildenbrand, linux-mm
Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Shuah Khan,
linux-kernel, linux-kselftest
On 2025/8/6 10:20, Zi Yan wrote:
> They are useful information for debugging split huge page tests.
>
> Signed-off-by: Zi Yan <ziy@nvidia.com>
LGTM.
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
> ---
> mm/huge_memory.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 2b4ea5a2ce7d..8a11c2d402d4 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -4327,8 +4327,8 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
> goto out;
> }
>
> - pr_debug("Split huge pages in pid: %d, vaddr: [0x%lx - 0x%lx]\n",
> - pid, vaddr_start, vaddr_end);
> + pr_debug("Split huge pages in pid: %d, vaddr: [0x%lx - 0x%lx], new_order: %u, in_folio_offset %ld\n",
> + pid, vaddr_start, vaddr_end, new_order, in_folio_offset);
>
> mmap_read_lock(mm);
> /*
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-06 2:20 ` [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds Zi Yan
2025-08-06 12:47 ` David Hildenbrand
@ 2025-08-07 8:45 ` Wei Yang
2025-08-07 17:04 ` Zi Yan
2025-08-07 8:55 ` Wei Yang
2 siblings, 1 reply; 21+ messages in thread
From: Wei Yang @ 2025-08-07 8:45 UTC (permalink / raw)
To: Zi Yan
Cc: David Hildenbrand, linux-mm, Andrew Morton, Lorenzo Stoakes,
Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
Barry Song, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
Michal Hocko, Shuah Khan, linux-kernel, linux-kselftest
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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-06 2:20 ` [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds Zi Yan
2025-08-06 12:47 ` David Hildenbrand
2025-08-07 8:45 ` Wei Yang
@ 2025-08-07 8:55 ` Wei Yang
2025-08-07 17:05 ` Zi Yan
2 siblings, 1 reply; 21+ messages in thread
From: Wei Yang @ 2025-08-07 8:55 UTC (permalink / raw)
To: Zi Yan
Cc: David Hildenbrand, linux-mm, Andrew Morton, Lorenzo Stoakes,
Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
Barry Song, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
Michal Hocko, Shuah Khan, linux-kernel, linux-kselftest
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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/4] selftests/mm: add check_folio_orders() helper.
2025-08-07 3:00 ` wang lian
@ 2025-08-07 17:00 ` Zi Yan
0 siblings, 0 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-07 17:00 UTC (permalink / raw)
To: wang lian
Cc: Liam.Howlett, akpm, baohua, baolin.wang, david, dev.jain,
linux-kernel, linux-kselftest, linux-mm, lorenzo.stoakes, mhocko,
npache, rppt, ryan.roberts, shuah, surenb, vbabka
On 6 Aug 2025, at 23:00, wang lian wrote:
> Hi Zi,
>
> Thanks for the patch.
>
> I have a nit suggestion to centralize some of the macro definitions
> for better consistency and reusability.
>
> On [Date of patch], Zi Yan wrote:
>> diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
>> ...
>> +#define PGMAP_PRESENT (1UL << 63)
>> +#define KPF_COMPOUND_HEAD (1UL << 15)
>> +#define KPF_COMPOUND_TAIL (1UL << 16)
>> +#define KPF_THP (1UL << 22)
>> +#define PFN_MASK ((1UL<<55)-1)
>
> Currently, these macros and `PGMAP_PRESENT` are defined locally in
> `vm_util.c`. It would be cleaner to move them to the shared header
> `vm_util.h`.
>
> This would also allow us to consistently use `PM_PRESENT` (from the
> header) instead of the local `PGMAP_PRESENT` duplicate. I noticed the
> patch is already moving in this direction, and we can complete this
> cleanup.
>
> How about a change like this?
I did not know about PM_PRESENT. Sure, will move the code like you
did below. Thanks.
>
> --- a/tools/testing/selftests/mm/vm_util.c
> +++ b/tools/testing/selftests/mm/vm_util.c
> @@ -17,17 +17,6 @@
> #define STATUS_FILE_PATH "/proc/self/status"
> #define MAX_LINE_LENGTH 500
>
> -#define PGMAP_PRESENT (1UL << 63)
> -#define KPF_COMPOUND_HEAD (1UL << 15)
> -#define KPF_COMPOUND_TAIL (1UL << 16)
> -#define KPF_THP (1UL << 22)
> -#define PFN_MASK ((1UL<<55)-1)
> -
> unsigned int __page_size;
> unsigned int __page_shift;
>
> @@ -360,7 +349,7 @@ static int get_page_flags(uint64_t vpn, int pagemap_file, int kpageflags_file,
> * Treat non-present page as a page without any flag, so that
> * gather_folio_orders() just record the current folio order.
> */
> - if (!(pfn & PGMAP_PRESENT)) {
> + if (!(pfn & PM_PRESENT)) {
> *flags = 0;
> return 0;
> }
> --- a/tools/testing/selftests/mm/vm_util.h
> +++ b/tools/testing/selftests/mm/vm_util.h
> @@ -17,6 +17,11 @@
> #define PM_FILE BIT_ULL(61)
> #define PM_SWAP BIT_ULL(62)
> #define PM_PRESENT BIT_ULL(63)
> +#define KPF_COMPOUND_HEAD (1UL << 15)
> +#define KPF_COMPOUND_TAIL (1UL << 16)
> +#define KPF_THP (1UL << 22)
> +#define PFN_MASK ((1UL<<55)-1)
>
> extern unsigned int __page_size;
> extern unsigned int __page_shift;
>
>
> Best regards,
> wang lian
--
Best Regards,
Yan, Zi
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/4] selftests/mm: add check_folio_orders() helper.
2025-08-07 6:49 ` Baolin Wang
@ 2025-08-07 17:02 ` Zi Yan
0 siblings, 0 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-07 17:02 UTC (permalink / raw)
To: Baolin Wang
Cc: David Hildenbrand, linux-mm, Andrew Morton, Lorenzo Stoakes,
Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Shuah Khan, linux-kernel, linux-kselftest
On 7 Aug 2025, at 2:49, Baolin Wang wrote:
> On 2025/8/6 10:20, Zi Yan wrote:
>> The helper gathers an folio order statistics of folios within a virtual
>> address range and checks it against a given order list. It aims to provide
>> a more precise folio order check instead of just checking the existence of
>> PMD folios.
>>
>> Signed-off-by: Zi Yan <ziy@nvidia.com>
>> ---
>> tools/testing/selftests/mm/vm_util.c | 139 +++++++++++++++++++++++++++
>> tools/testing/selftests/mm/vm_util.h | 2 +
>> 2 files changed, 141 insertions(+)
>>
>> diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
>> index 9dafa7669ef9..373621145b2a 100644
>> --- a/tools/testing/selftests/mm/vm_util.c
>> +++ b/tools/testing/selftests/mm/vm_util.c
>> @@ -17,6 +17,12 @@
>> #define STATUS_FILE_PATH "/proc/self/status"
>> #define MAX_LINE_LENGTH 500
>> +#define PGMAP_PRESENT (1UL << 63)
>> +#define KPF_COMPOUND_HEAD (1UL << 15)
>> +#define KPF_COMPOUND_TAIL (1UL << 16)
>> +#define KPF_THP (1UL << 22)
>> +#define PFN_MASK ((1UL<<55)-1)
>> +
>> unsigned int __page_size;
>> unsigned int __page_shift;
>> @@ -338,6 +344,139 @@ int detect_hugetlb_page_sizes(size_t sizes[], int max)
>> return count;
>> }
>> +static int get_page_flags(uint64_t vpn, int pagemap_file, int kpageflags_file,
>> + uint64_t *flags)
>> +{
>> + uint64_t pfn;
>> + size_t count;
>> +
>> + count = pread(pagemap_file, &pfn, sizeof(pfn),
>> + vpn * sizeof(pfn));
>> +
>> + if (count != sizeof(pfn))
>> + return -1;
>> +
>> + /*
>> + * Treat non-present page as a page without any flag, so that
>> + * gather_folio_orders() just record the current folio order.
>> + */
>> + if (!(pfn & PGMAP_PRESENT)) {
>> + *flags = 0;
>> + return 0;
>> + }
>
> It looks like you can reuse the helper pagemap_get_pfn() in this file?
Sure.
>
>> +
>> + count = pread(kpageflags_file, flags, sizeof(*flags),
>> + (pfn & PFN_MASK) * sizeof(*flags));
>> +
>> + if (count != sizeof(*flags))
>> + return -1;
>> +
>> + return 0;
>> +}
>> +
>> +static int gather_folio_orders(uint64_t vpn_start, size_t nr_pages,
>
> In this file, other helper functions use userspace virtual address as parameters, so can we consistently use virtual address for calculations instead of the 'vpn_start'?
>
Sure.
>> + int pagemap_file, int kpageflags_file,
>> + int orders[], int nr_orders)
>> +{
>> + uint64_t page_flags = 0;
>> + int cur_order = -1;
>> + uint64_t vpn;
>> +
>> + if (!pagemap_file || !kpageflags_file)
>> + return -1;
>> + if (nr_orders <= 0)
>> + return -1;
>> +
>> + for (vpn = vpn_start; vpn < vpn_start + nr_pages; ) {
>> + uint64_t next_folio_vpn;
>> + int status;
>> +
>> + if (get_page_flags(vpn, pagemap_file, kpageflags_file, &page_flags))
>> + return -1;
>> +
>> + /* all order-0 pages with possible false postive (non folio) */
>> + if (!(page_flags & (KPF_COMPOUND_HEAD | KPF_COMPOUND_TAIL))) {
>> + orders[0]++;
>> + vpn++;
>> + continue;
>> + }
>> +
>> + /* skip non thp compound pages */
>> + if (!(page_flags & KPF_THP)) {
>> + vpn++;
>> + continue;
>> + }
>> +
>> + /* vpn points to part of a THP at this point */
>> + if (page_flags & KPF_COMPOUND_HEAD)
>> + cur_order = 1;
>> + else {
>> + /* not a head nor a tail in a THP? */
>> + if (!(page_flags & KPF_COMPOUND_TAIL))
>> + return -1;
>> + continue;
>> + }
>> +
>> + next_folio_vpn = vpn + (1 << cur_order);
>> +
>> + if (next_folio_vpn >= vpn_start + nr_pages)
>> + break;
>> +
>> + while (!(status = get_page_flags(next_folio_vpn, pagemap_file,
>> + kpageflags_file,
>> + &page_flags))) {
>> + /* next compound head page or order-0 page */
>> + if ((page_flags & KPF_COMPOUND_HEAD) ||
>> + !(page_flags & (KPF_COMPOUND_HEAD |
>> + KPF_COMPOUND_TAIL))) {
>> + if (cur_order < nr_orders) {
>> + orders[cur_order]++;
>> + cur_order = -1;
>> + vpn = next_folio_vpn;
>> + }
>> + break;
>> + }
>> +
>> + /* not a head nor a tail in a THP? */
>> + if (!(page_flags & KPF_COMPOUND_TAIL))
>> + return -1;
>> +
>> + cur_order++;
>> + next_folio_vpn = vpn + (1 << cur_order);
>> + }
>> +
>> + if (status)
>> + return status;
>> + }
>> + if (cur_order > 0 && cur_order < nr_orders)
>> + orders[cur_order]++;
>> + return 0;
>> +}
>> +
>> +int check_folio_orders(uint64_t vpn_start, size_t nr_pages, int pagemap_file,
>> + int kpageflags_file, int orders[], int nr_orders)
>> +{
>> + int vpn_orders[nr_orders];
>
> IIRC, we should avoid using VLA (variable length arrays)?
OK. I can change it to malloc.
Thanks.
>
>> + int status;
>> + int i;
>> +
>> + memset(vpn_orders, 0, sizeof(int) * nr_orders);
>> + status = gather_folio_orders(vpn_start, nr_pages, pagemap_file,
>> + kpageflags_file, vpn_orders, nr_orders);
>> + if (status)
>> + return status;
>> +
>> + status = 0;
>> + for (i = 0; i < nr_orders; i++)
>> + if (vpn_orders[i] != orders[i]) {
>> + ksft_print_msg("order %d: expected: %d got %d\n", i,
>> + orders[i], vpn_orders[i]);
>> + status = -1;
>> + }
>> +
>> + return status;
>> +}
>> +
>> /* If `ioctls' non-NULL, the allowed ioctls will be returned into the var */
>> int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len,
>> bool miss, bool wp, bool minor, uint64_t *ioctls)
>> diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
>> index b55d1809debc..dee9504a6129 100644
>> --- a/tools/testing/selftests/mm/vm_util.h
>> +++ b/tools/testing/selftests/mm/vm_util.h
>> @@ -85,6 +85,8 @@ bool check_huge_shmem(void *addr, int nr_hpages, uint64_t hpage_size);
>> int64_t allocate_transhuge(void *ptr, int pagemap_fd);
>> unsigned long default_huge_page_size(void);
>> int detect_hugetlb_page_sizes(size_t sizes[], int max);
>> +int check_folio_orders(uint64_t vpn_start, size_t nr_pages, int pagemap_file,
>> + int kpageflags_file, int orders[], int nr_orders);
>> int uffd_register(int uffd, void *addr, uint64_t len,
>> bool miss, bool wp, bool minor);
--
Best Regards,
Yan, Zi
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-07 8:45 ` Wei Yang
@ 2025-08-07 17:04 ` Zi Yan
0 siblings, 0 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-07 17:04 UTC (permalink / raw)
To: Wei Yang
Cc: David Hildenbrand, linux-mm, Andrew Morton, Lorenzo Stoakes,
Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
Barry Song, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
Michal Hocko, Shuah Khan, linux-kernel, linux-kselftest
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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-07 8:55 ` Wei Yang
@ 2025-08-07 17:05 ` Zi Yan
2025-08-08 3:15 ` Wei Yang
0 siblings, 1 reply; 21+ messages in thread
From: Zi Yan @ 2025-08-07 17:05 UTC (permalink / raw)
To: Wei Yang
Cc: David Hildenbrand, linux-mm, Andrew Morton, Lorenzo Stoakes,
Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
Barry Song, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
Michal Hocko, Shuah Khan, linux-kernel, linux-kselftest
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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-07 17:05 ` Zi Yan
@ 2025-08-08 3:15 ` Wei Yang
2025-08-08 15:24 ` Zi Yan
0 siblings, 1 reply; 21+ messages in thread
From: Wei Yang @ 2025-08-08 3:15 UTC (permalink / raw)
To: Zi Yan
Cc: Wei Yang, David Hildenbrand, linux-mm, Andrew Morton,
Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Shuah Khan,
linux-kernel, linux-kselftest
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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-08 3:15 ` Wei Yang
@ 2025-08-08 15:24 ` Zi Yan
2025-08-08 15:44 ` Zi Yan
0 siblings, 1 reply; 21+ messages in thread
From: Zi Yan @ 2025-08-08 15:24 UTC (permalink / raw)
To: Wei Yang
Cc: David Hildenbrand, linux-mm, Andrew Morton, Lorenzo Stoakes,
Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
Barry Song, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
Michal Hocko, Shuah Khan, linux-kernel, linux-kselftest
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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds.
2025-08-08 15:24 ` Zi Yan
@ 2025-08-08 15:44 ` Zi Yan
0 siblings, 0 replies; 21+ messages in thread
From: Zi Yan @ 2025-08-08 15:44 UTC (permalink / raw)
To: Wei Yang
Cc: David Hildenbrand, linux-mm, Andrew Morton, Lorenzo Stoakes,
Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
Barry Song, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
Michal Hocko, Shuah Khan, linux-kernel, linux-kselftest
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
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2025-08-08 15:44 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-06 2:20 [PATCH 0/4] Better split_huge_page_test result check Zi Yan
2025-08-06 2:20 ` [PATCH 1/4] mm/huge_memory: add new_order and offset to split_huge_pages*() pr_debug Zi Yan
2025-08-06 12:42 ` David Hildenbrand
2025-08-06 16:51 ` Lorenzo Stoakes
2025-08-07 6:50 ` Baolin Wang
2025-08-06 2:20 ` [PATCH 2/4] mm/huge_memory: move to next folio after folio_split() succeeds Zi Yan
2025-08-06 12:47 ` David Hildenbrand
2025-08-06 14:29 ` Zi Yan
2025-08-07 8:45 ` Wei Yang
2025-08-07 17:04 ` Zi Yan
2025-08-07 8:55 ` Wei Yang
2025-08-07 17:05 ` Zi Yan
2025-08-08 3:15 ` Wei Yang
2025-08-08 15:24 ` Zi Yan
2025-08-08 15:44 ` Zi Yan
2025-08-06 2:20 ` [PATCH 3/4] selftests/mm: add check_folio_orders() helper Zi Yan
2025-08-07 3:00 ` wang lian
2025-08-07 17:00 ` [PATCH " Zi Yan
2025-08-07 6:49 ` Baolin Wang
2025-08-07 17:02 ` Zi Yan
2025-08-06 2:20 ` [PATCH 4/4] selftests/mm: check after-split folio orders in split_huge_page_test Zi Yan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).