]> git.hungrycats.org Git - linux/commitdiff
selftests/arm64: Treat KSM merge_across_nodes as optional
authorMuhammad Usama Anjum <usama.anjum@arm.com>
Tue, 25 Aug 2026 11:18:35 +0000 (12:18 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Sep 2026 11:36:14 +0000 (13:36 +0200)
[ Upstream commit 1a0dba077f34a2f8faa98308d30d4b546d073145 ]

The MTE KSM test requires write access to KSM sysfs but does not check
that it is running as root. It also unconditionally saves, enables and
restores the merge_across_nodes attribute. The kernel only creates this
attribute when CONFIG_NUMA=y, so a non-NUMA kernel prints the following
message three times even though every KSM subtest passes:

  # ERR: missing /sys/kernel/mm/ksm/merge_across_nodes

Skip the test when it is not running as root. Check that the optional
attribute is readable and writable, treating ENOENT as its expected
absence on non-NUMA kernels and skipping the test for other access
failures. Only save, enable and restore the attribute when it is
available.

Check MTE availability before the privilege and sysfs checks so systems
without MTE retain the existing feature-unavailable skip result.

This preserves the existing behavior on NUMA kernels without requiring
NUMA or reducing KSM coverage on single-node systems.

Fixes: f981d8fa2646 ("kselftest/arm64: Verify KSM page merge for MTE pages")
Signed-off-by: Muhammad Usama Anjum <usama.anjum@arm.com>
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
tools/testing/selftests/arm64/mte/check_ksm_options.c

index 866f0929b66478ebcd62331b7cefb6847dd0c29a..4855b737d5507a7f0996eb50b96f0f7a8480ad04 100644 (file)
@@ -6,6 +6,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 static size_t page_sz;
 static unsigned long ksm_sysfs[5];
+static bool has_merge_across_nodes;
+
+static bool merge_across_nodes_available(void)
+{
+       const char *path = PATH_KSM "merge_across_nodes";
+
+       if (!access(path, R_OK | W_OK))
+               return true;
+       if (errno == ENOENT)
+               return false;
+
+       ksft_exit_skip("Unable to read and write %s: %s\n", path,
+                      strerror(errno));
+}
 
 static unsigned long read_sysfs(char *str)
 {
@@ -56,8 +71,10 @@ static void write_sysfs(char *str, unsigned long val)
 
 static void mte_ksm_setup(void)
 {
-       ksm_sysfs[0] = read_sysfs(PATH_KSM "merge_across_nodes");
-       write_sysfs(PATH_KSM "merge_across_nodes", 1);
+       if (has_merge_across_nodes) {
+               ksm_sysfs[0] = read_sysfs(PATH_KSM "merge_across_nodes");
+               write_sysfs(PATH_KSM "merge_across_nodes", 1);
+       }
        ksm_sysfs[1] = read_sysfs(PATH_KSM "sleep_millisecs");
        write_sysfs(PATH_KSM "sleep_millisecs", 0);
        ksm_sysfs[2] = read_sysfs(PATH_KSM "run");
@@ -70,7 +87,8 @@ static void mte_ksm_setup(void)
 
 static void mte_ksm_restore(void)
 {
-       write_sysfs(PATH_KSM "merge_across_nodes", ksm_sysfs[0]);
+       if (has_merge_across_nodes)
+               write_sysfs(PATH_KSM "merge_across_nodes", ksm_sysfs[0]);
        write_sysfs(PATH_KSM "sleep_millisecs", ksm_sysfs[1]);
        write_sysfs(PATH_KSM "run", ksm_sysfs[2]);
        write_sysfs(PATH_KSM "max_page_sharing", ksm_sysfs[3]);
@@ -137,6 +155,11 @@ int main(int argc, char *argv[])
        err = mte_default_setup();
        if (err)
                return err;
+
+       if (geteuid() != 0)
+               ksft_exit_skip("Please run the test as root\n");
+
+       has_merge_across_nodes = merge_across_nodes_available();
        page_sz = getpagesize();
        if (!page_sz) {
                ksft_print_msg("ERR: Unable to get page size\n");