The KSM NUMA merge test allocates identical pages on different NUMA
nodes and verifies KSM behavior with merge_across_nodes enabled and
disabled.

On systems with memoryless NUMA nodes, for example:
 #numactl  -H
      available: 2 nodes (0,4)
      .....
      node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
      node 0 size: 14825 MB
      node 0 free: 1382 MB
      node 4 cpus:
      node 4 size: 0 MB
      node 4 free: 0 MB

the test may attempt to allocate memory on a node without memory,
causing numa_alloc_onnode() to fail and resulting in a spurious test
failure.

The test currently checks numa_num_configured_nodes() to determine
whether sufficient NUMA nodes are available. However, configured nodes
do not necessarily have memory.

Reuse the existing get_first_mem_node() and get_next_mem_node()
helpers to locate NUMA nodes that actually contain memory, and skip
the test when fewer than two such nodes are available.

Before patch:
       ---------------------------
        running ./ksm_tests -N -m 1
       ---------------------------
        mbind: Invalid argument
        ok 1 KSM NUMA merging
        Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0
        [PASS]
       ok 1 ksm_tests -N -m 1
       ---------------------------
        running ./ksm_tests -N -m 0
       ---------------------------
        mbind: Invalid argument
        not ok 1 KSM NUMA merging
        Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0
        [FAIL]
       not ok 2 ksm_tests -N -m 0 # exit=1

After patch:
       ---------------------------
        running ./ksm_tests -N -m 1
       ---------------------------
        At least 2 NUMA nodes with memory must be available
        ok 1
        SKIP KSM NUMA merging
        Totals: pass:0 fail:0 xfail:0 xpass:0 skip:1 error:0
        [PASS]
        ok 1 ksm_tests -N -m 1
       ---------------------------
        running ./ksm_tests -N -m 0
       ---------------------------
        At least 2 NUMA nodes with memory must be available
        ok 1
        SKIP KSM NUMA merging
        Totals: pass:0 fail:0 xfail:0 xpass:0 skip:1 error:0
        [PASS]
        ok 2 ksm_tests -N -m 0

Fixes: e3820ab252dd ("selftest/vm: fix ksm selftest to run with different NUMA 
topologies")
Co-developed-by: David Hildenbrand (Arm) <[email protected]>
Signed-off-by: David Hildenbrand (Arm) <[email protected]>
Signed-off-by: Sayali Patil <[email protected]>
---
 tools/testing/selftests/mm/ksm_tests.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/mm/ksm_tests.c 
b/tools/testing/selftests/mm/ksm_tests.c
index a050f4840cfa..2ebbb544c671 100644
--- a/tools/testing/selftests/mm/ksm_tests.c
+++ b/tools/testing/selftests/mm/ksm_tests.c
@@ -440,9 +440,9 @@ static int get_next_mem_node(int node)
                mem_node = i % (max_node + 1);
                node_size = numa_node_size(mem_node, NULL);
                if (node_size > 0)
-                       break;
+                       return mem_node;
        }
-       return mem_node;
+       return -ENODEV;
 }
 
 static int get_first_mem_node(void)
@@ -455,8 +455,8 @@ static int check_ksm_numa_merge(int merge_type, int 
mapping, int prot, int timeo
 {
        void *numa1_map_ptr, *numa2_map_ptr;
        struct timespec start_time;
+       int first_node, second_node;
        int page_count = 2;
-       int first_node;
 
        if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
                ksft_perror("clock_gettime");
@@ -467,17 +467,19 @@ static int check_ksm_numa_merge(int merge_type, int 
mapping, int prot, int timeo
                ksft_print_msg("NUMA support not enabled\n");
                return KSFT_SKIP;
        }
-       if (numa_num_configured_nodes() <= 1) {
-               ksft_print_msg("At least 2 NUMA nodes must be available\n");
+       first_node = get_first_mem_node();
+       second_node = get_next_mem_node(first_node);
+
+       if (second_node < 0) {
+               ksft_print_msg("At least 2 NUMA nodes with memory must be 
available\n");
                return KSFT_SKIP;
        }
        if (ksm_write_sysfs(KSM_FP("merge_across_nodes"), merge_across_nodes))
                return KSFT_FAIL;
 
        /* allocate 2 pages in 2 different NUMA nodes and fill them with the 
same data */
-       first_node = get_first_mem_node();
        numa1_map_ptr = numa_alloc_onnode(page_size, first_node);
-       numa2_map_ptr = numa_alloc_onnode(page_size, 
get_next_mem_node(first_node));
+       numa2_map_ptr = numa_alloc_onnode(page_size, second_node);
        if (!numa1_map_ptr || !numa2_map_ptr) {
                ksft_perror("numa_alloc_onnode");
                return KSFT_FAIL;
-- 
2.52.0


Reply via email to