[PATCH v1 05/31] testcases: sysfs: Add sys_node01

Cyril Hrubis <[email protected]>
Newsgroups gmane.linux.ltp
Message-ID <[email protected]>
A test for a /sys/devices/system/node/* files.

Signed-off-by: Cyril Hrubis <[email protected]>
---
 runtest/sysfs                                 |   1 +
 .../sysfs/devices/system/node/.gitignore      |   1 +
 .../kernel/sysfs/devices/system/node/Makefile |   7 ++
 .../sysfs/devices/system/node/sys_node01.c    | 112 ++++++++++++++++++
 4 files changed, 121 insertions(+)
 create mode 100644 testcases/kernel/sysfs/devices/system/node/.gitignore
 create mode 100644 testcases/kernel/sysfs/devices/system/node/Makefile
 create mode 100644 testcases/kernel/sysfs/devices/system/node/sys_node01.c

diff --git a/runtest/sysfs b/runtest/sysfs
index 7c014a57e..347bd78c1 100644
--- a/runtest/sysfs
+++ b/runtest/sysfs
@@ -1,3 +1,4 @@
 sys_power01 sys_power01
 sys_kernel01 sys_kernel01
 sys_clocksource01 sys_clocksource01
+sys_node01 sys_node01
diff --git a/testcases/kernel/sysfs/devices/system/node/.gitignore b/testcases/kernel/sysfs/devices/system/node/.gitignore
new file mode 100644
index 000000000..42a442639
--- /dev/null
+++ b/testcases/kernel/sysfs/devices/system/node/.gitignore
@@ -0,0 +1 @@
+/sys_node01
diff --git a/testcases/kernel/sysfs/devices/system/node/Makefile b/testcases/kernel/sysfs/devices/system/node/Makefile
new file mode 100644
index 000000000..781865569
--- /dev/null
+++ b/testcases/kernel/sysfs/devices/system/node/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2026 Cyril Hrubis <[email protected]>
+
+top_srcdir		?= ../../../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/sysfs/devices/system/node/sys_node01.c b/testcases/kernel/sysfs/devices/system/node/sys_node01.c
new file mode 100644
index 000000000..2c2dca30b
--- /dev/null
+++ b/testcases/kernel/sysfs/devices/system/node/sys_node01.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Cyril Hrubis <[email protected]>
+ */
+
+/*\
+ * Sanity checks for the NUMA node attributes exported under
+ * /sys/devices/system/node/.
+ *
+ * The kernel exports cpulist-style files describing the node state:
+ *
+ * - possible - node ids that could possibly be online
+ * - online   - node ids that are currently online
+ *
+ * as well as a per-node memory summary in nodeN/meminfo.
+ *
+ * The test verifies that:
+ *
+ * - online is a subset of possible
+ * - for each online node MemUsed == MemTotal - MemFree
+ * - the sum of all per-node MemTotal values matches MemTotal in /proc/meminfo
+ *
+ * All checks skip gracefully with TCONF on systems without NUMA sysfs.
+ */
+
+#include <stdio.h>
+#include <limits.h>
+#include "tst_test.h"
+#include "tst_sysfs_assert.h"
+
+#define SYS_NODE "/sys/devices/system/node"
+
+static long read_node_meminfo(int nid, const char *item)
+{
+	char path[PATH_MAX];
+	char fmt[128];
+	long val;
+
+	snprintf(path, sizeof(path), SYS_NODE "/node%d/meminfo", nid);
+	snprintf(fmt, sizeof(fmt), "Node %d %s: %%ld", nid, item);
+
+	SAFE_FILE_LINES_SCANF(path, fmt, &val);
+
+	return val;
+}
+
+static void check_node_mem(int nid, long *sum_total)
+{
+	long total, free, used;
+
+	total = read_node_meminfo(nid, "MemTotal");
+	free = read_node_meminfo(nid, "MemFree");
+	used = read_node_meminfo(nid, "MemUsed");
+
+	*sum_total += total;
+
+	if (used == total - free) {
+		tst_res(TPASS,
+			"node%d: MemUsed (%ld) == MemTotal (%ld) - MemFree (%ld)",
+			nid, used, total, free);
+	} else {
+		tst_res(TFAIL,
+			"node%d: MemUsed (%ld) != MemTotal (%ld) - MemFree (%ld)",
+			nid, used, total, free);
+	}
+}
+
+static void check_sum_memtotal(long sum_total)
+{
+	long global_total;
+
+	SAFE_FILE_LINES_SCANF("/proc/meminfo", "MemTotal: %ld", &global_total);
+
+	if (sum_total == global_total) {
+		tst_res(TPASS,
+			"sum of node MemTotal (%ld kB) matches /proc/meminfo MemTotal (%ld kB)",
+			sum_total, global_total);
+	} else {
+		tst_res(TFAIL,
+			"sum of node MemTotal (%ld kB) differs from /proc/meminfo MemTotal (%ld kB)",
+			sum_total, global_total);
+	}
+}
+
+static void run(void)
+{
+	int count, max_id, nid;
+	long sum_total = 0;
+
+	if (access(SYS_NODE "/online", F_OK)) {
+		tst_res(TCONF, SYS_NODE " is not available");
+		return;
+	}
+
+	TST_SYSFS_ASSERT_LIST_SUBSET(SYS_NODE "/online", SYS_NODE "/possible");
+
+	if (TST_SYSFS_ASSERT_PARSE_LIST(&count, &max_id, SYS_NODE "/online"))
+		return;
+
+	for (nid = 0; nid <= max_id; nid++) {
+		if (!tst_sysfs_exists(SYS_NODE "/node%d", nid))
+			continue;
+
+		check_node_mem(nid, &sum_total);
+	}
+
+	check_sum_memtotal(sum_total);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+};
-- 
2.54.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.