[LTP] [LTP PATCH v2 4/5] ftrace: Add C implementation of ftrace_stress_test and update build
Praveen K Pandey
praveen@linux.ibm.com
Sat Jun 6 21:58:17 CEST 2026
Convert 18 ftrace_stress shell scripts to a single multi-threaded C
implementation. The stress test exercises various ftrace features
concurrently using pthread:
- Switching between different tracers
- Reading from trace_pipe
- Enabling/disabling events
- Modifying buffer size
- Setting trace filters
- Modifying trace options
- And more...
Update Makefile to:
- Build new C test binaries
- Link ftrace_stress_test with pthread
- Use FILTER_OUT_MAKE_TARGETS for library object
- Place dependency rules after generic_leaf_target.mk include
Update runtest/tracing to use new C binaries instead of shell scripts.
Signed-off-by: Praveen K Pandey <praveen@linux.ibm.com>
---
runtest/tracing | 6 +-
testcases/kernel/tracing/ftrace_test/Makefile | 19 +-
.../tracing/ftrace_test/ftrace_stress_test.c | 324 ++++++++++++++++++
3 files changed, 344 insertions(+), 5 deletions(-)
create mode 100644 testcases/kernel/tracing/ftrace_test/ftrace_stress_test.c
diff --git a/runtest/tracing b/runtest/tracing
index 674e2ad97..4204c2dc4 100644
--- a/runtest/tracing
+++ b/runtest/tracing
@@ -1,7 +1,7 @@
#DESCRIPTION:Tracing testing
-ftrace_regression01 ftrace_regression01.sh
-ftrace_regression02 ftrace_regression02.sh
-ftrace-stress-test ftrace_stress_test.sh 90
+ftrace_regression01 ftrace_regression01
+ftrace_regression02 ftrace_regression02
+ftrace-stress-test ftrace_stress_test
dynamic_debug01 dynamic_debug01.sh
fanotify25 fanotify25
pt_full_trace_basic pt_test
diff --git a/testcases/kernel/tracing/ftrace_test/Makefile b/testcases/kernel/tracing/ftrace_test/Makefile
index e4a913a56..f4b9c4c7b 100644
--- a/testcases/kernel/tracing/ftrace_test/Makefile
+++ b/testcases/kernel/tracing/ftrace_test/Makefile
@@ -1,7 +1,22 @@
-top_srcdir ?= ../../../..
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2010 FUJITSU LIMITED
+# Copyright (c) 2024 Linux Test Project
+# Copyright (c) IBM, 2026
+# Converted to C by: Praveen K Pandey <praveen@linux.ibm.com>
+
+top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
-INSTALL_TARGETS := *.sh ftrace_stress/*
+# Filter out ftrace_lib from standalone build targets
+FILTER_OUT_MAKE_TARGETS := ftrace_lib
include $(top_srcdir)/include/mk/generic_leaf_target.mk
+
+# C test binaries with shared library dependencies
+ftrace_regression01: ftrace_lib.o
+ftrace_regression02: ftrace_lib.o
+ftrace_stress_test: ftrace_lib.o
+
+# Only ftrace_stress_test needs pthread
+ftrace_stress_test: LDLIBS += -lpthread
diff --git a/testcases/kernel/tracing/ftrace_test/ftrace_stress_test.c b/testcases/kernel/tracing/ftrace_test/ftrace_stress_test.c
new file mode 100644
index 000000000..c59861b11
--- /dev/null
+++ b/testcases/kernel/tracing/ftrace_test/ftrace_stress_test.c
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2010 FUJITSU LIMITED
+ * Copyright (c) 2024 Linux Test Project
+ * Copyright (c) IBM, 2026
+ *
+ * Author: Li Zefan <lizf@cn.fujitsu.com>
+ * Converted to C by: Praveen K Pandey <praveen@linux.ibm.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Stress test for ftrace subsystem.
+ *
+ * This test exercises various ftrace features concurrently to detect
+ * race conditions, memory leaks, and other issues in the ftrace subsystem.
+ *
+ * [Algorithm]
+ *
+ * The test spawns multiple threads, each exercising a different ftrace
+ * feature:
+ * - Switching between different tracers
+ * - Reading from trace_pipe
+ * - Enabling/disabling events
+ * - Modifying buffer size
+ * - Setting trace filters
+ * - Modifying trace options
+ * - And more...
+ *
+ * All threads run concurrently for a specified duration, then the test
+ * verifies the system is still stable.
+ */
+
+#include <pthread.h>
+#include <signal.h>
+#include "tst_test.h"
+#include "ftrace_lib.h"
+
+#define DEFAULT_TEST_DURATION 60 /* seconds */
+#define MAX_THREADS 20
+
+static volatile int stop_testing = 0;
+static int test_duration = DEFAULT_TEST_DURATION;
+static pthread_t threads[MAX_THREADS];
+static int thread_count = 0;
+
+struct stress_test {
+ const char *name;
+ const char *file;
+ void *(*func)(void *);
+ int enabled;
+};
+
+/* Thread function for current_tracer stress test */
+static void *stress_current_tracer(void *arg)
+{
+ int count;
+ char **tracers;
+ int i, loop;
+
+ (void)arg;
+
+ tracers = ftrace_get_available_tracers(&count);
+ if (!tracers || count == 0) {
+ tst_res(TINFO, "No tracers available");
+ return NULL;
+ }
+
+ loop = 0;
+ while (!stop_testing) {
+ for (i = 0; i < count && !stop_testing; i++) {
+ /* Skip mmiotrace as it can cause issues */
+ if (strcmp(tracers[i], "mmiotrace") == 0)
+ continue;
+
+ ftrace_set_tracer(tracers[i]);
+ }
+ loop++;
+ if (loop >= 200)
+ usleep(1000000); /* Sleep 1 second after 200 loops */
+ }
+
+ for (i = 0; i < count; i++)
+ free(tracers[i]);
+ free(tracers);
+
+ return NULL;
+}
+
+/* Thread function for trace_pipe stress test */
+static void *stress_trace_pipe(void *arg)
+{
+ char *path;
+ FILE *fp;
+ int loop = 0;
+
+ (void)arg;
+
+ path = ftrace_get_path("trace_pipe");
+ if (!path)
+ return NULL;
+
+ while (!stop_testing) {
+ fp = fopen(path, "r");
+ if (fp) {
+ /* Read for a short time */
+ usleep(200000); /* 200ms */
+ fclose(fp);
+ }
+
+ usleep(200000); /* 200ms */
+ loop++;
+ if (loop >= 20) {
+ sleep(2);
+ loop = 0;
+ }
+ }
+
+ free(path);
+ return NULL;
+}
+
+/* Thread function for set_event stress test */
+static void *stress_set_event(void *arg)
+{
+ int i;
+
+ (void)arg;
+
+ while (!stop_testing) {
+ /* Enable/disable all events */
+ for (i = 0; i < 100 && !stop_testing; i++) {
+ ftrace_write_file("events/enable", "1\n");
+ ftrace_write_file("events/enable", "0\n");
+ }
+
+ sleep(1);
+ }
+
+ return NULL;
+}
+
+/* Thread function for buffer_size_kb stress test */
+static void *stress_buffer_size(void *arg)
+{
+ const char *sizes[] = {"1024", "2048", "4096", "8192"};
+ int i;
+
+ (void)arg;
+
+ while (!stop_testing) {
+ for (i = 0; i < 4 && !stop_testing; i++) {
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%s\n", sizes[i]);
+ ftrace_write_file("buffer_size_kb", buf);
+ usleep(100000);
+ }
+ sleep(1);
+ }
+
+ return NULL;
+}
+
+/* Thread function for tracing_on stress test */
+static void *stress_tracing_on(void *arg)
+{
+ int i;
+
+ (void)arg;
+
+ while (!stop_testing) {
+ for (i = 0; i < 100 && !stop_testing; i++) {
+ ftrace_enable_tracing();
+ ftrace_disable_tracing();
+ }
+ sleep(1);
+ }
+
+ return NULL;
+}
+
+/* Thread function for trace_options stress test */
+static void *stress_trace_options(void *arg)
+{
+ const char *options[] = {
+ "print-parent", "sym-offset", "sym-addr",
+ "verbose", "raw", "hex", "bin", "block"
+ };
+ int i;
+
+ (void)arg;
+
+ while (!stop_testing) {
+ for (i = 0; i < 8 && !stop_testing; i++) {
+ char buf[64];
+ snprintf(buf, sizeof(buf), "%s\n", options[i]);
+ ftrace_write_file("trace_options", buf);
+ snprintf(buf, sizeof(buf), "no%s\n", options[i]);
+ ftrace_write_file("trace_options", buf);
+ }
+ sleep(1);
+ }
+
+ return NULL;
+}
+
+/* Thread function for set_ftrace_filter stress test */
+static void *stress_set_ftrace_filter(void *arg)
+{
+ (void)arg;
+
+ if (!ftrace_file_exists("set_ftrace_filter"))
+ return NULL;
+
+ while (!stop_testing) {
+ ftrace_write_file("set_ftrace_filter", "schedule\n");
+ ftrace_write_file("set_ftrace_filter", "\n");
+ usleep(500000);
+ }
+
+ return NULL;
+}
+
+static struct stress_test stress_tests[] = {
+ {"current_tracer", "current_tracer", stress_current_tracer, 0},
+ {"trace_pipe", "trace_pipe", stress_trace_pipe, 0},
+ {"set_event", "events/enable", stress_set_event, 0},
+ {"buffer_size_kb", "buffer_size_kb", stress_buffer_size, 0},
+ {"tracing_on", "tracing_on", stress_tracing_on, 0},
+ {"trace_options", "trace_options", stress_trace_options, 0},
+ {"set_ftrace_filter", "set_ftrace_filter", stress_set_ftrace_filter, 0},
+ {NULL, NULL, NULL, 0}
+};
+
+static void check_available_tests(void)
+{
+ int i;
+
+ for (i = 0; stress_tests[i].name; i++) {
+ if (ftrace_file_exists(stress_tests[i].file) ||
+ access(stress_tests[i].file, F_OK) == 0) {
+ stress_tests[i].enabled = 1;
+ tst_res(TINFO, "Test target available: %s", stress_tests[i].name);
+ } else {
+ tst_res(TINFO, "Test target not available: %s", stress_tests[i].name);
+ }
+ }
+}
+
+static void start_stress_tests(void)
+{
+ int i;
+
+ thread_count = 0;
+ for (i = 0; stress_tests[i].name; i++) {
+ if (!stress_tests[i].enabled)
+ continue;
+
+ if (pthread_create(&threads[thread_count], NULL,
+ stress_tests[i].func, NULL) != 0) {
+ tst_res(TWARN, "Failed to create thread for %s",
+ stress_tests[i].name);
+ } else {
+ tst_res(TINFO, "Started stress test: %s", stress_tests[i].name);
+ thread_count++;
+ }
+ }
+
+ tst_res(TINFO, "Started %d stress test threads", thread_count);
+}
+
+static void stop_stress_tests(void)
+{
+ int i;
+
+ stop_testing = 1;
+
+ for (i = 0; i < thread_count; i++) {
+ pthread_join(threads[i], NULL);
+ }
+
+ tst_res(TINFO, "All stress test threads stopped");
+}
+
+static void run_test(void)
+{
+ tst_res(TINFO, "Starting ftrace stress test for %d seconds", test_duration);
+
+ check_available_tests();
+ start_stress_tests();
+
+ /* Run for specified duration */
+ sleep(test_duration);
+
+ stop_stress_tests();
+
+ tst_res(TPASS, "Ftrace stress test completed successfully");
+ tst_res(TINFO, "Check dmesg for any kernel warnings or errors");
+}
+
+static void setup(void)
+{
+ ftrace_initialize();
+
+ /* Check for test duration parameter */
+ if (tst_parse_int(getenv("LTP_TIMEOUT_MUL"), &test_duration, 1, INT_MAX))
+ test_duration = DEFAULT_TEST_DURATION;
+}
+
+static void cleanup(void)
+{
+ stop_testing = 1;
+ ftrace_cleanup();
+}
+
+static struct tst_test test = {
+ .test_all = run_test,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .timeout = DEFAULT_TEST_DURATION + 30,
+};
+
--
2.50.1 (Apple Git-155)
More information about the ltp
mailing list