From: Kemeng Shi shikemeng@huawei.com
euleros inclusion category: feature feature: etmem bugzilla: https://gitee.com/openeuler/kernel/issues/I7RO5Q CVE: NA Reference: https://gitee.com/openeuler/kernel/commit/62620120ef23c8b2dbb69339339b5e4924...
-------------------------------------------------
add a callback in pte_hole during walk_page_range for user to scan page without page table.
Signed-off-by: Kemeng Shi shikemeng@huawei.com Reviewed-by: louhongxiang louhongxiang@huawei.com Reviewed-by: Chen Wandun chenwandun@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- fs/proc/etmem_scan.c | 45 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-)
diff --git a/fs/proc/etmem_scan.c b/fs/proc/etmem_scan.c index 3d751fbb9b40..8bcb8d3af7c5 100644 --- a/fs/proc/etmem_scan.c +++ b/fs/proc/etmem_scan.c @@ -86,6 +86,11 @@
#define RET_RESCAN_FLAG 0x10000
+/* error return IDLE_PAGE_TYPE_MAX or return valid page type */ +enum ProcIdlePageType (*vm_handle_pte_hole)(unsigned long addr, + unsigned long next, int depth, struct mm_walk *walk) = NULL; +EXPORT_SYMBOL_GPL(vm_handle_pte_hole); + static int set_walk_step(const char *val, const struct kernel_param *kp) { int ret; @@ -794,6 +799,11 @@ static unsigned long vm_idle_find_gpa(struct page_idle_ctrl *pic, return INVALID_PAGE; }
+static inline unsigned long mask_to_size(unsigned long mask) +{ + return ~mask + 1; +} + static int mm_idle_hugetlb_entry(pte_t *pte, unsigned long hmask, unsigned long addr, unsigned long next, struct mm_walk *walk); @@ -802,11 +812,40 @@ static int vm_idle_hugetlb_entry(pte_t *pte, unsigned long hmask, struct mm_walk *walk) { struct page_idle_ctrl *pic = walk->private; + enum ProcIdlePageType page_type;
pic->flags |= VM_SCAN_HOST; + + /* hugetlb page table entry of vm maybe not present while page is resident + * in address_space + */ + if (mask_to_size(hmask) != PUD_SIZE && !pte_present(*pte) && + vm_handle_pte_hole != NULL) { + page_type = vm_handle_pte_hole(addr, next, -1, walk); + if (page_type < IDLE_PAGE_TYPE_MAX) + return pic_add_page(pic, addr, next, page_type); + } + return mm_idle_hugetlb_entry(pte, hmask, addr, next, walk); }
+static int vm_idle_pte_hole(unsigned long addr, unsigned long next, int depth, struct mm_walk *walk) +{ + struct page_idle_ctrl *pic = walk->private; + enum ProcIdlePageType pagetype; + + if (vm_handle_pte_hole == NULL) + return 0; + + pagetype = vm_handle_pte_hole(addr, next, depth, walk); + if (pagetype >= IDLE_PAGE_TYPE_MAX) + return 0; + + debug_printk("scan pte hole addr %pK type %d\n", addr, pagetype); + pic->flags |= VM_SCAN_HOST; + return pic_add_page(pic, addr, next, pagetype); +} + static int mm_idle_pmd_entry(pmd_t *pmd, unsigned long addr, unsigned long next, struct mm_walk *walk); static int vm_idle_pmd_entry(pmd_t *pmd, unsigned long addr, @@ -925,6 +964,7 @@ static ssize_t vm_idle_read(struct file *file, char *buf, mm_walk_ops.pmd_entry = vm_idle_pmd_entry; mm_walk_ops.pud_entry = vm_idle_pud_entry; mm_walk_ops.hugetlb_entry = vm_idle_hugetlb_entry; + mm_walk_ops.pte_hole = vm_idle_pte_hole; mm_walk_ops.test_walk = mm_idle_test_walk;
mm_walk.mm = mm; @@ -1052,11 +1092,6 @@ static int mm_idle_pte_range(struct page_idle_ctrl *pic, pmd_t *pmd, return err; }
-static inline unsigned long mask_to_size(unsigned long mask) -{ - return ~mask + 1; -} - static int mm_idle_hugetlb_entry(pte_t *pte, unsigned long hmask, unsigned long addr, unsigned long next, struct mm_walk *walk)