Skip to content

Commit

Permalink
mm/huge_memory: add folio_split() to debugfs testing interface
Browse files Browse the repository at this point in the history
This allows to test folio_split() by specifying an additional in folio
page offset parameter to split_huge_page debugfs interface.

Link: https://lkml.kernel.org/r/20250307174001.242794-7-ziy@nvidia.com
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>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
  • Loading branch information
Zi Yan authored and Andrew Morton committed Mar 18, 2025
1 parent 1f43d5a commit 4b94c18
Showing 1 changed file with 34 additions and 13 deletions.
47 changes: 34 additions & 13 deletions mm/huge_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -4331,7 +4331,8 @@ static inline bool vma_not_suitable_for_thp_split(struct vm_area_struct *vma)
}

static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
unsigned long vaddr_end, unsigned int new_order)
unsigned long vaddr_end, unsigned int new_order,
long in_folio_offset)
{
int ret = 0;
struct task_struct *task;
Expand Down Expand Up @@ -4415,8 +4416,16 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
if (!folio_test_anon(folio) && folio->mapping != mapping)
goto unlock;

if (!split_folio_to_order(folio, target_order))
split++;
if (in_folio_offset < 0 ||
in_folio_offset >= folio_nr_pages(folio)) {
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))
split++;
}

unlock:

Expand All @@ -4439,7 +4448,8 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start,
}

static int split_huge_pages_in_file(const char *file_path, pgoff_t off_start,
pgoff_t off_end, unsigned int new_order)
pgoff_t off_end, unsigned int new_order,
long in_folio_offset)
{
struct filename *file;
struct file *candidate;
Expand Down Expand Up @@ -4488,8 +4498,15 @@ static int split_huge_pages_in_file(const char *file_path, pgoff_t off_start,
if (folio->mapping != mapping)
goto unlock;

if (!split_folio_to_order(folio, target_order))
split++;
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))
split++;
}

unlock:
folio_unlock(folio);
Expand Down Expand Up @@ -4522,6 +4539,7 @@ static ssize_t split_huge_pages_write(struct file *file, const char __user *buf,
int pid;
unsigned long vaddr_start, vaddr_end;
unsigned int new_order = 0;
long in_folio_offset = -1;

ret = mutex_lock_interruptible(&split_debug_mutex);
if (ret)
Expand Down Expand Up @@ -4550,30 +4568,33 @@ static ssize_t split_huge_pages_write(struct file *file, const char __user *buf,
goto out;
}

ret = sscanf(tok_buf, "0x%lx,0x%lx,%d", &off_start,
&off_end, &new_order);
if (ret != 2 && ret != 3) {
ret = sscanf(tok_buf, "0x%lx,0x%lx,%d,%ld", &off_start, &off_end,
&new_order, &in_folio_offset);
if (ret != 2 && ret != 3 && ret != 4) {
ret = -EINVAL;
goto out;
}
ret = split_huge_pages_in_file(file_path, off_start, off_end, new_order);
ret = split_huge_pages_in_file(file_path, off_start, off_end,
new_order, in_folio_offset);
if (!ret)
ret = input_len;

goto out;
}

ret = sscanf(input_buf, "%d,0x%lx,0x%lx,%d", &pid, &vaddr_start, &vaddr_end, &new_order);
ret = sscanf(input_buf, "%d,0x%lx,0x%lx,%d,%ld", &pid, &vaddr_start,
&vaddr_end, &new_order, &in_folio_offset);
if (ret == 1 && pid == 1) {
split_huge_pages_all();
ret = strlen(input_buf);
goto out;
} else if (ret != 3 && ret != 4) {
} else if (ret != 3 && ret != 4 && ret != 5) {
ret = -EINVAL;
goto out;
}

ret = split_huge_pages_pid(pid, vaddr_start, vaddr_end, new_order);
ret = split_huge_pages_pid(pid, vaddr_start, vaddr_end, new_order,
in_folio_offset);
if (!ret)
ret = strlen(input_buf);
out:
Expand Down

0 comments on commit 4b94c18

Please sign in to comment.