Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'trace-v6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull more tracing updates from Steven Rostedt:

- Make buffer_percent read/write.

The buffer_percent file is how users can state how long to block on
the tracing buffer depending on how much is in the buffer. When it
hits the "buffer_percent" it will wake the task waiting on the
buffer. For some reason it was set to read-only.

This was not noticed because testing was done as root without
SELinux, but with SELinux it will prevent even root to write to it
without having CAP_DAC_OVERRIDE.

- The "touched_functions" was added this merge window, but one of the
reasons for adding it was not implemented.

That was to show what functions were not only touched, but had either
a direct trampoline attached to it, or a kprobe or live kernel
patching that can "hijack" the function to run a different function.
The point is to know if there's functions in the kernel that may not
be behaving as the kernel code shows. This can be used for debugging.

TODO: Add this information to kernel oops too.

* tag 'trace-v6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
ftrace: Add MODIFIED flag to show if IPMODIFY or direct was attached
tracing: Fix permissions for the buffer_percent file

+38 -5
+25
Documentation/trace/ftrace.rst
··· 350 350 an 'I' will be displayed on the same line as the function that 351 351 can be overridden. 352 352 353 + If a non ftrace trampoline is attached (BPF) a 'D' will be displayed. 354 + Note, normal ftrace trampolines can also be attached, but only one 355 + "direct" trampoline can be attached to a given function at a time. 356 + 357 + Some architectures can not call direct trampolines, but instead have 358 + the ftrace ops function located above the function entry point. In 359 + such cases an 'O' will be displayed. 360 + 361 + If a function had either the "ip modify" or a "direct" call attached to 362 + it in the past, a 'M' will be shown. This flag is never cleared. It is 363 + used to know if a function was every modified by the ftrace infrastructure, 364 + and can be used for debugging. 365 + 353 366 If the architecture supports it, it will also show what callback 354 367 is being directly called by the function. If the count is greater 355 368 than 1 it most likely will be ftrace_ops_list_func(). ··· 371 358 specific to the callback and which is not the standard trampoline, 372 359 its address will be printed as well as the function that the 373 360 trampoline calls. 361 + 362 + touched_functions: 363 + 364 + This file contains all the functions that ever had a function callback 365 + to it via the ftrace infrastructure. It has the same format as 366 + enabled_functions but shows all functions that have every been 367 + traced. 368 + 369 + To see any function that has every been modified by "ip modify" or a 370 + direct trampoline, one can perform the following command: 371 + 372 + grep ' M ' /sys/kernel/tracing/touched_functions 374 373 375 374 function_profile_enabled: 376 375
+3 -1
include/linux/ftrace.h
··· 549 549 * CALL_OPS - the record can use callsite-specific ops 550 550 * CALL_OPS_EN - the function is set up to use callsite-specific ops 551 551 * TOUCHED - A callback was added since boot up 552 + * MODIFIED - The function had IPMODIFY or DIRECT attached to it 552 553 * 553 554 * When a new ftrace_ops is registered and wants a function to save 554 555 * pt_regs, the rec->flags REGS is set. When the function has been ··· 570 569 FTRACE_FL_CALL_OPS = (1UL << 22), 571 570 FTRACE_FL_CALL_OPS_EN = (1UL << 21), 572 571 FTRACE_FL_TOUCHED = (1UL << 20), 572 + FTRACE_FL_MODIFIED = (1UL << 19), 573 573 }; 574 574 575 - #define FTRACE_REF_MAX_SHIFT 20 575 + #define FTRACE_REF_MAX_SHIFT 19 576 576 #define FTRACE_REF_MAX ((1UL << FTRACE_REF_MAX_SHIFT) - 1) 577 577 578 578 #define ftrace_rec_count(rec) ((rec)->flags & FTRACE_REF_MAX)
+9 -3
kernel/trace/ftrace.c
··· 46 46 #include "trace_stat.h" 47 47 48 48 /* Flags that do not get reset */ 49 - #define FTRACE_NOCLEAR_FLAGS (FTRACE_FL_DISABLED | FTRACE_FL_TOUCHED) 49 + #define FTRACE_NOCLEAR_FLAGS (FTRACE_FL_DISABLED | FTRACE_FL_TOUCHED | \ 50 + FTRACE_FL_MODIFIED) 50 51 51 52 #define FTRACE_INVALID_FUNCTION "__ftrace_invalid_address__" 52 53 ··· 2274 2273 rec->flags &= ~FTRACE_FL_TRAMP_EN; 2275 2274 } 2276 2275 2276 + /* Keep track of anything that modifies the function */ 2277 + if (rec->flags & (FTRACE_FL_DIRECT | FTRACE_FL_IPMODIFY)) 2278 + rec->flags |= FTRACE_FL_MODIFIED; 2279 + 2277 2280 if (flag & FTRACE_FL_DIRECT) { 2278 2281 /* 2279 2282 * If there's only one user (direct_ops helper) ··· 3871 3866 if (iter->flags & (FTRACE_ITER_ENABLED | FTRACE_ITER_TOUCHED)) { 3872 3867 struct ftrace_ops *ops; 3873 3868 3874 - seq_printf(m, " (%ld)%s%s%s%s", 3869 + seq_printf(m, " (%ld)%s%s%s%s%s", 3875 3870 ftrace_rec_count(rec), 3876 3871 rec->flags & FTRACE_FL_REGS ? " R" : " ", 3877 3872 rec->flags & FTRACE_FL_IPMODIFY ? " I" : " ", 3878 3873 rec->flags & FTRACE_FL_DIRECT ? " D" : " ", 3879 - rec->flags & FTRACE_FL_CALL_OPS ? " O" : " "); 3874 + rec->flags & FTRACE_FL_CALL_OPS ? " O" : " ", 3875 + rec->flags & FTRACE_FL_MODIFIED ? " M " : " "); 3880 3876 if (rec->flags & FTRACE_FL_TRAMP_EN) { 3881 3877 ops = ftrace_find_tramp_ops_any(rec); 3882 3878 if (ops) {
+1 -1
kernel/trace/trace.c
··· 9661 9661 9662 9662 tr->buffer_percent = 50; 9663 9663 9664 - trace_create_file("buffer_percent", TRACE_MODE_READ, d_tracer, 9664 + trace_create_file("buffer_percent", TRACE_MODE_WRITE, d_tracer, 9665 9665 tr, &buffer_percent_fops); 9666 9666 9667 9667 create_trace_options_dir(tr);