]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
selftests/vm: dedup THP helpers
authorZach O'Keefe <zokeefe@google.com>
Thu, 22 Sep 2022 22:40:41 +0000 (15:40 -0700)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 3 Oct 2022 21:03:34 +0000 (14:03 -0700)
These files:

tools/testing/selftests/vm/vm_util.c
tools/testing/selftests/vm/khugepaged.c

Both contain logic to:

1) Determine hugepage size on current system
2) Read /proc/self/smaps to determine number of THPs at an address

Refactor selftests/vm/khugepaged.c to use the vm_util common helpers and
add it as a build dependency.

Since selftests/vm/khugepaged.c is the largest user of check_huge(),
change the signature of check_huge() to match selftests/vm/khugepaged.c's
useage: take an expected number of hugepages, and return a bool indicating
if the correct number of hugepages were found.  Add a wrapper,
check_huge_anon(), in anticipation of checking smaps for file and shmem
hugepages.

Update existing callsites to use the new pattern / function.

Likewise, check_for_pattern() was duplicated, and it's a general enough
helper to include in vm_util helpers as well.

Link: https://lkml.kernel.org/r/20220907144521.3115321-6-zokeefe@google.com
Link: https://lkml.kernel.org/r/20220922224046.1143204-6-zokeefe@google.com
Signed-off-by: Zach O'Keefe <zokeefe@google.com>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Chris Kennelly <ckennelly@google.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: James Houghton <jthoughton@google.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Miaohe Lin <linmiaohe@huawei.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Rongwei Wang <rongwei.wang@linux.alibaba.com>
Cc: SeongJae Park <sj@kernel.org>
Cc: Song Liu <songliubraving@fb.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Yang Shi <shy828301@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
tools/testing/selftests/vm/Makefile
tools/testing/selftests/vm/khugepaged.c
tools/testing/selftests/vm/soft-dirty.c
tools/testing/selftests/vm/split_huge_page_test.c
tools/testing/selftests/vm/vm_util.c
tools/testing/selftests/vm/vm_util.h

index 4ae879f70f4c31a852ff5ded7514f5def17f29c2..c9c0996c122b4fe6911d78c436f56c1560cbd5ca 100644 (file)
@@ -95,6 +95,7 @@ TEST_FILES += va_128TBswitch.sh
 
 include ../lib.mk
 
+$(OUTPUT)/khugepaged: vm_util.c
 $(OUTPUT)/madv_populate: vm_util.c
 $(OUTPUT)/soft-dirty: vm_util.c
 $(OUTPUT)/split_huge_page_test: vm_util.c
index b55dc331af139239830d166b3483bb5ee2f5543f..235a64b4458c311762a5a4ba106dffeb19764d5c 100644 (file)
@@ -12,6 +12,8 @@
 #include <sys/mman.h>
 #include <sys/wait.h>
 
+#include "vm_util.h"
+
 #ifndef MADV_PAGEOUT
 #define MADV_PAGEOUT 21
 #endif
@@ -352,64 +354,12 @@ static void save_settings(void)
        signal(SIGQUIT, restore_settings);
 }
 
-#define MAX_LINE_LENGTH 500
-
-static bool check_for_pattern(FILE *fp, char *pattern, char *buf)
-{
-       while (fgets(buf, MAX_LINE_LENGTH, fp) != NULL) {
-               if (!strncmp(buf, pattern, strlen(pattern)))
-                       return true;
-       }
-       return false;
-}
-
 static bool check_huge(void *addr, int nr_hpages)
 {
-       bool thp = false;
-       int ret;
-       FILE *fp;
-       char buffer[MAX_LINE_LENGTH];
-       char addr_pattern[MAX_LINE_LENGTH];
-
-       ret = snprintf(addr_pattern, MAX_LINE_LENGTH, "%08lx-",
-                      (unsigned long) addr);
-       if (ret >= MAX_LINE_LENGTH) {
-               printf("%s: Pattern is too long\n", __func__);
-               exit(EXIT_FAILURE);
-       }
-
-
-       fp = fopen(PID_SMAPS, "r");
-       if (!fp) {
-               printf("%s: Failed to open file %s\n", __func__, PID_SMAPS);
-               exit(EXIT_FAILURE);
-       }
-       if (!check_for_pattern(fp, addr_pattern, buffer))
-               goto err_out;
-
-       ret = snprintf(addr_pattern, MAX_LINE_LENGTH, "AnonHugePages:%10ld kB",
-                      nr_hpages * (hpage_pmd_size >> 10));
-       if (ret >= MAX_LINE_LENGTH) {
-               printf("%s: Pattern is too long\n", __func__);
-               exit(EXIT_FAILURE);
-       }
-       /*
-        * Fetch the AnonHugePages: in the same block and check whether it got
-        * the expected number of hugeepages next.
-        */
-       if (!check_for_pattern(fp, "AnonHugePages:", buffer))
-               goto err_out;
-
-       if (strncmp(buffer, addr_pattern, strlen(addr_pattern)))
-               goto err_out;
-
-       thp = true;
-err_out:
-       fclose(fp);
-       return thp;
+       return check_huge_anon(addr, nr_hpages, hpage_pmd_size);
 }
 
-
+#define MAX_LINE_LENGTH 500
 static bool check_swap(void *addr, unsigned long size)
 {
        bool swap = false;
@@ -431,7 +381,7 @@ static bool check_swap(void *addr, unsigned long size)
                printf("%s: Failed to open file %s\n", __func__, PID_SMAPS);
                exit(EXIT_FAILURE);
        }
-       if (!check_for_pattern(fp, addr_pattern, buffer))
+       if (!check_for_pattern(fp, addr_pattern, buffer, sizeof(buffer)))
                goto err_out;
 
        ret = snprintf(addr_pattern, MAX_LINE_LENGTH, "Swap:%19ld kB",
@@ -444,7 +394,7 @@ static bool check_swap(void *addr, unsigned long size)
         * Fetch the Swap: in the same block and check whether it got
         * the expected number of hugeepages next.
         */
-       if (!check_for_pattern(fp, "Swap:", buffer))
+       if (!check_for_pattern(fp, "Swap:", buffer, sizeof(buffer)))
                goto err_out;
 
        if (strncmp(buffer, addr_pattern, strlen(addr_pattern)))
@@ -1066,7 +1016,7 @@ int main(int argc, const char **argv)
        setbuf(stdout, NULL);
 
        page_size = getpagesize();
-       hpage_pmd_size = read_num("hpage_pmd_size");
+       hpage_pmd_size = read_pmd_pagesize();
        hpage_pmd_nr = hpage_pmd_size / page_size;
 
        default_settings.khugepaged.max_ptes_none = hpage_pmd_nr - 1;
index e3a43f5d4fa2bb8f3916161a0efb0eb39ac657f8..21d8830c5f243aaf32a0b5eeae181775225056de 100644 (file)
@@ -91,7 +91,7 @@ static void test_hugepage(int pagemap_fd, int pagesize)
        for (i = 0; i < hpage_len; i++)
                map[i] = (char)i;
 
-       if (check_huge(map)) {
+       if (check_huge_anon(map, 1, hpage_len)) {
                ksft_test_result_pass("Test %s huge page allocation\n", __func__);
 
                clear_softdirty();
index 6aa2b8253aeda158aed9d07747962cfccfc324a1..76e1c36dd9e5777b43ba5958bfdac46a6a5a0a71 100644 (file)
@@ -92,7 +92,6 @@ void split_pmd_thp(void)
 {
        char *one_page;
        size_t len = 4 * pmd_pagesize;
-       uint64_t thp_size;
        size_t i;
 
        one_page = memalign(pmd_pagesize, len);
@@ -107,8 +106,7 @@ void split_pmd_thp(void)
        for (i = 0; i < len; i++)
                one_page[i] = (char)i;
 
-       thp_size = check_huge(one_page);
-       if (!thp_size) {
+       if (!check_huge_anon(one_page, 1, pmd_pagesize)) {
                printf("No THP is allocated\n");
                exit(EXIT_FAILURE);
        }
@@ -124,9 +122,8 @@ void split_pmd_thp(void)
                }
 
 
-       thp_size = check_huge(one_page);
-       if (thp_size) {
-               printf("Still %ld kB AnonHugePages not split\n", thp_size);
+       if (check_huge_anon(one_page, 0, pmd_pagesize)) {
+               printf("Still AnonHugePages not split\n");
                exit(EXIT_FAILURE);
        }
 
@@ -172,8 +169,7 @@ void split_pte_mapped_thp(void)
        for (i = 0; i < len; i++)
                one_page[i] = (char)i;
 
-       thp_size = check_huge(one_page);
-       if (!thp_size) {
+       if (!check_huge_anon(one_page, 1, pmd_pagesize)) {
                printf("No THP is allocated\n");
                exit(EXIT_FAILURE);
        }
index b58ab11a7a302a96b2ce297f9aa23c1e0e9bfa7e..9dae51b8219f1db6de79f33cd25c17b4b19d67b1 100644 (file)
@@ -42,9 +42,9 @@ void clear_softdirty(void)
                ksft_exit_fail_msg("writing clear_refs failed\n");
 }
 
-static bool check_for_pattern(FILE *fp, const char *pattern, char *buf)
+bool check_for_pattern(FILE *fp, const char *pattern, char *buf, size_t len)
 {
-       while (fgets(buf, MAX_LINE_LENGTH, fp) != NULL) {
+       while (fgets(buf, len, fp)) {
                if (!strncmp(buf, pattern, strlen(pattern)))
                        return true;
        }
@@ -72,9 +72,10 @@ uint64_t read_pmd_pagesize(void)
        return strtoul(buf, NULL, 10);
 }
 
-uint64_t check_huge(void *addr)
+bool __check_huge(void *addr, char *pattern, int nr_hpages,
+                 uint64_t hpage_size)
 {
-       uint64_t thp = 0;
+       uint64_t thp = -1;
        int ret;
        FILE *fp;
        char buffer[MAX_LINE_LENGTH];
@@ -89,20 +90,27 @@ uint64_t check_huge(void *addr)
        if (!fp)
                ksft_exit_fail_msg("%s: Failed to open file %s\n", __func__, SMAP_FILE_PATH);
 
-       if (!check_for_pattern(fp, addr_pattern, buffer))
+       if (!check_for_pattern(fp, addr_pattern, buffer, sizeof(buffer)))
                goto err_out;
 
        /*
-        * Fetch the AnonHugePages: in the same block and check the number of
+        * Fetch the pattern in the same block and check the number of
         * hugepages.
         */
-       if (!check_for_pattern(fp, "AnonHugePages:", buffer))
+       if (!check_for_pattern(fp, pattern, buffer, sizeof(buffer)))
                goto err_out;
 
-       if (sscanf(buffer, "AnonHugePages:%10ld kB", &thp) != 1)
+       snprintf(addr_pattern, MAX_LINE_LENGTH, "%s%%9ld kB", pattern);
+
+       if (sscanf(buffer, addr_pattern, &thp) != 1)
                ksft_exit_fail_msg("Reading smap error\n");
 
 err_out:
        fclose(fp);
-       return thp;
+       return thp == (nr_hpages * (hpage_size >> 10));
+}
+
+bool check_huge_anon(void *addr, int nr_hpages, uint64_t hpage_size)
+{
+       return __check_huge(addr, "AnonHugePages: ", nr_hpages, hpage_size);
 }
index 2e512bd57ae141e40f3494f3b82124aac1a1bd00..8434ea0c95cd79e3bffaf7a9218edd4d15967a87 100644 (file)
@@ -5,5 +5,6 @@
 uint64_t pagemap_get_entry(int fd, char *start);
 bool pagemap_is_softdirty(int fd, char *start);
 void clear_softdirty(void);
+bool check_for_pattern(FILE *fp, const char *pattern, char *buf, size_t len);
 uint64_t read_pmd_pagesize(void);
-uint64_t check_huge(void *addr);
+bool check_huge_anon(void *addr, int nr_hpages, uint64_t hpage_size);