This allows to test folio_split() by specifying an additional in folio
page offset parameter to split_huge_page debugfs interface.

Signed-off-by: Zi Yan <z...@nvidia.com>
---
 mm/huge_memory.c | 47 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 34 insertions(+), 13 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 36594eef5c24..dad6819901a8 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4180,7 +4180,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;
@@ -4264,8 +4265,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:
 
@@ -4288,7 +4297,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;
@@ -4337,8 +4347,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);
@@ -4371,6 +4388,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)
@@ -4399,30 +4417,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:
-- 
2.47.2


Reply via email to