From: "Kiryl Shutsemau (Meta)" <[email protected]>

check_huge_anon() and check_huge_file() open /proc/self/pagemap and
/proc/kpageflags on every call and read the PMD size from sysfs on top.
The khugepaged test calls them hundreds of times.

Open both once and keep the descriptors.  A pagemap descriptor is tied
to the mm of the process that opened it, and the khugepaged fork() cases
call check_huge() from the child, so reopen it when getpid() changes.

Cache the PMD size in read_pmd_pagesize() as well.

Assisted-by: LLM
Signed-off-by: Kiryl Shutsemau (Meta) <[email protected]>
---
 tools/testing/selftests/mm/vm_util.c | 68 ++++++++++++++++++++--------
 1 file changed, 50 insertions(+), 18 deletions(-)

diff --git a/tools/testing/selftests/mm/vm_util.c 
b/tools/testing/selftests/mm/vm_util.c
index 762c31f7dfab..e284e378d806 100644
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -22,6 +22,43 @@
 unsigned int __page_size;
 unsigned int __page_shift;
 
+/*
+ * A pagemap file reads the mm of the process that opened it, so a child
+ * inherits a descriptor that describes its parent.  Open a new one whenever
+ * the pid changed since the last open.
+ */
+static int pagemap_fd_get(void)
+{
+       static int fd = -1;
+       static pid_t pid;
+
+       if (fd >= 0 && pid == getpid())
+               return fd;
+
+       if (fd >= 0)
+               close(fd);
+
+       fd = open(PAGEMAP_PATH, O_RDONLY);
+       if (fd < 0)
+               ksft_exit_fail_msg("open pagemap fail\n");
+       pid = getpid();
+
+       return fd;
+}
+
+static int kpageflags_fd_get(void)
+{
+       static int fd = -1;
+
+       if (fd < 0) {
+               fd = open(KPAGEFLAGS_PATH, O_RDONLY);
+               if (fd < 0)
+                       ksft_exit_fail_msg("open kpageflags fail\n");
+       }
+
+       return fd;
+}
+
 uint64_t pagemap_get_entry(int fd, char *start)
 {
        const unsigned long pfn = (unsigned long)start / getpagesize();
@@ -161,10 +198,14 @@ bool check_for_pattern(FILE *fp, const char *pattern, 
char *buf, size_t len)
 
 uint64_t read_pmd_pagesize(void)
 {
+       static uint64_t pmd_pagesize;
        int fd;
        char buf[20];
        ssize_t num_read;
 
+       if (pmd_pagesize)
+               return pmd_pagesize;
+
        fd = open(PMD_SIZE_FILE_PATH, O_RDONLY);
        if (fd == -1)
                return 0;
@@ -177,7 +218,8 @@ uint64_t read_pmd_pagesize(void)
        buf[num_read] = '\0';
        close(fd);
 
-       return strtoul(buf, NULL, 10);
+       pmd_pagesize = strtoul(buf, NULL, 10);
+       return pmd_pagesize;
 }
 
 unsigned long rss_anon(void)
@@ -407,7 +449,6 @@ static bool check_huge_type(uint64_t categories, enum 
check_huge_type type)
 static bool __check_huge(void *addr, size_t len, int nr_hpages,
                uint64_t hpage_size, enum check_huge_type type)
 {
-       bool ret = false;
        int pagemap_fd, kpageflags_fd;
        int nr_pmd_mappings = 0;
        uint64_t pmd_pagesize, scan_mapping_size;
@@ -426,42 +467,33 @@ static bool __check_huge(void *addr, size_t len, int 
nr_hpages,
        /* Some mTHP tests check a partially populated PMD-sized range. */
        allow_nonpresent = (uint64_t)nr_hpages * hpage_size < len;
 
-       pagemap_fd = open(PAGEMAP_PATH, O_RDONLY);
-       if (pagemap_fd < 0)
-               ksft_exit_fail_msg("open pagemap fail\n");
-
-       kpageflags_fd = open(KPAGEFLAGS_PATH, O_RDONLY);
-       if (kpageflags_fd < 0)
-               ksft_exit_fail_msg("open kpageflags fail\n");
+       pagemap_fd = pagemap_fd_get();
+       kpageflags_fd = kpageflags_fd_get();
 
        if (!check_pmd_mapping &&
            !check_large_folios(pagemap_fd, kpageflags_fd,
                                addr, len, nr_hpages, hpage_size))
-               goto out;
+               return false;
 
        for (; start < end; start += scan_mapping_size) {
                categories = pagemap_scan_get_categories(pagemap_fd, start);
                pfn = pagemap_get_pfn(pagemap_fd, start);
                if (pfn == -1UL) {
                        if (!allow_nonpresent)
-                               goto out;
+                               return false;
                        else
                                continue;
                }
                if (check_pmd_mapping && (categories & PAGE_IS_HUGE))
                        nr_pmd_mappings++;
                if (!check_huge_type(categories, type))
-                       goto out;
+                       return false;
        }
 
        if (check_pmd_mapping && (nr_pmd_mappings != nr_hpages))
-               goto out;
-       ret = true;
+               return false;
 
-out:
-       close(pagemap_fd);
-       close(kpageflags_fd);
-       return ret;
+       return true;
 }
 
 bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t 
hpage_size)
-- 
2.54.0


Reply via email to