Linux Test Project
 help / color / mirror / Atom feed
From: Cyril Hrubis <chrubis@suse.cz>
To: Praveen K Pandey <praveen@linux.ibm.com>
Cc: ltp@lists.linux.it
Subject: Re: [LTP] [PATCH v6 1/5] ftrace: Add common library for C implementation
Date: Wed, 10 Jun 2026 11:31:09 +0200	[thread overview]
Message-ID: <aiku3VRfJZS4dsxY@yuki.lan> (raw)
In-Reply-To: <20260609041632.74427-2-praveen@linux.ibm.com>

Hi!
> +char *ftrace_get_path(const char *filename)
> +{
> +	char *path;
> +
> +	SAFE_ASPRINTF(&path, "%s/%s", tracing_path, filename);
> +	return path;
> +}
> +
> +char *ftrace_read_file(const char *filename)
> +{
> +	char *path;
> +	FILE *fp;
> +	char *content = NULL;
> +	size_t len = 0;
> +	ssize_t read;
> +	char *line = NULL;
> +	size_t total_size = 0;
> +
> +	path = ftrace_get_path(filename);
> +	if (!path)
> +		return NULL;
> +
> +	fp = fopen(path, "r");
> +	free(path);
> +
> +	if (!fp)
> +		return NULL;
> +
> +	while ((read = getline(&line, &len, fp)) != -1) {
> +		char *new_content = realloc(content, total_size + read + 1);
> +
> +		if (!new_content) {
> +			free(content);
> +			free(line);
> +			fclose(fp);
> +			return NULL;
> +		}
> +		content = new_content;
> +		memcpy(content + total_size, line, read);
> +		total_size += read;
> +	}
> +
> +	if (content)
> +		content[total_size] = '\0';
> +
> +	free(line);
> +	fclose(fp);
> +
> +	return content;
> +}
> +
> +int ftrace_write_file(const char *filename, const char *content)
> +{
> +	char *path;
> +	FILE *fp;
> +	int ret;
> +
> +	path = ftrace_get_path(filename);
> +	if (!path)
> +		return -1;
> +
> +	fp = fopen(path, "w");
> +	free(path);
> +
> +	if (!fp)
> +		return -1;
> +
> +	ret = fprintf(fp, "%s", content);
> +	fclose(fp);
> +
> +	return (ret > 0) ? 0 : -1;
> +}
> +
> +int ftrace_file_exists(const char *filename)
> +{
> +	char *path;
> +	int ret;
> +
> +	path = ftrace_get_path(filename);
> +	if (!path)
> +		return 0;
> +
> +	ret = (access(path, F_OK) == 0);
> +	free(path);
> +
> +	return ret;
> +}
> +
> +void ftrace_save_settings(void)
> +{
> +	if (saved_state.saved)
> +		return;
> +
> +	saved_state.trace_options = ftrace_read_file("trace_options");
> +	saved_state.tracing_on = ftrace_read_file("tracing_on");
> +	saved_state.buffer_size = ftrace_read_file("buffer_size_kb");
> +
> +	if (ftrace_file_exists("tracing_cpumask"))
> +		saved_state.tracing_cpumask = ftrace_read_file("tracing_cpumask");
> +
> +	if (ftrace_file_exists("tracing_enabled"))
> +		saved_state.tracing_enabled = ftrace_read_file("tracing_enabled");
> +
> +	if (ftrace_file_exists("stack_max_size")) {
> +		FILE *fp = fopen("/proc/sys/kernel/stack_tracer_enabled", "r");
> +
> +		if (fp) {
> +			saved_state.stack_tracer_enabled = malloc(32);
> +			if (saved_state.stack_tracer_enabled)
> +				fgets(saved_state.stack_tracer_enabled, 32, fp);
> +			fclose(fp);
> +		}
> +	}
> +
> +	if (access("/proc/sys/kernel/ftrace_enabled", F_OK) == 0) {
> +		FILE *fp = fopen("/proc/sys/kernel/ftrace_enabled", "r");
> +
> +		if (fp) {
> +			saved_state.ftrace_enabled = malloc(32);
> +			if (saved_state.ftrace_enabled)
> +				fgets(saved_state.ftrace_enabled, 32, fp);
> +			fclose(fp);
> +		}
> +	}
> +
> +	if (ftrace_file_exists("function_profile_enabled"))
> +		saved_state.function_profile_enabled = ftrace_read_file("function_profile_enabled");
> +
> +	saved_state.saved = 1;
> +}
> +
> +void ftrace_restore_settings(void)
> +{
> +	if (!saved_state.saved)
> +		return;
> +
> +	ftrace_write_file("current_tracer", "nop\n");
> +	ftrace_write_file("events/enable", "0\n");
> +
> +	if (ftrace_file_exists("tracing_max_latency"))
> +		ftrace_write_file("tracing_max_latency", "0\n");
> +
> +	if (saved_state.tracing_cpumask)
> +		ftrace_write_file("tracing_cpumask", saved_state.tracing_cpumask);
> +
> +	if (ftrace_file_exists("trace_clock"))
> +		ftrace_write_file("trace_clock", "local\n");
> +
> +	if (saved_state.function_profile_enabled)
> +		ftrace_write_file("function_profile_enabled", saved_state.function_profile_enabled);
> +
> +	if (saved_state.ftrace_enabled) {
> +		FILE *fp = fopen("/proc/sys/kernel/ftrace_enabled", "w");
> +
> +		if (fp) {
> +			fprintf(fp, "%s", saved_state.ftrace_enabled);
> +			fclose(fp);
> +		}
> +	}
> +
> +	if (saved_state.stack_tracer_enabled && ftrace_file_exists("stack_max_size")) {
> +		FILE *fp = fopen("/proc/sys/kernel/stack_tracer_enabled", "w");
> +
> +		if (fp) {
> +			fprintf(fp, "%s", saved_state.stack_tracer_enabled);
> +			fclose(fp);
> +		}
> +		ftrace_write_file("stack_max_size", "0\n");
> +	}
> +
> +	if (saved_state.buffer_size)
> +		ftrace_write_file("buffer_size_kb", saved_state.buffer_size);
> +
> +	if (saved_state.tracing_on)
> +		ftrace_write_file("tracing_on", saved_state.tracing_on);
> +
> +	if (saved_state.tracing_enabled)
> +		ftrace_write_file("tracing_enabled", saved_state.tracing_enabled);
> +
> +	if (saved_state.trace_options) {
> +		char *options = strdup(saved_state.trace_options);
> +
> +		if (options) {
> +			char *token = strtok(options, "\n");
> +
> +			while (token) {
> +				ftrace_write_file("trace_options", token);
> +				token = strtok(NULL, "\n");
> +			}
> +			free(options);
> +		}
> +	}
> +
> +	ftrace_clear_trace();
> +
> +	if (ftrace_file_exists("set_ftrace_filter"))
> +		ftrace_write_file("set_ftrace_filter", "\n");
> +}
> +
> +char **ftrace_get_available_tracers(int *count)
> +{
> +	char *path;
> +	FILE *fp;
> +	char **tracers = NULL;
> +	char *line = NULL;
> +	size_t len = 0;
> +	int n = 0;
> +	int capacity = 16;
> +
> +	path = ftrace_get_path("available_tracers");
> +	if (!path) {
> +		*count = 0;
> +		return NULL;
> +	}
> +
> +	fp = fopen(path, "r");
> +	free(path);
> +
> +	if (!fp) {
> +		*count = 0;
> +		return NULL;
> +	}
> +
> +	tracers = malloc(sizeof(char *) * capacity);
> +	if (!tracers) {
> +		fclose(fp);
> +		*count = 0;
> +		return NULL;
> +	}
> +
> +	if (getline(&line, &len, fp) != -1) {
> +		char *token;
> +		char *saveptr;
> +
> +		token = strtok_r(line, " \n", &saveptr);
> +		while (token) {
> +			if (n >= capacity) {
> +				capacity *= 2;
> +				char **new_tracers = realloc(tracers, sizeof(char *) * capacity);
> +
> +				if (!new_tracers) {
> +					while (n > 0)
> +						free(tracers[--n]);
> +					free(tracers);
> +					free(line);
> +					fclose(fp);
> +					*count = 0;
> +					return NULL;
> +				}
> +				tracers = new_tracers;
> +			}
> +
> +			tracers[n] = strdup(token);
> +			if (!tracers[n]) {
> +				while (n > 0)
> +					free(tracers[--n]);
> +				free(tracers);
> +				free(line);
> +				fclose(fp);
> +				*count = 0;
> +				return NULL;
> +			}
> +			n++;
> +			token = strtok_r(NULL, " \n", &saveptr);
> +		}

The loop here does not make any sense, we are reading the file line by
line now, the strtok_r() will not split the line into tokens, there is
going to be only a single line in the buffer.

> +	}
> +
> +	free(line);
> +	fclose(fp);
> +
> +	*count = n;
> +	return tracers;
> +}
> +
> +int ftrace_set_tracer(const char *tracer)
> +{
> +	char *path;
> +
> +	path = ftrace_get_path("current_tracer");
> +	if (!path)
> +		return -1;
> +
> +	SAFE_FILE_PRINTF(path, "%s", tracer);
> +	free(path);
> +
> +	return 0;

It's way too ugly to construct the path each time we need to write to
the tracing file.

I guess that the ideal solution is to use the SAFE_FILE_PRINTFAT() that
way we will only need to open the tracing directory with O_DIRECTORY in
the ftrace_initialize() and then we can print to all these files
relative to the dirfd without construction any paths, which can replace
all the ftrace_write_file() with SAFE_FILE_PRINTFAT().

For reading small files we can use SAFE_FILE_READAT().

> diff --git a/testcases/kernel/tracing/ftrace_test/ftrace_lib.h b/testcases/kernel/tracing/ftrace_test/ftrace_lib.h
> new file mode 100644
> index 000000000..79fdfee28
> --- /dev/null
> +++ b/testcases/kernel/tracing/ftrace_test/ftrace_lib.h
> @@ -0,0 +1,136 @@
> +/* 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>
> + */
> +
> +#ifndef FTRACE_LIB_H
> +#define FTRACE_LIB_H
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <sys/mount.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +#include <errno.h>
> +#include <limits.h>
> +
> +extern char *tracing_path;
> +extern char *debugfs_path;
> +
> +struct ftrace_saved_state {
> +	char *trace_options;
> +	char *tracing_on;
> +	char *buffer_size;
> +	char *tracing_cpumask;
> +	char *tracing_enabled;
> +	char *stack_tracer_enabled;
> +	char *ftrace_enabled;
> +	char *function_profile_enabled;
> +	int saved;
> +};
> +
> +extern struct ftrace_saved_state saved_state;
> +
> +/**
> + * ftrace_initialize - Initialize ftrace test environment
> + *
> + * Checks if debugfs is mounted, mounts it if needed, verifies tracing
> + * support, and saves current ftrace settings.
> + */
> +void ftrace_initialize(void);
> +
> +/**
> + * ftrace_cleanup - Cleanup and restore ftrace settings
> + *
> + * Restores all saved ftrace settings and unmounts debugfs if needed.
> + */
> +void ftrace_cleanup(void);
> +
> +/**
> + * ftrace_save_settings - Save current ftrace settings
> + *
> + * Saves all ftrace configuration to restore later.
> + */
> +void ftrace_save_settings(void);
> +
> +/**
> + * ftrace_restore_settings - Restore saved ftrace settings
> + *
> + * Restores ftrace configuration saved by ftrace_save_settings().
> + */
> +void ftrace_restore_settings(void);
> +
> +/**
> + * ftrace_get_path - Get full path to a tracing file
> + * @filename: Name of the file in tracing directory
> + *
> + * Return: Allocated string with full path (caller must free)
> + */
> +char *ftrace_get_path(const char *filename);
> +
> +/**
> + * ftrace_read_file - Read content from a tracing file
> + * @filename: Name of the file in tracing directory
> + *
> + * Return: Allocated string with file content (caller must free)
> + */
> +char *ftrace_read_file(const char *filename);
> +
> +/**
> + * ftrace_write_file - Write content to a tracing file
> + * @filename: Name of the file in tracing directory
> + * @content: Content to write
> + *
> + * Return: 0 on success, -1 on failure
> + */
> +int ftrace_write_file(const char *filename, const char *content);
> +
> +/**
> + * ftrace_file_exists - Check if a tracing file exists
> + * @filename: Name of the file in tracing directory
> + *
> + * Return: 1 if exists, 0 otherwise
> + */
> +int ftrace_file_exists(const char *filename);
> +
> +/**
> + * ftrace_get_available_tracers - Get list of available tracers
> + * @count: Pointer to store number of tracers
> + *
> + * Return: Array of tracer names (caller must free)
> + */
> +char **ftrace_get_available_tracers(int *count);
> +
> +/**
> + * ftrace_set_tracer - Set current tracer
> + * @tracer: Name of the tracer to set
> + *
> + * Return: 0 on success, -1 on failure
> + */
> +int ftrace_set_tracer(const char *tracer);
> +
> +/**
> + * ftrace_clear_trace - Clear the trace buffer
> + */
> +void ftrace_clear_trace(void);
> +
> +/**
> + * ftrace_enable_tracing - Enable tracing
> + */
> +void ftrace_enable_tracing(void);
> +
> +/**
> + * ftrace_disable_tracing - Disable tracing
> + */
> +void ftrace_disable_tracing(void);
> +
> +#endif /* FTRACE_LIB_H */
> +
> -- 
> 2.50.1

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

  parent reply	other threads:[~2026-06-10  9:31 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-09  4:16 [LTP] [PATCH v6 0/5] ftrace: Convert shell tests to C Praveen K Pandey
2026-06-09  4:16 ` [LTP] [PATCH v6 1/5] ftrace: Add common library for C implementation Praveen K Pandey
2026-06-09  5:14   ` [LTP] " linuxtestproject.agent
2026-06-10  9:31   ` Cyril Hrubis [this message]
2026-06-09  4:16 ` [LTP] [PATCH v6 2/5] ftrace: Convert ftrace_regression01.sh to C Praveen K Pandey
2026-06-09  4:16 ` [LTP] [PATCH v6 3/5] ftrace: Convert ftrace_regression02.sh " Praveen K Pandey
2026-06-09  4:16 ` [LTP] [PATCH v6 4/5] ftrace: Convert ftrace_stress_test.sh " Praveen K Pandey
2026-06-09  4:16 ` [LTP] [PATCH v6 5/5] ftrace: Remove obsolete shell test files Praveen K Pandey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aiku3VRfJZS4dsxY@yuki.lan \
    --to=chrubis@suse.cz \
    --cc=ltp@lists.linux.it \
    --cc=praveen@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox