[LTP] [PATCH v5 1/3] lib: add tst_test.needs_debugfs flag

Piotr Kubaj piotr.kubaj@intel.com
Wed Oct 21 10:59:30 CEST 2026


Tests reading debugfs files each carry the same statfs() and mount()
dance, because /sys/kernel/debug exists as a plain sysfs directory even
when debugfs is not mounted on it, so checking for the path is not
enough.

With needs_debugfs set the library mounts debugfs during setup, exits
with TCONF if it cannot, and unmounts it at the end only if it did the
mount. The flag implies needs_root. Add TST_DEBUGFS_PATH for tests to
build their paths from, register the flag in the metadata parser and add
a lib/newlib_tests self-test.

Signed-off-by: Piotr Kubaj <piotr.kubaj@intel.com>
---
 doc/developers/writing_tests.rst     |  3 +++
 include/tst_fs.h                     |  6 +++++
 include/tst_test.h                   |  8 ++++++
 lib/newlib_tests/.gitignore          |  1 +
 lib/newlib_tests/runtest.sh          |  1 +
 lib/newlib_tests/tst_needs_debugfs.c | 32 +++++++++++++++++++++++
 lib/tst_test.c                       | 38 ++++++++++++++++++++++++++++
 metadata/metaparse.c                 |  1 +
 8 files changed, 90 insertions(+)
 create mode 100644 lib/newlib_tests/tst_needs_debugfs.c

diff --git a/doc/developers/writing_tests.rst b/doc/developers/writing_tests.rst
index 9a56c0265..5d08cd907 100644
--- a/doc/developers/writing_tests.rst
+++ b/doc/developers/writing_tests.rst
@@ -448,6 +448,9 @@ shell API. For tests using the new shell loader library, see
     * - .needs_cpu_vendor
       - \-
 
+    * - .needs_debugfs
+      - \-
+
     * - .needs_devfs
       - \-
 
diff --git a/include/tst_fs.h b/include/tst_fs.h
index 80eb1292e..278bbab17 100644
--- a/include/tst_fs.h
+++ b/include/tst_fs.h
@@ -8,6 +8,7 @@
 
 /* man 2 statfs or kernel-source/include/uapi/linux/magic.h */
 #define TST_BTRFS_MAGIC    0x9123683E
+#define TST_DEBUGFS_MAGIC  0x64626720
 #define TST_NFS_MAGIC      0x6969
 #define TST_RAMFS_MAGIC    0x858458f6
 #define TST_TMPFS_MAGIC    0x01021994
@@ -58,6 +59,11 @@ enum {
 #define OVL_WORK	OVL_BASE_MNTPOINT"/work"
 #define OVL_MNT		OVL_BASE_MNTPOINT"/ovl"
 
+/**
+ * TST_DEBUGFS_PATH - Where debugfs is mounted by tst_test.needs_debugfs.
+ */
+#define TST_DEBUGFS_PATH "/sys/kernel/debug"
+
 /*
  * @path: path is the pathname of any file within the mounted file system
  * @mult: mult should be TST_KB, TST_MB or TST_GB
diff --git a/include/tst_test.h b/include/tst_test.h
index 80b46f9b1..9e464ea85 100644
--- a/include/tst_test.h
+++ b/include/tst_test.h
@@ -358,6 +358,13 @@ struct tst_fs {
  *               needed for tests that need to create device files since tmpfs
  *               at /tmp is usually mounted with 'nodev' option.
  *
+ * @needs_debugfs: If set debugfs is mounted at TST_DEBUGFS_PATH i.e.
+ *                 /sys/kernel/debug, unless it is mounted there already, and
+ *                 the test exits with TCONF if it cannot be. The library
+ *                 unmounts it at the end of the test if it mounted it. Both
+ *                 mounting debugfs and reading its content require root, so
+ *                 the flag implies tst_test.needs_root.
+ *
  * @restore_wallclock: Saves wall clock at the start of the test and restores
  *                     it at the end with the help of monotonic timers.
  *                     Testcases that modify system wallclock use this to
@@ -576,6 +583,7 @@ struct tst_fs {
 	unsigned int child_needs_reinit:1;
 	unsigned int runs_script:1;
 	unsigned int needs_devfs:1;
+	unsigned int needs_debugfs:1;
 	unsigned int restore_wallclock:1;
 
 	unsigned int all_filesystems:1;
diff --git a/lib/newlib_tests/.gitignore b/lib/newlib_tests/.gitignore
index 3a6e1643c..24008fa5c 100644
--- a/lib/newlib_tests/.gitignore
+++ b/lib/newlib_tests/.gitignore
@@ -59,6 +59,7 @@ tst_needs_cmds05
 tst_needs_cmds06
 tst_needs_cmds07
 tst_needs_cmds08
+tst_needs_debugfs
 test_runtime01
 test_runtime02
 test_children_cleanup
diff --git a/lib/newlib_tests/runtest.sh b/lib/newlib_tests/runtest.sh
index 71808ef8b..1a51d8b7a 100755
--- a/lib/newlib_tests/runtest.sh
+++ b/lib/newlib_tests/runtest.sh
@@ -27,6 +27,7 @@ tst_expiration_timer
 tst_filesystems01
 tst_fuzzy_sync0[1-3]
 tst_needs_cmds0[1-36-8]
+tst_needs_debugfs
 tst_res_hexd
 tst_safe_sscanf
 tst_strstatus}"
diff --git a/lib/newlib_tests/tst_needs_debugfs.c b/lib/newlib_tests/tst_needs_debugfs.c
new file mode 100644
index 000000000..7689665a4
--- /dev/null
+++ b/lib/newlib_tests/tst_needs_debugfs.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Piotr Kubaj <piotr.kubaj@intel.com>
+ */
+
+/*
+ * Test that tst_test.needs_debugfs gets debugfs mounted for the test.
+ *
+ * Run it both with debugfs mounted and with it unmounted, it has to pass either
+ * way. In the latter case the library reports mounting debugfs and has to leave
+ * it unmounted once the test is over.
+ */
+
+#include <sys/vfs.h>
+#include "tst_test.h"
+
+static void run(void)
+{
+	struct statfs sfs;
+
+	SAFE_STATFS(TST_DEBUGFS_PATH, &sfs);
+
+	if (sfs.f_type == TST_DEBUGFS_MAGIC)
+		tst_res(TPASS, "debugfs is mounted at %s", TST_DEBUGFS_PATH);
+	else
+		tst_res(TFAIL, "debugfs is not mounted at %s", TST_DEBUGFS_PATH);
+}
+
+static struct tst_test test = {
+	.needs_debugfs = 1,
+	.test_all = run,
+};
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 10ff73397..a42d3f462 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -15,6 +15,7 @@
 #include <errno.h>
 #include <sys/mount.h>
 #include <sys/types.h>
+#include <sys/vfs.h>
 #include <sys/utsname.h>
 #include <sys/wait.h>
 #include <math.h>
@@ -81,6 +82,7 @@ struct context {
 	tst_atomic_t abort_flag;
 	uint32_t mntpoint_mounted:1;
 	uint32_t ovl_mounted:1;
+	uint32_t debugfs_mounted:1;
 	uint32_t tdebug;
 };
 
@@ -1224,6 +1226,31 @@ static void prepare_and_mount_dev_fs(const char *mntpoint)
 	}
 }
 
+static void mount_debugfs(void)
+{
+	struct statfs sfs;
+
+	/*
+	 * TST_DEBUGFS_PATH exists as a plain sysfs directory whenever
+	 * CONFIG_DEBUG_FS is enabled, whether or not debugfs is mounted on it,
+	 * so the filesystem type has to be checked rather than the directory
+	 * being present.
+	 */
+	if (statfs(TST_DEBUGFS_PATH, &sfs))
+		tst_brk(TCONF | TERRNO, "Can't statfs %s", TST_DEBUGFS_PATH);
+
+	if (sfs.f_type == TST_DEBUGFS_MAGIC)
+		return;
+
+	if (mount("debugfs", TST_DEBUGFS_PATH, "debugfs", 0, NULL)) {
+		tst_brk(TCONF | TERRNO, "Can't mount debugfs at %s",
+			TST_DEBUGFS_PATH);
+	}
+
+	tst_res(TINFO, "Mounted debugfs at %s", TST_DEBUGFS_PATH);
+	context->debugfs_mounted = 1;
+}
+
 static void prepare_and_mount_hugetlb_fs(void)
 {
 	if (access(PATH_MM_HUGEPAGES, F_OK))
@@ -1474,6 +1501,9 @@ static void do_setup(int argc, char *argv[])
 	if (tst_test->needs_kconfigs && tst_kconfig_check(tst_test->needs_kconfigs))
 		tst_brk(TCONF, "Aborting due to unsuitable kernel config, see above!");
 
+	if (tst_test->needs_debugfs)
+		tst_test->needs_root = 1;
+
 	if (tst_test->needs_root && geteuid() != 0)
 		tst_brk(TCONF, "Test needs to be run as root");
 
@@ -1565,6 +1595,9 @@ static void do_setup(int argc, char *argv[])
 			"Two or more of needs_{rofs, devfs, device, hugetlbfs} are set");
 	}
 
+	if (tst_test->needs_debugfs)
+		mount_debugfs();
+
 	if (tst_test->needs_devfs)
 		prepare_and_mount_dev_fs(tst_test->mntpoint);
 
@@ -1676,6 +1709,11 @@ static void do_cleanup(void)
 	if (context->mntpoint_mounted)
 		tst_umount(tst_test->mntpoint);
 
+	if (context->debugfs_mounted) {
+		tst_umount(TST_DEBUGFS_PATH);
+		context->debugfs_mounted = 0;
+	}
+
 	if (tst_test->needs_device && tdev.dev)
 		tst_release_device(tdev.dev);
 
diff --git a/metadata/metaparse.c b/metadata/metaparse.c
index cb141c383..7f2c09037 100644
--- a/metadata/metaparse.c
+++ b/metadata/metaparse.c
@@ -1169,6 +1169,7 @@ static struct typemap tst_test_typemap[] = {
 	{.id = "child_needs_reinit", .type = DATA_BOOL},
 	{.id = "runs_script", .type = DATA_BOOL},
 	{.id = "needs_devfs", .type = DATA_BOOL},
+	{.id = "needs_debugfs", .type = DATA_BOOL},
 	{.id = "restore_wallclock", .type = DATA_BOOL},
 	{.id = "all_filesystems", .type = DATA_BOOL},
 	{.id = "skip_in_lockdown", .type = DATA_BOOL},
-- 
2.47.3

---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu ustawy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w transakcjach handlowych.

Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.



More information about the ltp mailing list