mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
tracing: Move pid filtering into trace_pid.c
The trace.c file was a dumping ground for most tracing code. Start organizing it better by moving various functions out into their own files. Move the PID filtering functions from trace.c into its own trace_pid.c file. Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Andrew Morton <akpm@linux-foundation.org> Link: https://patch.msgid.link/20260208032450.998330662@kernel.org Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
27931ee8f4
commit
98021e37d6
3 changed files with 247 additions and 242 deletions
|
|
@ -68,6 +68,7 @@ obj-$(CONFIG_TRACING) += trace_output.o
|
|||
obj-$(CONFIG_TRACING) += trace_seq.o
|
||||
obj-$(CONFIG_TRACING) += trace_stat.o
|
||||
obj-$(CONFIG_TRACING) += trace_printk.o
|
||||
obj-$(CONFIG_TRACING) += trace_pid.o
|
||||
obj-$(CONFIG_TRACING) += pid_list.o
|
||||
obj-$(CONFIG_TRACING_MAP) += tracing_map.o
|
||||
obj-$(CONFIG_PREEMPTIRQ_DELAY_TEST) += preemptirq_delay_test.o
|
||||
|
|
|
|||
|
|
@ -637,248 +637,6 @@ int tracing_check_open_get_tr(struct trace_array *tr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_find_filtered_pid - check if a pid exists in a filtered_pid list
|
||||
* @filtered_pids: The list of pids to check
|
||||
* @search_pid: The PID to find in @filtered_pids
|
||||
*
|
||||
* Returns true if @search_pid is found in @filtered_pids, and false otherwise.
|
||||
*/
|
||||
bool
|
||||
trace_find_filtered_pid(struct trace_pid_list *filtered_pids, pid_t search_pid)
|
||||
{
|
||||
return trace_pid_list_is_set(filtered_pids, search_pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_ignore_this_task - should a task be ignored for tracing
|
||||
* @filtered_pids: The list of pids to check
|
||||
* @filtered_no_pids: The list of pids not to be traced
|
||||
* @task: The task that should be ignored if not filtered
|
||||
*
|
||||
* Checks if @task should be traced or not from @filtered_pids.
|
||||
* Returns true if @task should *NOT* be traced.
|
||||
* Returns false if @task should be traced.
|
||||
*/
|
||||
bool
|
||||
trace_ignore_this_task(struct trace_pid_list *filtered_pids,
|
||||
struct trace_pid_list *filtered_no_pids,
|
||||
struct task_struct *task)
|
||||
{
|
||||
/*
|
||||
* If filtered_no_pids is not empty, and the task's pid is listed
|
||||
* in filtered_no_pids, then return true.
|
||||
* Otherwise, if filtered_pids is empty, that means we can
|
||||
* trace all tasks. If it has content, then only trace pids
|
||||
* within filtered_pids.
|
||||
*/
|
||||
|
||||
return (filtered_pids &&
|
||||
!trace_find_filtered_pid(filtered_pids, task->pid)) ||
|
||||
(filtered_no_pids &&
|
||||
trace_find_filtered_pid(filtered_no_pids, task->pid));
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_filter_add_remove_task - Add or remove a task from a pid_list
|
||||
* @pid_list: The list to modify
|
||||
* @self: The current task for fork or NULL for exit
|
||||
* @task: The task to add or remove
|
||||
*
|
||||
* If adding a task, if @self is defined, the task is only added if @self
|
||||
* is also included in @pid_list. This happens on fork and tasks should
|
||||
* only be added when the parent is listed. If @self is NULL, then the
|
||||
* @task pid will be removed from the list, which would happen on exit
|
||||
* of a task.
|
||||
*/
|
||||
void trace_filter_add_remove_task(struct trace_pid_list *pid_list,
|
||||
struct task_struct *self,
|
||||
struct task_struct *task)
|
||||
{
|
||||
if (!pid_list)
|
||||
return;
|
||||
|
||||
/* For forks, we only add if the forking task is listed */
|
||||
if (self) {
|
||||
if (!trace_find_filtered_pid(pid_list, self->pid))
|
||||
return;
|
||||
}
|
||||
|
||||
/* "self" is set for forks, and NULL for exits */
|
||||
if (self)
|
||||
trace_pid_list_set(pid_list, task->pid);
|
||||
else
|
||||
trace_pid_list_clear(pid_list, task->pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_pid_next - Used for seq_file to get to the next pid of a pid_list
|
||||
* @pid_list: The pid list to show
|
||||
* @v: The last pid that was shown (+1 the actual pid to let zero be displayed)
|
||||
* @pos: The position of the file
|
||||
*
|
||||
* This is used by the seq_file "next" operation to iterate the pids
|
||||
* listed in a trace_pid_list structure.
|
||||
*
|
||||
* Returns the pid+1 as we want to display pid of zero, but NULL would
|
||||
* stop the iteration.
|
||||
*/
|
||||
void *trace_pid_next(struct trace_pid_list *pid_list, void *v, loff_t *pos)
|
||||
{
|
||||
long pid = (unsigned long)v;
|
||||
unsigned int next;
|
||||
|
||||
(*pos)++;
|
||||
|
||||
/* pid already is +1 of the actual previous bit */
|
||||
if (trace_pid_list_next(pid_list, pid, &next) < 0)
|
||||
return NULL;
|
||||
|
||||
pid = next;
|
||||
|
||||
/* Return pid + 1 to allow zero to be represented */
|
||||
return (void *)(pid + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_pid_start - Used for seq_file to start reading pid lists
|
||||
* @pid_list: The pid list to show
|
||||
* @pos: The position of the file
|
||||
*
|
||||
* This is used by seq_file "start" operation to start the iteration
|
||||
* of listing pids.
|
||||
*
|
||||
* Returns the pid+1 as we want to display pid of zero, but NULL would
|
||||
* stop the iteration.
|
||||
*/
|
||||
void *trace_pid_start(struct trace_pid_list *pid_list, loff_t *pos)
|
||||
{
|
||||
unsigned long pid;
|
||||
unsigned int first;
|
||||
loff_t l = 0;
|
||||
|
||||
if (trace_pid_list_first(pid_list, &first) < 0)
|
||||
return NULL;
|
||||
|
||||
pid = first;
|
||||
|
||||
/* Return pid + 1 so that zero can be the exit value */
|
||||
for (pid++; pid && l < *pos;
|
||||
pid = (unsigned long)trace_pid_next(pid_list, (void *)pid, &l))
|
||||
;
|
||||
return (void *)pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_pid_show - show the current pid in seq_file processing
|
||||
* @m: The seq_file structure to write into
|
||||
* @v: A void pointer of the pid (+1) value to display
|
||||
*
|
||||
* Can be directly used by seq_file operations to display the current
|
||||
* pid value.
|
||||
*/
|
||||
int trace_pid_show(struct seq_file *m, void *v)
|
||||
{
|
||||
unsigned long pid = (unsigned long)v - 1;
|
||||
|
||||
seq_printf(m, "%lu\n", pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 128 should be much more than enough */
|
||||
#define PID_BUF_SIZE 127
|
||||
|
||||
int trace_pid_write(struct trace_pid_list *filtered_pids,
|
||||
struct trace_pid_list **new_pid_list,
|
||||
const char __user *ubuf, size_t cnt)
|
||||
{
|
||||
struct trace_pid_list *pid_list;
|
||||
struct trace_parser parser;
|
||||
unsigned long val;
|
||||
int nr_pids = 0;
|
||||
ssize_t read = 0;
|
||||
ssize_t ret;
|
||||
loff_t pos;
|
||||
pid_t pid;
|
||||
|
||||
if (trace_parser_get_init(&parser, PID_BUF_SIZE + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Always recreate a new array. The write is an all or nothing
|
||||
* operation. Always create a new array when adding new pids by
|
||||
* the user. If the operation fails, then the current list is
|
||||
* not modified.
|
||||
*/
|
||||
pid_list = trace_pid_list_alloc();
|
||||
if (!pid_list) {
|
||||
trace_parser_put(&parser);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (filtered_pids) {
|
||||
/* copy the current bits to the new max */
|
||||
ret = trace_pid_list_first(filtered_pids, &pid);
|
||||
while (!ret) {
|
||||
ret = trace_pid_list_set(pid_list, pid);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = trace_pid_list_next(filtered_pids, pid + 1, &pid);
|
||||
nr_pids++;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
while (cnt > 0) {
|
||||
|
||||
pos = 0;
|
||||
|
||||
ret = trace_get_user(&parser, ubuf, cnt, &pos);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
read += ret;
|
||||
ubuf += ret;
|
||||
cnt -= ret;
|
||||
|
||||
if (!trace_parser_loaded(&parser))
|
||||
break;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (kstrtoul(parser.buffer, 0, &val))
|
||||
break;
|
||||
|
||||
pid = (pid_t)val;
|
||||
|
||||
if (trace_pid_list_set(pid_list, pid) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
nr_pids++;
|
||||
|
||||
trace_parser_clear(&parser);
|
||||
ret = 0;
|
||||
}
|
||||
out:
|
||||
trace_parser_put(&parser);
|
||||
|
||||
if (ret < 0) {
|
||||
trace_pid_list_free(pid_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!nr_pids) {
|
||||
/* Cleared the list of pids */
|
||||
trace_pid_list_free(pid_list);
|
||||
pid_list = NULL;
|
||||
}
|
||||
|
||||
*new_pid_list = pid_list;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
static u64 buffer_ftrace_now(struct array_buffer *buf, int cpu)
|
||||
{
|
||||
u64 ts;
|
||||
|
|
|
|||
246
kernel/trace/trace_pid.c
Normal file
246
kernel/trace/trace_pid.c
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
/**
|
||||
* trace_find_filtered_pid - check if a pid exists in a filtered_pid list
|
||||
* @filtered_pids: The list of pids to check
|
||||
* @search_pid: The PID to find in @filtered_pids
|
||||
*
|
||||
* Returns true if @search_pid is found in @filtered_pids, and false otherwise.
|
||||
*/
|
||||
bool
|
||||
trace_find_filtered_pid(struct trace_pid_list *filtered_pids, pid_t search_pid)
|
||||
{
|
||||
return trace_pid_list_is_set(filtered_pids, search_pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_ignore_this_task - should a task be ignored for tracing
|
||||
* @filtered_pids: The list of pids to check
|
||||
* @filtered_no_pids: The list of pids not to be traced
|
||||
* @task: The task that should be ignored if not filtered
|
||||
*
|
||||
* Checks if @task should be traced or not from @filtered_pids.
|
||||
* Returns true if @task should *NOT* be traced.
|
||||
* Returns false if @task should be traced.
|
||||
*/
|
||||
bool
|
||||
trace_ignore_this_task(struct trace_pid_list *filtered_pids,
|
||||
struct trace_pid_list *filtered_no_pids,
|
||||
struct task_struct *task)
|
||||
{
|
||||
/*
|
||||
* If filtered_no_pids is not empty, and the task's pid is listed
|
||||
* in filtered_no_pids, then return true.
|
||||
* Otherwise, if filtered_pids is empty, that means we can
|
||||
* trace all tasks. If it has content, then only trace pids
|
||||
* within filtered_pids.
|
||||
*/
|
||||
|
||||
return (filtered_pids &&
|
||||
!trace_find_filtered_pid(filtered_pids, task->pid)) ||
|
||||
(filtered_no_pids &&
|
||||
trace_find_filtered_pid(filtered_no_pids, task->pid));
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_filter_add_remove_task - Add or remove a task from a pid_list
|
||||
* @pid_list: The list to modify
|
||||
* @self: The current task for fork or NULL for exit
|
||||
* @task: The task to add or remove
|
||||
*
|
||||
* If adding a task, if @self is defined, the task is only added if @self
|
||||
* is also included in @pid_list. This happens on fork and tasks should
|
||||
* only be added when the parent is listed. If @self is NULL, then the
|
||||
* @task pid will be removed from the list, which would happen on exit
|
||||
* of a task.
|
||||
*/
|
||||
void trace_filter_add_remove_task(struct trace_pid_list *pid_list,
|
||||
struct task_struct *self,
|
||||
struct task_struct *task)
|
||||
{
|
||||
if (!pid_list)
|
||||
return;
|
||||
|
||||
/* For forks, we only add if the forking task is listed */
|
||||
if (self) {
|
||||
if (!trace_find_filtered_pid(pid_list, self->pid))
|
||||
return;
|
||||
}
|
||||
|
||||
/* "self" is set for forks, and NULL for exits */
|
||||
if (self)
|
||||
trace_pid_list_set(pid_list, task->pid);
|
||||
else
|
||||
trace_pid_list_clear(pid_list, task->pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_pid_next - Used for seq_file to get to the next pid of a pid_list
|
||||
* @pid_list: The pid list to show
|
||||
* @v: The last pid that was shown (+1 the actual pid to let zero be displayed)
|
||||
* @pos: The position of the file
|
||||
*
|
||||
* This is used by the seq_file "next" operation to iterate the pids
|
||||
* listed in a trace_pid_list structure.
|
||||
*
|
||||
* Returns the pid+1 as we want to display pid of zero, but NULL would
|
||||
* stop the iteration.
|
||||
*/
|
||||
void *trace_pid_next(struct trace_pid_list *pid_list, void *v, loff_t *pos)
|
||||
{
|
||||
long pid = (unsigned long)v;
|
||||
unsigned int next;
|
||||
|
||||
(*pos)++;
|
||||
|
||||
/* pid already is +1 of the actual previous bit */
|
||||
if (trace_pid_list_next(pid_list, pid, &next) < 0)
|
||||
return NULL;
|
||||
|
||||
pid = next;
|
||||
|
||||
/* Return pid + 1 to allow zero to be represented */
|
||||
return (void *)(pid + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_pid_start - Used for seq_file to start reading pid lists
|
||||
* @pid_list: The pid list to show
|
||||
* @pos: The position of the file
|
||||
*
|
||||
* This is used by seq_file "start" operation to start the iteration
|
||||
* of listing pids.
|
||||
*
|
||||
* Returns the pid+1 as we want to display pid of zero, but NULL would
|
||||
* stop the iteration.
|
||||
*/
|
||||
void *trace_pid_start(struct trace_pid_list *pid_list, loff_t *pos)
|
||||
{
|
||||
unsigned long pid;
|
||||
unsigned int first;
|
||||
loff_t l = 0;
|
||||
|
||||
if (trace_pid_list_first(pid_list, &first) < 0)
|
||||
return NULL;
|
||||
|
||||
pid = first;
|
||||
|
||||
/* Return pid + 1 so that zero can be the exit value */
|
||||
for (pid++; pid && l < *pos;
|
||||
pid = (unsigned long)trace_pid_next(pid_list, (void *)pid, &l))
|
||||
;
|
||||
return (void *)pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_pid_show - show the current pid in seq_file processing
|
||||
* @m: The seq_file structure to write into
|
||||
* @v: A void pointer of the pid (+1) value to display
|
||||
*
|
||||
* Can be directly used by seq_file operations to display the current
|
||||
* pid value.
|
||||
*/
|
||||
int trace_pid_show(struct seq_file *m, void *v)
|
||||
{
|
||||
unsigned long pid = (unsigned long)v - 1;
|
||||
|
||||
seq_printf(m, "%lu\n", pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 128 should be much more than enough */
|
||||
#define PID_BUF_SIZE 127
|
||||
|
||||
int trace_pid_write(struct trace_pid_list *filtered_pids,
|
||||
struct trace_pid_list **new_pid_list,
|
||||
const char __user *ubuf, size_t cnt)
|
||||
{
|
||||
struct trace_pid_list *pid_list;
|
||||
struct trace_parser parser;
|
||||
unsigned long val;
|
||||
int nr_pids = 0;
|
||||
ssize_t read = 0;
|
||||
ssize_t ret;
|
||||
loff_t pos;
|
||||
pid_t pid;
|
||||
|
||||
if (trace_parser_get_init(&parser, PID_BUF_SIZE + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Always recreate a new array. The write is an all or nothing
|
||||
* operation. Always create a new array when adding new pids by
|
||||
* the user. If the operation fails, then the current list is
|
||||
* not modified.
|
||||
*/
|
||||
pid_list = trace_pid_list_alloc();
|
||||
if (!pid_list) {
|
||||
trace_parser_put(&parser);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (filtered_pids) {
|
||||
/* copy the current bits to the new max */
|
||||
ret = trace_pid_list_first(filtered_pids, &pid);
|
||||
while (!ret) {
|
||||
ret = trace_pid_list_set(pid_list, pid);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = trace_pid_list_next(filtered_pids, pid + 1, &pid);
|
||||
nr_pids++;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
while (cnt > 0) {
|
||||
|
||||
pos = 0;
|
||||
|
||||
ret = trace_get_user(&parser, ubuf, cnt, &pos);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
read += ret;
|
||||
ubuf += ret;
|
||||
cnt -= ret;
|
||||
|
||||
if (!trace_parser_loaded(&parser))
|
||||
break;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (kstrtoul(parser.buffer, 0, &val))
|
||||
break;
|
||||
|
||||
pid = (pid_t)val;
|
||||
|
||||
if (trace_pid_list_set(pid_list, pid) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
nr_pids++;
|
||||
|
||||
trace_parser_clear(&parser);
|
||||
ret = 0;
|
||||
}
|
||||
out:
|
||||
trace_parser_put(&parser);
|
||||
|
||||
if (ret < 0) {
|
||||
trace_pid_list_free(pid_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!nr_pids) {
|
||||
/* Cleared the list of pids */
|
||||
trace_pid_list_free(pid_list);
|
||||
pid_list = NULL;
|
||||
}
|
||||
|
||||
*new_pid_list = pid_list;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue