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

Merge tag 'trace-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing updates from Steven Rostedt:
"Updates for tracing and bootconfig:

- Add support for "bool" type in synthetic events

- Add per instance tracing for bootconfig

- Support perf-style return probe ("SYMBOL%return") in kprobes and
uprobes

- Allow for kprobes to be enabled earlier in boot up

- Added tracepoint helper function to allow testing if tracepoints
are enabled in headers

- Synthetic events can now have dynamic strings (variable length)

- Various fixes and cleanups"

* tag 'trace-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (58 commits)
tracing: support "bool" type in synthetic trace events
selftests/ftrace: Add test case for synthetic event syntax errors
tracing: Handle synthetic event array field type checking correctly
selftests/ftrace: Change synthetic event name for inter-event-combined test
tracing: Add synthetic event error logging
tracing: Check that the synthetic event and field names are legal
tracing: Move is_good_name() from trace_probe.h to trace.h
tracing: Don't show dynamic string internals in synthetic event description
tracing: Fix some typos in comments
tracing/boot: Add ftrace.instance.*.alloc_snapshot option
tracing: Fix race in trace_open and buffer resize call
tracing: Check return value of __create_val_fields() before using its result
tracing: Fix synthetic print fmt check for use of __get_str()
tracing: Remove a pointless assignment
ftrace: ftrace_global_list is renamed to ftrace_ops_list
ftrace: Format variable declarations of ftrace_allocate_records
ftrace: Simplify the calculation of page number for ftrace_page->records
ftrace: Simplify the dyn_ftrace->flags macro
ftrace: Simplify the hash calculation
ftrace: Use fls() to get the bits for dup_hash()
...

+1705 -332
+38
Documentation/trace/boottime-trace.rst
··· 61 61 ftrace.[instance.INSTANCE.]options = OPT1[, OPT2[...]] 62 62 Enable given ftrace options. 63 63 64 + ftrace.[instance.INSTANCE.]tracing_on = 0|1 65 + Enable/Disable tracing on this instance when starting boot-time tracing. 66 + (you can enable it by the "traceon" event trigger action) 67 + 64 68 ftrace.[instance.INSTANCE.]trace_clock = CLOCK 65 69 Set given CLOCK to ftrace's trace_clock. 66 70 ··· 120 116 take care for event name conflict. 121 117 122 118 119 + When to Start 120 + ============= 121 + 122 + All boot-time tracing options starting with ``ftrace`` will be enabled at the 123 + end of core_initcall. This means you can trace the events from postcore_initcall. 124 + Most of the subsystems and architecture dependent drivers will be initialized 125 + after that (arch_initcall or subsys_initcall). Thus, you can trace those with 126 + boot-time tracing. 127 + If you want to trace events before core_initcall, you can use the options 128 + starting with ``kernel``. Some of them will be enabled eariler than the initcall 129 + processing (for example,. ``kernel.ftrace=function`` and ``kernel.trace_event`` 130 + will start before the initcall.) 131 + 132 + 123 133 Examples 124 134 ======== 125 135 ··· 181 163 182 164 The instance node also accepts event nodes so that each instance 183 165 can customize its event tracing. 166 + 167 + With the trigger action and kprobes, you can trace function-graph while 168 + a function is called. For example, this will trace all function calls in 169 + the pci_proc_init():: 170 + 171 + ftrace { 172 + tracing_on = 0 173 + tracer = function_graph 174 + event.kprobes { 175 + start_event { 176 + probes = "pci_proc_init" 177 + actions = "traceon" 178 + } 179 + end_event { 180 + probes = "pci_proc_init%return" 181 + actions = "traceoff" 182 + } 183 + } 184 + } 185 + 184 186 185 187 This boot-time tracing also supports ftrace kernel parameters via boot 186 188 config.
+13 -2
Documentation/trace/events.rst
··· 589 589 { .type = "int", .name = "my_int_field" }, 590 590 }; 591 591 592 - See synth_field_size() for available types. If field_name contains [n] 593 - the field is considered to be an array. 592 + See synth_field_size() for available types. 593 + 594 + If field_name contains [n], the field is considered to be a static array. 595 + 596 + If field_names contains[] (no subscript), the field is considered to 597 + be a dynamic array, which will only take as much space in the event as 598 + is required to hold the array. 599 + 600 + Because space for an event is reserved before assigning field values 601 + to the event, using dynamic arrays implies that the piecewise 602 + in-kernel API described below can't be used with dynamic arrays. The 603 + other non-piecewise in-kernel APIs can, however, be used with dynamic 604 + arrays. 594 605 595 606 If the event is created from within a module, a pointer to the module 596 607 must be passed to synth_event_create(). This will ensure that the
+18
Documentation/trace/histogram.rst
··· 1776 1776 variables and their types, which can be any valid field type, 1777 1777 separated by semicolons, to the tracing/synthetic_events file. 1778 1778 1779 + See synth_field_size() for available types. 1780 + 1781 + If field_name contains [n], the field is considered to be a static array. 1782 + 1783 + If field_names contains[] (no subscript), the field is considered to 1784 + be a dynamic array, which will only take as much space in the event as 1785 + is required to hold the array. 1786 + 1787 + A string field can be specified using either the static notation: 1788 + 1789 + char name[32]; 1790 + 1791 + Or the dynamic: 1792 + 1793 + char name[]; 1794 + 1795 + The size limit for either is 256. 1796 + 1779 1797 For instance, the following creates a new event named 'wakeup_latency' 1780 1798 with 3 fields: lat, pid, and prio. Each of those fields is simply a 1781 1799 variable reference to a variable on another event::
+2
Documentation/trace/kprobetrace.rst
··· 30 30 31 31 p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe 32 32 r[MAXACTIVE][:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe 33 + p:[GRP/]EVENT] [MOD:]SYM[+0]%return [FETCHARGS] : Set a return probe 33 34 -:[GRP/]EVENT : Clear a probe 34 35 35 36 GRP : Group name. If omitted, use "kprobes" for it. ··· 38 37 based on SYM+offs or MEMADDR. 39 38 MOD : Module name which has given SYM. 40 39 SYM[+offs] : Symbol+offset where the probe is inserted. 40 + SYM%return : Return address of the symbol 41 41 MEMADDR : Address where the probe is inserted. 42 42 MAXACTIVE : Maximum number of instances of the specified function that 43 43 can be probed simultaneously, or 0 for the default value
+27
Documentation/trace/tracepoints.rst
··· 146 146 define tracepoints. Check http://lwn.net/Articles/379903, 147 147 http://lwn.net/Articles/381064 and http://lwn.net/Articles/383362 148 148 for a series of articles with more details. 149 + 150 + If you require calling a tracepoint from a header file, it is not 151 + recommended to call one directly or to use the trace_<tracepoint>_enabled() 152 + function call, as tracepoints in header files can have side effects if a 153 + header is included from a file that has CREATE_TRACE_POINTS set, as 154 + well as the trace_<tracepoint>() is not that small of an inline 155 + and can bloat the kernel if used by other inlined functions. Instead, 156 + include tracepoint-defs.h and use tracepoint_enabled(). 157 + 158 + In a C file:: 159 + 160 + void do_trace_foo_bar_wrapper(args) 161 + { 162 + trace_foo_bar(args); 163 + } 164 + 165 + In the header file:: 166 + 167 + DECLARE_TRACEPOINT(foo_bar); 168 + 169 + static inline void some_inline_function() 170 + { 171 + [..] 172 + if (tracepoint_enabled(foo_bar)) 173 + do_trace_foo_bar_wrapper(args); 174 + [..] 175 + }
+2
Documentation/trace/uprobetracer.rst
··· 28 28 29 29 p[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] : Set a uprobe 30 30 r[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] : Set a return uprobe (uretprobe) 31 + p[:[GRP/]EVENT] PATH:OFFSET%return [FETCHARGS] : Set a return uprobe (uretprobe) 31 32 -:[GRP/]EVENT : Clear uprobe or uretprobe event 32 33 33 34 GRP : Group name. If omitted, "uprobes" is the default value. ··· 36 35 on PATH+OFFSET. 37 36 PATH : Path to an executable or a library. 38 37 OFFSET : Offset where the probe is inserted. 38 + OFFSET%return : Offset where the return probe is inserted. 39 39 40 40 FETCHARGS : Arguments. Each probe can have up to 128 args. 41 41 %REG : Fetch register REG
+1
MAINTAINERS
··· 6626 6626 F: include/linux/bootconfig.h 6627 6627 F: lib/bootconfig.c 6628 6628 F: tools/bootconfig/* 6629 + F: tools/bootconfig/scripts/* 6629 6630 6630 6631 EXYNOS DP DRIVER 6631 6632 M: Jingoo Han <jingoohan1@gmail.com>
+9 -11
arch/x86/include/asm/msr.h
··· 60 60 #define EAX_EDX_RET(val, low, high) "=A" (val) 61 61 #endif 62 62 63 - #ifdef CONFIG_TRACEPOINTS 64 63 /* 65 64 * Be very careful with includes. This header is prone to include loops. 66 65 */ 67 66 #include <asm/atomic.h> 68 67 #include <linux/tracepoint-defs.h> 69 68 70 - extern struct tracepoint __tracepoint_read_msr; 71 - extern struct tracepoint __tracepoint_write_msr; 72 - extern struct tracepoint __tracepoint_rdpmc; 73 - #define msr_tracepoint_active(t) static_key_false(&(t).key) 69 + #ifdef CONFIG_TRACEPOINTS 70 + DECLARE_TRACEPOINT(read_msr); 71 + DECLARE_TRACEPOINT(write_msr); 72 + DECLARE_TRACEPOINT(rdpmc); 74 73 extern void do_trace_write_msr(unsigned int msr, u64 val, int failed); 75 74 extern void do_trace_read_msr(unsigned int msr, u64 val, int failed); 76 75 extern void do_trace_rdpmc(unsigned int msr, u64 val, int failed); 77 76 #else 78 - #define msr_tracepoint_active(t) false 79 77 static inline void do_trace_write_msr(unsigned int msr, u64 val, int failed) {} 80 78 static inline void do_trace_read_msr(unsigned int msr, u64 val, int failed) {} 81 79 static inline void do_trace_rdpmc(unsigned int msr, u64 val, int failed) {} ··· 126 128 127 129 val = __rdmsr(msr); 128 130 129 - if (msr_tracepoint_active(__tracepoint_read_msr)) 131 + if (tracepoint_enabled(read_msr)) 130 132 do_trace_read_msr(msr, val, 0); 131 133 132 134 return val; ··· 148 150 _ASM_EXTABLE(2b, 3b) 149 151 : [err] "=r" (*err), EAX_EDX_RET(val, low, high) 150 152 : "c" (msr), [fault] "i" (-EIO)); 151 - if (msr_tracepoint_active(__tracepoint_read_msr)) 153 + if (tracepoint_enabled(read_msr)) 152 154 do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), *err); 153 155 return EAX_EDX_VAL(val, low, high); 154 156 } ··· 159 161 { 160 162 __wrmsr(msr, low, high); 161 163 162 - if (msr_tracepoint_active(__tracepoint_write_msr)) 164 + if (tracepoint_enabled(write_msr)) 163 165 do_trace_write_msr(msr, ((u64)high << 32 | low), 0); 164 166 } 165 167 ··· 179 181 : "c" (msr), "0" (low), "d" (high), 180 182 [fault] "i" (-EIO) 181 183 : "memory"); 182 - if (msr_tracepoint_active(__tracepoint_write_msr)) 184 + if (tracepoint_enabled(write_msr)) 183 185 do_trace_write_msr(msr, ((u64)high << 32 | low), err); 184 186 return err; 185 187 } ··· 246 248 DECLARE_ARGS(val, low, high); 247 249 248 250 asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter)); 249 - if (msr_tracepoint_active(__tracepoint_rdpmc)) 251 + if (tracepoint_enabled(rdpmc)) 250 252 do_trace_rdpmc(counter, EAX_EDX_VAL(val, low, high), 0); 251 253 return EAX_EDX_VAL(val, low, high); 252 254 }
+4 -7
include/linux/ftrace.h
··· 217 217 extern struct ftrace_ops ftrace_list_end; 218 218 219 219 /* 220 - * Traverse the ftrace_global_list, invoking all entries. The reason that we 220 + * Traverse the ftrace_ops_list, invoking all entries. The reason that we 221 221 * can use rcu_dereference_raw_check() is that elements removed from this list 222 222 * are simply leaked, so there is no need to interact with a grace-period 223 223 * mechanism. The rcu_dereference_raw_check() calls are needed to handle 224 - * concurrent insertions into the ftrace_global_list. 224 + * concurrent insertions into the ftrace_ops_list. 225 225 * 226 226 * Silly Alpha and silly pointer-speculation compiler optimizations! 227 227 */ ··· 432 432 * DIRECT - there is a direct function to call 433 433 * 434 434 * When a new ftrace_ops is registered and wants a function to save 435 - * pt_regs, the rec->flag REGS is set. When the function has been 435 + * pt_regs, the rec->flags REGS is set. When the function has been 436 436 * set up to save regs, the REG_EN flag is set. Once a function 437 437 * starts saving regs it will do so until all ftrace_ops are removed 438 438 * from tracing that function. ··· 450 450 }; 451 451 452 452 #define FTRACE_REF_MAX_SHIFT 23 453 - #define FTRACE_FL_BITS 9 454 - #define FTRACE_FL_MASKED_BITS ((1UL << FTRACE_FL_BITS) - 1) 455 - #define FTRACE_FL_MASK (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT) 456 453 #define FTRACE_REF_MAX ((1UL << FTRACE_REF_MAX_SHIFT) - 1) 457 454 458 - #define ftrace_rec_count(rec) ((rec)->flags & ~FTRACE_FL_MASK) 455 + #define ftrace_rec_count(rec) ((rec)->flags & FTRACE_REF_MAX) 459 456 460 457 struct dyn_ftrace { 461 458 unsigned long ip; /* address of mcount call-site */
+21 -21
include/linux/page_ref.h
··· 7 7 #include <linux/page-flags.h> 8 8 #include <linux/tracepoint-defs.h> 9 9 10 - extern struct tracepoint __tracepoint_page_ref_set; 11 - extern struct tracepoint __tracepoint_page_ref_mod; 12 - extern struct tracepoint __tracepoint_page_ref_mod_and_test; 13 - extern struct tracepoint __tracepoint_page_ref_mod_and_return; 14 - extern struct tracepoint __tracepoint_page_ref_mod_unless; 15 - extern struct tracepoint __tracepoint_page_ref_freeze; 16 - extern struct tracepoint __tracepoint_page_ref_unfreeze; 10 + DECLARE_TRACEPOINT(page_ref_set); 11 + DECLARE_TRACEPOINT(page_ref_mod); 12 + DECLARE_TRACEPOINT(page_ref_mod_and_test); 13 + DECLARE_TRACEPOINT(page_ref_mod_and_return); 14 + DECLARE_TRACEPOINT(page_ref_mod_unless); 15 + DECLARE_TRACEPOINT(page_ref_freeze); 16 + DECLARE_TRACEPOINT(page_ref_unfreeze); 17 17 18 18 #ifdef CONFIG_DEBUG_PAGE_REF 19 19 ··· 24 24 * 25 25 * See trace_##name##_enabled(void) in include/linux/tracepoint.h 26 26 */ 27 - #define page_ref_tracepoint_active(t) static_key_false(&(t).key) 27 + #define page_ref_tracepoint_active(t) tracepoint_enabled(t) 28 28 29 29 extern void __page_ref_set(struct page *page, int v); 30 30 extern void __page_ref_mod(struct page *page, int v); ··· 75 75 static inline void set_page_count(struct page *page, int v) 76 76 { 77 77 atomic_set(&page->_refcount, v); 78 - if (page_ref_tracepoint_active(__tracepoint_page_ref_set)) 78 + if (page_ref_tracepoint_active(page_ref_set)) 79 79 __page_ref_set(page, v); 80 80 } 81 81 ··· 91 91 static inline void page_ref_add(struct page *page, int nr) 92 92 { 93 93 atomic_add(nr, &page->_refcount); 94 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod)) 94 + if (page_ref_tracepoint_active(page_ref_mod)) 95 95 __page_ref_mod(page, nr); 96 96 } 97 97 98 98 static inline void page_ref_sub(struct page *page, int nr) 99 99 { 100 100 atomic_sub(nr, &page->_refcount); 101 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod)) 101 + if (page_ref_tracepoint_active(page_ref_mod)) 102 102 __page_ref_mod(page, -nr); 103 103 } 104 104 ··· 106 106 { 107 107 int ret = atomic_sub_return(nr, &page->_refcount); 108 108 109 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_and_return)) 109 + if (page_ref_tracepoint_active(page_ref_mod_and_return)) 110 110 __page_ref_mod_and_return(page, -nr, ret); 111 111 return ret; 112 112 } ··· 114 114 static inline void page_ref_inc(struct page *page) 115 115 { 116 116 atomic_inc(&page->_refcount); 117 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod)) 117 + if (page_ref_tracepoint_active(page_ref_mod)) 118 118 __page_ref_mod(page, 1); 119 119 } 120 120 121 121 static inline void page_ref_dec(struct page *page) 122 122 { 123 123 atomic_dec(&page->_refcount); 124 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod)) 124 + if (page_ref_tracepoint_active(page_ref_mod)) 125 125 __page_ref_mod(page, -1); 126 126 } 127 127 ··· 129 129 { 130 130 int ret = atomic_sub_and_test(nr, &page->_refcount); 131 131 132 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_and_test)) 132 + if (page_ref_tracepoint_active(page_ref_mod_and_test)) 133 133 __page_ref_mod_and_test(page, -nr, ret); 134 134 return ret; 135 135 } ··· 138 138 { 139 139 int ret = atomic_inc_return(&page->_refcount); 140 140 141 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_and_return)) 141 + if (page_ref_tracepoint_active(page_ref_mod_and_return)) 142 142 __page_ref_mod_and_return(page, 1, ret); 143 143 return ret; 144 144 } ··· 147 147 { 148 148 int ret = atomic_dec_and_test(&page->_refcount); 149 149 150 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_and_test)) 150 + if (page_ref_tracepoint_active(page_ref_mod_and_test)) 151 151 __page_ref_mod_and_test(page, -1, ret); 152 152 return ret; 153 153 } ··· 156 156 { 157 157 int ret = atomic_dec_return(&page->_refcount); 158 158 159 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_and_return)) 159 + if (page_ref_tracepoint_active(page_ref_mod_and_return)) 160 160 __page_ref_mod_and_return(page, -1, ret); 161 161 return ret; 162 162 } ··· 165 165 { 166 166 int ret = atomic_add_unless(&page->_refcount, nr, u); 167 167 168 - if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_unless)) 168 + if (page_ref_tracepoint_active(page_ref_mod_unless)) 169 169 __page_ref_mod_unless(page, nr, ret); 170 170 return ret; 171 171 } ··· 174 174 { 175 175 int ret = likely(atomic_cmpxchg(&page->_refcount, count, 0) == count); 176 176 177 - if (page_ref_tracepoint_active(__tracepoint_page_ref_freeze)) 177 + if (page_ref_tracepoint_active(page_ref_freeze)) 178 178 __page_ref_freeze(page, count, ret); 179 179 return ret; 180 180 } ··· 185 185 VM_BUG_ON(count == 0); 186 186 187 187 atomic_set_release(&page->_refcount, count); 188 - if (page_ref_tracepoint_active(__tracepoint_page_ref_unfreeze)) 188 + if (page_ref_tracepoint_active(page_ref_unfreeze)) 189 189 __page_ref_unfreeze(page, count); 190 190 } 191 191
+34
include/linux/tracepoint-defs.h
··· 53 53 u32 writable_size; 54 54 } __aligned(32); 55 55 56 + /* 57 + * If a tracepoint needs to be called from a header file, it is not 58 + * recommended to call it directly, as tracepoints in header files 59 + * may cause side-effects and bloat the kernel. Instead, use 60 + * tracepoint_enabled() to test if the tracepoint is enabled, then if 61 + * it is, call a wrapper function defined in a C file that will then 62 + * call the tracepoint. 63 + * 64 + * For "trace_foo_bar()", you would need to create a wrapper function 65 + * in a C file to call trace_foo_bar(): 66 + * void do_trace_foo_bar(args) { trace_foo_bar(args); } 67 + * Then in the header file, declare the tracepoint: 68 + * DECLARE_TRACEPOINT(foo_bar); 69 + * And call your wrapper: 70 + * static inline void some_inlined_function() { 71 + * [..] 72 + * if (tracepoint_enabled(foo_bar)) 73 + * do_trace_foo_bar(args); 74 + * [..] 75 + * } 76 + * 77 + * Note: tracepoint_enabled(foo_bar) is equivalent to trace_foo_bar_enabled() 78 + * but is safe to have in headers, where trace_foo_bar_enabled() is not. 79 + */ 80 + #define DECLARE_TRACEPOINT(tp) \ 81 + extern struct tracepoint __tracepoint_##tp 82 + 83 + #ifdef CONFIG_TRACEPOINTS 84 + # define tracepoint_enabled(tp) \ 85 + static_key_false(&(__tracepoint_##tp).key) 86 + #else 87 + # define tracepoint_enabled(tracepoint) false 88 + #endif 89 + 56 90 #endif
+1 -1
kernel/kprobes.c
··· 2614 2614 init_test_probes(); 2615 2615 return err; 2616 2616 } 2617 - subsys_initcall(init_kprobes); 2617 + early_initcall(init_kprobes); 2618 2618 2619 2619 #ifdef CONFIG_DEBUG_FS 2620 2620 static void report_probe(struct seq_file *pi, struct kprobe *p,
+4 -4
kernel/trace/fgraph.c
··· 387 387 } 388 388 } 389 389 390 - read_lock(&tasklist_lock); 391 - do_each_thread(g, t) { 390 + rcu_read_lock(); 391 + for_each_process_thread(g, t) { 392 392 if (start == end) { 393 393 ret = -EAGAIN; 394 394 goto unlock; ··· 403 403 smp_wmb(); 404 404 t->ret_stack = ret_stack_list[start++]; 405 405 } 406 - } while_each_thread(g, t); 406 + } 407 407 408 408 unlock: 409 - read_unlock(&tasklist_lock); 409 + rcu_read_unlock(); 410 410 free: 411 411 for (i = start; i < end; i++) 412 412 kfree(ret_stack_list[i]);
+13 -11
kernel/trace/ftrace.c
··· 230 230 /* 231 231 * For static tracing, we need to be a bit more careful. 232 232 * The function change takes affect immediately. Thus, 233 - * we need to coorditate the setting of the function_trace_ops 233 + * we need to coordinate the setting of the function_trace_ops 234 234 * with the setting of the ftrace_trace_function. 235 235 * 236 236 * Set the function to the list ops, which will call the ··· 1368 1368 int i; 1369 1369 1370 1370 /* 1371 - * Make the hash size about 1/2 the # found 1371 + * Use around half the size (max bit of it), but 1372 + * a minimum of 2 is fine (as size of 0 or 1 both give 1 for bits). 1372 1373 */ 1373 - for (size /= 2; size; size >>= 1) 1374 - bits++; 1374 + bits = fls(size / 2); 1375 1375 1376 1376 /* Don't allocate too much */ 1377 1377 if (bits > FTRACE_HASH_MAX_BITS) ··· 1451 1451 { 1452 1452 /* 1453 1453 * The function record is a match if it exists in the filter 1454 - * hash and not in the notrace hash. Note, an emty hash is 1454 + * hash and not in the notrace hash. Note, an empty hash is 1455 1455 * considered a match for the filter hash, but an empty 1456 1456 * notrace hash is considered not in the notrace hash. 1457 1457 */ ··· 2402 2402 * 2403 2403 * If the record has the FTRACE_FL_REGS set, that means that it 2404 2404 * wants to convert to a callback that saves all regs. If FTRACE_FL_REGS 2405 - * is not not set, then it wants to convert to the normal callback. 2405 + * is not set, then it wants to convert to the normal callback. 2406 2406 * 2407 2407 * Returns the address of the trampoline to set to 2408 2408 */ ··· 2976 2976 synchronize_rcu_tasks_rude(); 2977 2977 2978 2978 /* 2979 - * When the kernel is preeptive, tasks can be preempted 2979 + * When the kernel is preemptive, tasks can be preempted 2980 2980 * while on a ftrace trampoline. Just scheduling a task on 2981 2981 * a CPU is not good enough to flush them. Calling 2982 2982 * synchornize_rcu_tasks() will wait for those tasks to ··· 3129 3129 static int ftrace_allocate_records(struct ftrace_page *pg, int count) 3130 3130 { 3131 3131 int order; 3132 + int pages; 3132 3133 int cnt; 3133 3134 3134 3135 if (WARN_ON(!count)) 3135 3136 return -EINVAL; 3136 3137 3137 - order = get_count_order(DIV_ROUND_UP(count, ENTRIES_PER_PAGE)); 3138 + pages = DIV_ROUND_UP(count, ENTRIES_PER_PAGE); 3139 + order = get_count_order(pages); 3138 3140 3139 3141 /* 3140 3142 * We want to fill as much as possible. No more than a page 3141 3143 * may be empty. 3142 3144 */ 3143 - while ((PAGE_SIZE << order) / ENTRY_SIZE >= count + ENTRIES_PER_PAGE) 3145 + if (!is_power_of_2(pages)) 3144 3146 order--; 3145 3147 3146 3148 again: ··· 4370 4368 * @ip: The instruction pointer address to map @data to 4371 4369 * @data: The data to map to @ip 4372 4370 * 4373 - * Returns 0 on succes otherwise an error. 4371 + * Returns 0 on success otherwise an error. 4374 4372 */ 4375 4373 int ftrace_func_mapper_add_ip(struct ftrace_func_mapper *mapper, 4376 4374 unsigned long ip, void *data) ··· 4538 4536 4539 4537 /* 4540 4538 * Note, there's a small window here that the func_hash->filter_hash 4541 - * may be NULL or empty. Need to be carefule when reading the loop. 4539 + * may be NULL or empty. Need to be careful when reading the loop. 4542 4540 */ 4543 4541 mutex_lock(&probe->ops.func_hash->regex_lock); 4544 4542
+10
kernel/trace/ring_buffer.c
··· 4866 4866 if (!cpumask_test_cpu(cpu, buffer->cpumask)) 4867 4867 return; 4868 4868 4869 + /* prevent another thread from changing buffer sizes */ 4870 + mutex_lock(&buffer->mutex); 4871 + 4869 4872 atomic_inc(&cpu_buffer->resize_disabled); 4870 4873 atomic_inc(&cpu_buffer->record_disabled); 4871 4874 ··· 4879 4876 4880 4877 atomic_dec(&cpu_buffer->record_disabled); 4881 4878 atomic_dec(&cpu_buffer->resize_disabled); 4879 + 4880 + mutex_unlock(&buffer->mutex); 4882 4881 } 4883 4882 EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu); 4884 4883 ··· 4893 4888 { 4894 4889 struct ring_buffer_per_cpu *cpu_buffer; 4895 4890 int cpu; 4891 + 4892 + /* prevent another thread from changing buffer sizes */ 4893 + mutex_lock(&buffer->mutex); 4896 4894 4897 4895 for_each_online_buffer_cpu(buffer, cpu) { 4898 4896 cpu_buffer = buffer->buffers[cpu]; ··· 4915 4907 atomic_dec(&cpu_buffer->record_disabled); 4916 4908 atomic_dec(&cpu_buffer->resize_disabled); 4917 4909 } 4910 + 4911 + mutex_unlock(&buffer->mutex); 4918 4912 } 4919 4913 4920 4914 /**
+12 -6
kernel/trace/synth_event_gen_test.c
··· 242 242 { .type = "pid_t", .name = "next_pid_field" }, 243 243 { .type = "char[16]", .name = "next_comm_field" }, 244 244 { .type = "u64", .name = "ts_ns" }, 245 + { .type = "char[]", .name = "dynstring_field_1" }, 245 246 { .type = "u64", .name = "ts_ms" }, 246 247 { .type = "unsigned int", .name = "cpu" }, 247 248 { .type = "char[64]", .name = "my_string_field" }, 249 + { .type = "char[]", .name = "dynstring_field_2" }, 248 250 { .type = "int", .name = "my_int_field" }, 249 251 }; 250 252 ··· 256 254 */ 257 255 static int __init test_create_synth_event(void) 258 256 { 259 - u64 vals[7]; 257 + u64 vals[9]; 260 258 int ret; 261 259 262 260 /* Create the create_synth_test event with the fields above */ ··· 294 292 vals[0] = 777; /* next_pid_field */ 295 293 vals[1] = (u64)(long)"tiddlywinks"; /* next_comm_field */ 296 294 vals[2] = 1000000; /* ts_ns */ 297 - vals[3] = 1000; /* ts_ms */ 298 - vals[4] = raw_smp_processor_id(); /* cpu */ 299 - vals[5] = (u64)(long)"thneed"; /* my_string_field */ 300 - vals[6] = 398; /* my_int_field */ 295 + vals[3] = (u64)(long)"xrayspecs"; /* dynstring_field_1 */ 296 + vals[4] = 1000; /* ts_ms */ 297 + vals[5] = raw_smp_processor_id(); /* cpu */ 298 + vals[6] = (u64)(long)"thneed"; /* my_string_field */ 299 + vals[7] = (u64)(long)"kerplunk"; /* dynstring_field_2 */ 300 + vals[8] = 398; /* my_int_field */ 301 301 302 302 /* Now generate a create_synth_test event */ 303 303 ret = synth_event_trace_array(create_synth_test, vals, ARRAY_SIZE(vals)); ··· 426 422 int ret; 427 423 428 424 /* Trace some bogus values just for testing */ 429 - ret = synth_event_trace(create_synth_test, 7, /* number of values */ 425 + ret = synth_event_trace(create_synth_test, 9, /* number of values */ 430 426 (u64)444, /* next_pid_field */ 431 427 (u64)(long)"clackers", /* next_comm_field */ 432 428 (u64)1000000, /* ts_ns */ 429 + (u64)(long)"viewmaster",/* dynstring_field_1 */ 433 430 (u64)1000, /* ts_ms */ 434 431 (u64)raw_smp_processor_id(), /* cpu */ 435 432 (u64)(long)"Thneed", /* my_string_field */ 433 + (u64)(long)"yoyos", /* dynstring_field_2 */ 436 434 (u64)999); /* my_int_field */ 437 435 return ret; 438 436 }
+73 -38
kernel/trace/trace.c
··· 2650 2650 2651 2651 preempt_disable(); 2652 2652 if (cpu == smp_processor_id() && 2653 - this_cpu_read(trace_buffered_event) != 2653 + __this_cpu_read(trace_buffered_event) != 2654 2654 per_cpu(trace_buffered_event, cpu)) 2655 2655 WARN_ON_ONCE(1); 2656 2656 preempt_enable(); ··· 5142 5142 "\t -:[<group>/]<event>\n" 5143 5143 #ifdef CONFIG_KPROBE_EVENTS 5144 5144 "\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n" 5145 - "place (kretprobe): [<module>:]<symbol>[+<offset>]|<memaddr>\n" 5145 + "place (kretprobe): [<module>:]<symbol>[+<offset>]%return|<memaddr>\n" 5146 5146 #endif 5147 5147 #ifdef CONFIG_UPROBE_EVENTS 5148 - " place (uprobe): <path>:<offset>[(ref_ctr_offset)]\n" 5148 + " place (uprobe): <path>:<offset>[%return][(ref_ctr_offset)]\n" 5149 5149 #endif 5150 5150 "\t args: <name>=fetcharg[:type]\n" 5151 5151 "\t fetcharg: %<register>, @<address>, @<symbol>[+|-<offset>],\n" ··· 5269 5269 "\t trace(<synthetic_event>,param list) - generate synthetic event\n" 5270 5270 "\t save(field,...) - save current event fields\n" 5271 5271 #ifdef CONFIG_TRACER_SNAPSHOT 5272 - "\t snapshot() - snapshot the trace buffer\n" 5272 + "\t snapshot() - snapshot the trace buffer\n\n" 5273 + #endif 5274 + #ifdef CONFIG_SYNTH_EVENTS 5275 + " events/synthetic_events\t- Create/append/remove/show synthetic events\n" 5276 + "\t Write into this file to define/undefine new synthetic events.\n" 5277 + "\t example: echo 'myevent u64 lat; char name[]' >> synthetic_events\n" 5273 5278 #endif 5274 5279 #endif 5275 5280 ; ··· 6687 6682 written = -EFAULT; 6688 6683 } else 6689 6684 written = cnt; 6690 - len = cnt; 6691 6685 6692 6686 if (tr->trace_marker_file && !list_empty(&tr->trace_marker_file->triggers)) { 6693 6687 /* do not add \n before testing triggers, but add \0 */ ··· 8662 8658 return tr; 8663 8659 } 8664 8660 8661 + static int trace_array_create_dir(struct trace_array *tr) 8662 + { 8663 + int ret; 8664 + 8665 + tr->dir = tracefs_create_dir(tr->name, trace_instance_dir); 8666 + if (!tr->dir) 8667 + return -EINVAL; 8668 + 8669 + ret = event_trace_add_tracer(tr->dir, tr); 8670 + if (ret) 8671 + tracefs_remove(tr->dir); 8672 + 8673 + init_tracer_tracefs(tr, tr->dir); 8674 + __update_tracer_options(tr); 8675 + 8676 + return ret; 8677 + } 8678 + 8665 8679 static struct trace_array *trace_array_create(const char *name) 8666 8680 { 8667 8681 struct trace_array *tr; ··· 8715 8693 if (allocate_trace_buffers(tr, trace_buf_size) < 0) 8716 8694 goto out_free_tr; 8717 8695 8718 - tr->dir = tracefs_create_dir(name, trace_instance_dir); 8719 - if (!tr->dir) 8696 + if (ftrace_allocate_ftrace_ops(tr) < 0) 8720 8697 goto out_free_tr; 8721 - 8722 - ret = event_trace_add_tracer(tr->dir, tr); 8723 - if (ret) { 8724 - tracefs_remove(tr->dir); 8725 - goto out_free_tr; 8726 - } 8727 8698 8728 8699 ftrace_init_trace_array(tr); 8729 8700 8730 - init_tracer_tracefs(tr, tr->dir); 8731 8701 init_trace_flags_index(tr); 8732 - __update_tracer_options(tr); 8702 + 8703 + if (trace_instance_dir) { 8704 + ret = trace_array_create_dir(tr); 8705 + if (ret) 8706 + goto out_free_tr; 8707 + } else 8708 + __trace_early_add_events(tr); 8733 8709 8734 8710 list_add(&tr->list, &ftrace_trace_arrays); 8735 8711 8736 8712 tr->ref++; 8737 8713 8738 - 8739 8714 return tr; 8740 8715 8741 8716 out_free_tr: 8717 + ftrace_free_ftrace_ops(tr); 8742 8718 free_trace_buffers(tr); 8743 8719 free_cpumask_var(tr->tracing_cpumask); 8744 8720 kfree(tr->name); ··· 8841 8821 free_cpumask_var(tr->tracing_cpumask); 8842 8822 kfree(tr->name); 8843 8823 kfree(tr); 8844 - tr = NULL; 8845 8824 8846 8825 return 0; 8847 8826 } ··· 8894 8875 8895 8876 static __init void create_trace_instances(struct dentry *d_tracer) 8896 8877 { 8878 + struct trace_array *tr; 8879 + 8897 8880 trace_instance_dir = tracefs_create_instance_dir("instances", d_tracer, 8898 8881 instance_mkdir, 8899 8882 instance_rmdir); 8900 8883 if (MEM_FAIL(!trace_instance_dir, "Failed to create instances directory\n")) 8901 8884 return; 8885 + 8886 + mutex_lock(&event_mutex); 8887 + mutex_lock(&trace_types_lock); 8888 + 8889 + list_for_each_entry(tr, &ftrace_trace_arrays, list) { 8890 + if (!tr->name) 8891 + continue; 8892 + if (MEM_FAIL(trace_array_create_dir(tr) < 0, 8893 + "Failed to create instance directory\n")) 8894 + break; 8895 + } 8896 + 8897 + mutex_unlock(&trace_types_lock); 8898 + mutex_unlock(&event_mutex); 8902 8899 } 8903 8900 8904 8901 static void ··· 9028 8993 * directory. It is called via fs_initcall() by any of the boot up code 9029 8994 * and expects to return the dentry of the top level tracing directory. 9030 8995 */ 9031 - struct dentry *tracing_init_dentry(void) 8996 + int tracing_init_dentry(void) 9032 8997 { 9033 8998 struct trace_array *tr = &global_trace; 9034 8999 9035 9000 if (security_locked_down(LOCKDOWN_TRACEFS)) { 9036 9001 pr_warn("Tracing disabled due to lockdown\n"); 9037 - return ERR_PTR(-EPERM); 9002 + return -EPERM; 9038 9003 } 9039 9004 9040 9005 /* The top level trace array uses NULL as parent */ 9041 9006 if (tr->dir) 9042 - return NULL; 9007 + return 0; 9043 9008 9044 9009 if (WARN_ON(!tracefs_initialized())) 9045 - return ERR_PTR(-ENODEV); 9010 + return -ENODEV; 9046 9011 9047 9012 /* 9048 9013 * As there may still be users that expect the tracing ··· 9053 9018 tr->dir = debugfs_create_automount("tracing", NULL, 9054 9019 trace_automount, NULL); 9055 9020 9056 - return NULL; 9021 + return 0; 9057 9022 } 9058 9023 9059 9024 extern struct trace_eval_map *__start_ftrace_eval_maps[]; ··· 9140 9105 9141 9106 static __init int tracer_init_tracefs(void) 9142 9107 { 9143 - struct dentry *d_tracer; 9108 + int ret; 9144 9109 9145 9110 trace_access_lock_init(); 9146 9111 9147 - d_tracer = tracing_init_dentry(); 9148 - if (IS_ERR(d_tracer)) 9112 + ret = tracing_init_dentry(); 9113 + if (ret) 9149 9114 return 0; 9150 9115 9151 9116 event_trace_init(); 9152 9117 9153 - init_tracer_tracefs(&global_trace, d_tracer); 9154 - ftrace_init_tracefs_toplevel(&global_trace, d_tracer); 9118 + init_tracer_tracefs(&global_trace, NULL); 9119 + ftrace_init_tracefs_toplevel(&global_trace, NULL); 9155 9120 9156 - trace_create_file("tracing_thresh", 0644, d_tracer, 9121 + trace_create_file("tracing_thresh", 0644, NULL, 9157 9122 &global_trace, &tracing_thresh_fops); 9158 9123 9159 - trace_create_file("README", 0444, d_tracer, 9124 + trace_create_file("README", 0444, NULL, 9160 9125 NULL, &tracing_readme_fops); 9161 9126 9162 - trace_create_file("saved_cmdlines", 0444, d_tracer, 9127 + trace_create_file("saved_cmdlines", 0444, NULL, 9163 9128 NULL, &tracing_saved_cmdlines_fops); 9164 9129 9165 - trace_create_file("saved_cmdlines_size", 0644, d_tracer, 9130 + trace_create_file("saved_cmdlines_size", 0644, NULL, 9166 9131 NULL, &tracing_saved_cmdlines_size_fops); 9167 9132 9168 - trace_create_file("saved_tgids", 0444, d_tracer, 9133 + trace_create_file("saved_tgids", 0444, NULL, 9169 9134 NULL, &tracing_saved_tgids_fops); 9170 9135 9171 9136 trace_eval_init(); 9172 9137 9173 - trace_create_eval_file(d_tracer); 9138 + trace_create_eval_file(NULL); 9174 9139 9175 9140 #ifdef CONFIG_MODULES 9176 9141 register_module_notifier(&trace_module_nb); 9177 9142 #endif 9178 9143 9179 9144 #ifdef CONFIG_DYNAMIC_FTRACE 9180 - trace_create_file("dyn_ftrace_total_info", 0444, d_tracer, 9145 + trace_create_file("dyn_ftrace_total_info", 0444, NULL, 9181 9146 NULL, &tracing_dyn_info_fops); 9182 9147 #endif 9183 9148 9184 - create_trace_instances(d_tracer); 9149 + create_trace_instances(NULL); 9185 9150 9186 9151 update_tracer_options(&global_trace); 9187 9152 ··· 9344 9309 } 9345 9310 9346 9311 /* 9347 - * We need to stop all tracing on all CPUS to read the 9312 + * We need to stop all tracing on all CPUS to read 9348 9313 * the next buffer. This is a bit expensive, but is 9349 9314 * not done often. We fill all what we can read, 9350 9315 * and then release the locks again. ··· 9487 9452 } 9488 9453 9489 9454 /* 9490 - * Make sure we don't accidently add more trace options 9455 + * Make sure we don't accidentally add more trace options 9491 9456 * than we have bits for. 9492 9457 */ 9493 9458 BUILD_BUG_ON(TRACE_ITER_LAST_BIT > TRACE_FLAGS_MAX_SIZE); ··· 9516 9481 9517 9482 /* 9518 9483 * The prepare callbacks allocates some memory for the ring buffer. We 9519 - * don't free the buffer if the if the CPU goes down. If we were to free 9484 + * don't free the buffer if the CPU goes down. If we were to free 9520 9485 * the buffer, then the user would lose any trace that was in the 9521 9486 * buffer. The memory will be removed once the "instance" is removed. 9522 9487 */
+26 -5
kernel/trace/trace.h
··· 19 19 #include <linux/glob.h> 20 20 #include <linux/irq_work.h> 21 21 #include <linux/workqueue.h> 22 + #include <linux/ctype.h> 22 23 23 24 #ifdef CONFIG_FTRACE_SYSCALLS 24 25 #include <asm/unistd.h> /* For NR_SYSCALLS */ ··· 247 246 * tracing_snapshot_cond(tr, cond_data), the cond_data passed in is 248 247 * passed in turn to the cond_snapshot.update() function. That data 249 248 * can be compared by the update() implementation with the cond_data 250 - * contained wihin the struct cond_snapshot instance associated with 249 + * contained within the struct cond_snapshot instance associated with 251 250 * the trace_array. Because the tr->max_lock is held throughout the 252 251 * update() call, the update() function can directly retrieve the 253 252 * cond_snapshot and cond_data associated with the per-instance ··· 272 271 * take the snapshot, by returning 'true' if so, 'false' if no 273 272 * snapshot should be taken. Because the max_lock is held for 274 273 * the duration of update(), the implementation is safe to 275 - * directly retrieven and save any implementation data it needs 274 + * directly retrieved and save any implementation data it needs 276 275 * to in association with the snapshot. 277 276 */ 278 277 struct cond_snapshot { ··· 574 573 * The function callback, which can use the FTRACE bits to 575 574 * check for recursion. 576 575 * 577 - * Now if the arch does not suppport a feature, and it calls 576 + * Now if the arch does not support a feature, and it calls 578 577 * the global list function which calls the ftrace callback 579 578 * all three of these steps will do a recursion protection. 580 579 * There's no reason to do one if the previous caller already ··· 738 737 void *data, 739 738 const struct file_operations *fops); 740 739 741 - struct dentry *tracing_init_dentry(void); 740 + int tracing_init_dentry(void); 742 741 743 742 struct ring_buffer_event; 744 743 ··· 1126 1125 int ftrace_create_function_files(struct trace_array *tr, 1127 1126 struct dentry *parent); 1128 1127 void ftrace_destroy_function_files(struct trace_array *tr); 1128 + int ftrace_allocate_ftrace_ops(struct trace_array *tr); 1129 + void ftrace_free_ftrace_ops(struct trace_array *tr); 1129 1130 void ftrace_init_global_array_ops(struct trace_array *tr); 1130 1131 void ftrace_init_array_ops(struct trace_array *tr, ftrace_func_t func); 1131 1132 void ftrace_reset_array_ops(struct trace_array *tr); ··· 1149 1146 { 1150 1147 return 0; 1151 1148 } 1149 + static inline int ftrace_allocate_ftrace_ops(struct trace_array *tr) 1150 + { 1151 + return 0; 1152 + } 1153 + static inline void ftrace_free_ftrace_ops(struct trace_array *tr) { } 1152 1154 static inline void ftrace_destroy_function_files(struct trace_array *tr) { } 1153 1155 static inline __init void 1154 1156 ftrace_init_global_array_ops(struct trace_array *tr) { } ··· 1480 1472 /* 1481 1473 * Helper function for event_trigger_unlock_commit{_regs}(). 1482 1474 * If there are event triggers attached to this event that requires 1483 - * filtering against its fields, then they wil be called as the 1475 + * filtering against its fields, then they will be called as the 1484 1476 * entry already holds the field information of the current event. 1485 1477 * 1486 1478 * It also checks if the event should be discarded or not. ··· 1659 1651 extern int event_trace_init(void); 1660 1652 extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr); 1661 1653 extern int event_trace_del_tracer(struct trace_array *tr); 1654 + extern void __trace_early_add_events(struct trace_array *tr); 1662 1655 1663 1656 extern struct trace_event_file *__find_event_file(struct trace_array *tr, 1664 1657 const char *system, ··· 2089 2080 memset((char *)iter + offset, 0, sizeof(struct trace_iterator) - offset); 2090 2081 2091 2082 iter->pos = -1; 2083 + } 2084 + 2085 + /* Check the name is good for event/group/fields */ 2086 + static inline bool is_good_name(const char *name) 2087 + { 2088 + if (!isalpha(*name) && *name != '_') 2089 + return false; 2090 + while (*++name != '\0') { 2091 + if (!isalpha(*name) && !isdigit(*name) && *name != '_') 2092 + return false; 2093 + } 2094 + return true; 2092 2095 } 2093 2096 2094 2097 #endif /* _LINUX_KERNEL_TRACE_H */
+21 -2
kernel/trace/trace_boot.c
··· 40 40 pr_err("Failed to set option: %s\n", buf); 41 41 } 42 42 43 + p = xbc_node_find_value(node, "tracing_on", NULL); 44 + if (p && *p != '\0') { 45 + if (kstrtoul(p, 10, &v)) 46 + pr_err("Failed to set tracing on: %s\n", p); 47 + if (v) 48 + tracer_tracing_on(tr); 49 + else 50 + tracer_tracing_off(tr); 51 + } 52 + 43 53 p = xbc_node_find_value(node, "trace_clock", NULL); 44 54 if (p && *p != '\0') { 45 55 if (tracing_set_clock(tr, p) < 0) ··· 284 274 if (tracing_set_tracer(tr, p) < 0) 285 275 pr_err("Failed to set given tracer: %s\n", p); 286 276 } 277 + 278 + /* Since tracer can free snapshot buffer, allocate snapshot here.*/ 279 + if (xbc_node_find_value(node, "alloc_snapshot", NULL)) { 280 + if (tracing_alloc_snapshot_instance(tr) < 0) 281 + pr_err("Failed to allocate snapshot buffer\n"); 282 + } 287 283 } 288 284 289 285 static void __init ··· 346 330 347 331 return 0; 348 332 } 349 - 350 - fs_initcall(trace_boot_init); 333 + /* 334 + * Start tracing at the end of core-initcall, so that it starts tracing 335 + * from the beginning of postcore_initcall. 336 + */ 337 + core_initcall_sync(trace_boot_init);
+5 -5
kernel/trace/trace_dynevent.c
··· 206 206 /* Make a tracefs interface for controlling dynamic events */ 207 207 static __init int init_dynamic_event(void) 208 208 { 209 - struct dentry *d_tracer; 210 209 struct dentry *entry; 210 + int ret; 211 211 212 - d_tracer = tracing_init_dentry(); 213 - if (IS_ERR(d_tracer)) 212 + ret = tracing_init_dentry(); 213 + if (ret) 214 214 return 0; 215 215 216 - entry = tracefs_create_file("dynamic_events", 0644, d_tracer, 216 + entry = tracefs_create_file("dynamic_events", 0644, NULL, 217 217 NULL, &dynamic_events_ops); 218 218 219 219 /* Event list interface */ ··· 402 402 * whitespace, all followed by a separator, if applicable. After the 403 403 * first arg string is successfully appended to the command string, 404 404 * the optional @operator is appended, followed by the second arg and 405 - * and optional @separator. If no separator was specified when 405 + * optional @separator. If no separator was specified when 406 406 * initializing the arg, a space will be appended. 407 407 */ 408 408 void dynevent_arg_pair_init(struct dynevent_arg_pair *arg_pair,
+81 -59
kernel/trace/trace_events.c
··· 38 38 LIST_HEAD(ftrace_events); 39 39 static LIST_HEAD(ftrace_generic_fields); 40 40 static LIST_HEAD(ftrace_common_fields); 41 + static bool eventdir_initialized; 41 42 42 43 #define GFP_TRACE (GFP_KERNEL | __GFP_ZERO) 43 44 ··· 2125 2124 } 2126 2125 2127 2126 static int 2127 + event_define_fields(struct trace_event_call *call) 2128 + { 2129 + struct list_head *head; 2130 + int ret = 0; 2131 + 2132 + /* 2133 + * Other events may have the same class. Only update 2134 + * the fields if they are not already defined. 2135 + */ 2136 + head = trace_get_fields(call); 2137 + if (list_empty(head)) { 2138 + struct trace_event_fields *field = call->class->fields_array; 2139 + unsigned int offset = sizeof(struct trace_entry); 2140 + 2141 + for (; field->type; field++) { 2142 + if (field->type == TRACE_FUNCTION_TYPE) { 2143 + field->define_fields(call); 2144 + break; 2145 + } 2146 + 2147 + offset = ALIGN(offset, field->align); 2148 + ret = trace_define_field(call, field->type, field->name, 2149 + offset, field->size, 2150 + field->is_signed, field->filter_type); 2151 + if (WARN_ON_ONCE(ret)) { 2152 + pr_err("error code is %d\n", ret); 2153 + break; 2154 + } 2155 + 2156 + offset += field->size; 2157 + } 2158 + } 2159 + 2160 + return ret; 2161 + } 2162 + 2163 + static int 2128 2164 event_create_dir(struct dentry *parent, struct trace_event_file *file) 2129 2165 { 2130 2166 struct trace_event_call *call = file->event_call; 2131 2167 struct trace_array *tr = file->tr; 2132 - struct list_head *head; 2133 2168 struct dentry *d_events; 2134 2169 const char *name; 2135 2170 int ret; ··· 2199 2162 &ftrace_event_id_fops); 2200 2163 #endif 2201 2164 2202 - /* 2203 - * Other events may have the same class. Only update 2204 - * the fields if they are not already defined. 2205 - */ 2206 - head = trace_get_fields(call); 2207 - if (list_empty(head)) { 2208 - struct trace_event_fields *field = call->class->fields_array; 2209 - unsigned int offset = sizeof(struct trace_entry); 2210 - 2211 - for (; field->type; field++) { 2212 - if (field->type == TRACE_FUNCTION_TYPE) { 2213 - ret = field->define_fields(call); 2214 - break; 2215 - } 2216 - 2217 - offset = ALIGN(offset, field->align); 2218 - ret = trace_define_field(call, field->type, field->name, 2219 - offset, field->size, 2220 - field->is_signed, field->filter_type); 2221 - if (ret) 2222 - break; 2223 - 2224 - offset += field->size; 2225 - } 2226 - if (ret < 0) { 2227 - pr_warn("Could not initialize trace point events/%s\n", 2228 - name); 2229 - return -1; 2230 - } 2165 + ret = event_define_fields(call); 2166 + if (ret < 0) { 2167 + pr_warn("Could not initialize trace point events/%s\n", name); 2168 + return ret; 2231 2169 } 2232 2170 2233 2171 /* ··· 2487 2475 if (!file) 2488 2476 return -ENOMEM; 2489 2477 2490 - return event_create_dir(tr->event_dir, file); 2478 + if (eventdir_initialized) 2479 + return event_create_dir(tr->event_dir, file); 2480 + else 2481 + return event_define_fields(call); 2491 2482 } 2492 2483 2493 2484 /* ··· 2508 2493 if (!file) 2509 2494 return -ENOMEM; 2510 2495 2511 - return 0; 2496 + return event_define_fields(call); 2512 2497 } 2513 2498 2514 2499 struct ftrace_module_file_ops; ··· 3131 3116 #endif /* CONFIG_DYNAMIC_FTRACE */ 3132 3117 3133 3118 /* 3134 - * The top level array has already had its trace_event_file 3135 - * descriptors created in order to allow for early events to 3136 - * be recorded. This function is called after the tracefs has been 3137 - * initialized, and we now have to create the files associated 3138 - * to the events. 3119 + * The top level array and trace arrays created by boot-time tracing 3120 + * have already had its trace_event_file descriptors created in order 3121 + * to allow for early events to be recorded. 3122 + * This function is called after the tracefs has been initialized, 3123 + * and we now have to create the files associated to the events. 3139 3124 */ 3140 - static __init void 3141 - __trace_early_add_event_dirs(struct trace_array *tr) 3125 + static void __trace_early_add_event_dirs(struct trace_array *tr) 3142 3126 { 3143 3127 struct trace_event_file *file; 3144 3128 int ret; ··· 3152 3138 } 3153 3139 3154 3140 /* 3155 - * For early boot up, the top trace array requires to have 3156 - * a list of events that can be enabled. This must be done before 3157 - * the filesystem is set up in order to allow events to be traced 3158 - * early. 3141 + * For early boot up, the top trace array and the trace arrays created 3142 + * by boot-time tracing require to have a list of events that can be 3143 + * enabled. This must be done before the filesystem is set up in order 3144 + * to allow events to be traced early. 3159 3145 */ 3160 - static __init void 3161 - __trace_early_add_events(struct trace_array *tr) 3146 + void __trace_early_add_events(struct trace_array *tr) 3162 3147 { 3163 3148 struct trace_event_call *call; 3164 3149 int ret; ··· 3288 3275 goto out; 3289 3276 3290 3277 down_write(&trace_event_sem); 3291 - __trace_add_event_dirs(tr); 3278 + /* If tr already has the event list, it is initialized in early boot. */ 3279 + if (unlikely(!list_empty(&tr->events))) 3280 + __trace_early_add_event_dirs(tr); 3281 + else 3282 + __trace_add_event_dirs(tr); 3292 3283 up_write(&trace_event_sem); 3293 3284 3294 3285 out: ··· 3448 3431 3449 3432 early_initcall(event_trace_enable_again); 3450 3433 3434 + /* Init fields which doesn't related to the tracefs */ 3435 + static __init int event_trace_init_fields(void) 3436 + { 3437 + if (trace_define_generic_fields()) 3438 + pr_warn("tracing: Failed to allocated generic fields"); 3439 + 3440 + if (trace_define_common_fields()) 3441 + pr_warn("tracing: Failed to allocate common fields"); 3442 + 3443 + return 0; 3444 + } 3445 + 3451 3446 __init int event_trace_init(void) 3452 3447 { 3453 3448 struct trace_array *tr; 3454 - struct dentry *d_tracer; 3455 3449 struct dentry *entry; 3456 3450 int ret; 3457 3451 ··· 3470 3442 if (!tr) 3471 3443 return -ENODEV; 3472 3444 3473 - d_tracer = tracing_init_dentry(); 3474 - if (IS_ERR(d_tracer)) 3475 - return 0; 3476 - 3477 - entry = tracefs_create_file("available_events", 0444, d_tracer, 3445 + entry = tracefs_create_file("available_events", 0444, NULL, 3478 3446 tr, &ftrace_avail_fops); 3479 3447 if (!entry) 3480 3448 pr_warn("Could not create tracefs 'available_events' entry\n"); 3481 3449 3482 - if (trace_define_generic_fields()) 3483 - pr_warn("tracing: Failed to allocated generic fields"); 3484 - 3485 - if (trace_define_common_fields()) 3486 - pr_warn("tracing: Failed to allocate common fields"); 3487 - 3488 - ret = early_event_add_tracer(d_tracer, tr); 3450 + ret = early_event_add_tracer(NULL, tr); 3489 3451 if (ret) 3490 3452 return ret; 3491 3453 ··· 3484 3466 if (ret) 3485 3467 pr_warn("Failed to register trace events module notifier\n"); 3486 3468 #endif 3469 + 3470 + eventdir_initialized = true; 3471 + 3487 3472 return 0; 3488 3473 } 3489 3474 ··· 3495 3474 event_trace_memsetup(); 3496 3475 init_ftrace_syscalls(); 3497 3476 event_trace_enable(); 3477 + event_trace_init_fields(); 3498 3478 } 3499 3479 3500 3480 #ifdef CONFIG_EVENT_TRACE_STARTUP_TEST
+43 -2
kernel/trace/trace_events_hist.c
··· 147 147 */ 148 148 unsigned int var_ref_idx; 149 149 bool read_once; 150 + 151 + unsigned int var_str_idx; 150 152 }; 151 153 152 154 static u64 hist_field_none(struct hist_field *field, ··· 351 349 unsigned int n_keys; 352 350 unsigned int n_fields; 353 351 unsigned int n_vars; 352 + unsigned int n_var_str; 354 353 unsigned int key_size; 355 354 struct tracing_map_sort_key sort_keys[TRACING_MAP_SORT_KEYS_MAX]; 356 355 unsigned int n_sort_keys; ··· 1399 1396 } 1400 1397 } 1401 1398 1402 - n_str = hist_data->n_field_var_str + hist_data->n_save_var_str; 1399 + n_str = hist_data->n_field_var_str + hist_data->n_save_var_str + 1400 + hist_data->n_var_str; 1401 + if (n_str > SYNTH_FIELDS_MAX) { 1402 + hist_elt_data_free(elt_data); 1403 + return -EINVAL; 1404 + } 1405 + 1406 + BUILD_BUG_ON(STR_VAR_LEN_MAX & (sizeof(u64) - 1)); 1403 1407 1404 1408 size = STR_VAR_LEN_MAX; 1405 1409 ··· 3289 3279 3290 3280 field = event->fields[field_pos]; 3291 3281 3282 + /* 3283 + * A dynamic string synth field can accept static or 3284 + * dynamic. A static string synth field can only accept a 3285 + * same-sized static string, which is checked for later. 3286 + */ 3287 + if (strstr(hist_field->type, "char[") && field->is_string 3288 + && field->is_dynamic) 3289 + return 0; 3290 + 3292 3291 if (strcmp(field->type, hist_field->type) != 0) { 3293 3292 if (field->size != hist_field->size || 3294 3293 field->is_signed != hist_field->is_signed) ··· 3670 3651 { 3671 3652 struct trace_array *tr = hist_data->event_file->tr; 3672 3653 unsigned long flags = 0; 3654 + int ret; 3673 3655 3674 3656 if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX + TRACING_MAP_VARS_MAX)) 3675 3657 return -EINVAL; ··· 3685 3665 if (WARN_ON(hist_data->n_vars > TRACING_MAP_VARS_MAX)) 3686 3666 return -EINVAL; 3687 3667 3688 - return __create_val_field(hist_data, val_idx, file, var_name, expr_str, flags); 3668 + ret = __create_val_field(hist_data, val_idx, file, var_name, expr_str, flags); 3669 + 3670 + if (!ret && hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING) 3671 + hist_data->fields[val_idx]->var_str_idx = hist_data->n_var_str++; 3672 + 3673 + return ret; 3689 3674 } 3690 3675 3691 3676 static int create_val_fields(struct hist_trigger_data *hist_data, ··· 4417 4392 hist_val = hist_field->fn(hist_field, elt, rbe, rec); 4418 4393 if (hist_field->flags & HIST_FIELD_FL_VAR) { 4419 4394 var_idx = hist_field->var.idx; 4395 + 4396 + if (hist_field->flags & HIST_FIELD_FL_STRING) { 4397 + unsigned int str_start, var_str_idx, idx; 4398 + char *str, *val_str; 4399 + 4400 + str_start = hist_data->n_field_var_str + 4401 + hist_data->n_save_var_str; 4402 + var_str_idx = hist_field->var_str_idx; 4403 + idx = str_start + var_str_idx; 4404 + 4405 + str = elt_data->field_var_str[idx]; 4406 + val_str = (char *)(uintptr_t)hist_val; 4407 + strscpy(str, val_str, STR_VAR_LEN_MAX); 4408 + 4409 + hist_val = (u64)(uintptr_t)str; 4410 + } 4420 4411 tracing_map_set_var(elt, var_idx, hist_val); 4421 4412 continue; 4422 4413 }
+361 -52
kernel/trace/trace_events_synth.c
··· 20 20 21 21 #include "trace_synth.h" 22 22 23 + #undef ERRORS 24 + #define ERRORS \ 25 + C(BAD_NAME, "Illegal name"), \ 26 + C(CMD_INCOMPLETE, "Incomplete command"), \ 27 + C(EVENT_EXISTS, "Event already exists"), \ 28 + C(TOO_MANY_FIELDS, "Too many fields"), \ 29 + C(INCOMPLETE_TYPE, "Incomplete type"), \ 30 + C(INVALID_TYPE, "Invalid type"), \ 31 + C(INVALID_FIELD, "Invalid field"), \ 32 + C(CMD_TOO_LONG, "Command too long"), 33 + 34 + #undef C 35 + #define C(a, b) SYNTH_ERR_##a 36 + 37 + enum { ERRORS }; 38 + 39 + #undef C 40 + #define C(a, b) b 41 + 42 + static const char *err_text[] = { ERRORS }; 43 + 44 + static char last_cmd[MAX_FILTER_STR_VAL]; 45 + 46 + static int errpos(const char *str) 47 + { 48 + return err_pos(last_cmd, str); 49 + } 50 + 51 + static void last_cmd_set(char *str) 52 + { 53 + if (!str) 54 + return; 55 + 56 + strncpy(last_cmd, str, MAX_FILTER_STR_VAL - 1); 57 + } 58 + 59 + static void synth_err(u8 err_type, u8 err_pos) 60 + { 61 + tracing_log_err(NULL, "synthetic_events", last_cmd, err_text, 62 + err_type, err_pos); 63 + } 64 + 23 65 static int create_synth_event(int argc, const char **argv); 24 66 static int synth_event_show(struct seq_file *m, struct dyn_event *ev); 25 67 static int synth_event_release(struct dyn_event *ev); ··· 130 88 131 89 event->fields[i]->offset = n_u64; 132 90 133 - if (event->fields[i]->is_string) { 91 + if (event->fields[i]->is_string && !event->fields[i]->is_dynamic) { 134 92 offset += STR_VAR_LEN_MAX; 135 93 n_u64 += STR_VAR_LEN_MAX / sizeof(u64); 136 94 } else { ··· 174 132 start += sizeof("char[") - 1; 175 133 176 134 end = strchr(type, ']'); 177 - if (!end || end < start) 135 + if (!end || end < start || type + strlen(type) > end + 1) 178 136 return -EINVAL; 179 137 180 138 len = end - start; 181 139 if (len > 3) 182 140 return -EINVAL; 141 + 142 + if (len == 0) 143 + return 0; /* variable-length string */ 183 144 184 145 strncpy(buf, start, len); 185 146 buf[len] = '\0'; ··· 229 184 size = sizeof(long); 230 185 else if (strcmp(type, "unsigned long") == 0) 231 186 size = sizeof(unsigned long); 187 + else if (strcmp(type, "bool") == 0) 188 + size = sizeof(bool); 232 189 else if (strcmp(type, "pid_t") == 0) 233 190 size = sizeof(pid_t); 234 191 else if (strcmp(type, "gfp_t") == 0) ··· 273 226 fmt = "%ld"; 274 227 else if (strcmp(type, "unsigned long") == 0) 275 228 fmt = "%lu"; 229 + else if (strcmp(type, "bool") == 0) 230 + fmt = "%d"; 276 231 else if (strcmp(type, "pid_t") == 0) 277 232 fmt = "%d"; 278 233 else if (strcmp(type, "gfp_t") == 0) 279 234 fmt = "%x"; 280 235 else if (synth_field_is_string(type)) 281 - fmt = "%s"; 236 + fmt = "%.*s"; 282 237 283 238 return fmt; 284 239 } ··· 339 290 340 291 /* parameter values */ 341 292 if (se->fields[i]->is_string) { 342 - trace_seq_printf(s, print_fmt, se->fields[i]->name, 343 - (char *)&entry->fields[n_u64], 344 - i == se->n_fields - 1 ? "" : " "); 345 - n_u64 += STR_VAR_LEN_MAX / sizeof(u64); 293 + if (se->fields[i]->is_dynamic) { 294 + u32 offset, data_offset; 295 + char *str_field; 296 + 297 + offset = (u32)entry->fields[n_u64]; 298 + data_offset = offset & 0xffff; 299 + 300 + str_field = (char *)entry + data_offset; 301 + 302 + trace_seq_printf(s, print_fmt, se->fields[i]->name, 303 + STR_VAR_LEN_MAX, 304 + str_field, 305 + i == se->n_fields - 1 ? "" : " "); 306 + n_u64++; 307 + } else { 308 + trace_seq_printf(s, print_fmt, se->fields[i]->name, 309 + STR_VAR_LEN_MAX, 310 + (char *)&entry->fields[n_u64], 311 + i == se->n_fields - 1 ? "" : " "); 312 + n_u64 += STR_VAR_LEN_MAX / sizeof(u64); 313 + } 346 314 } else { 347 315 struct trace_print_flags __flags[] = { 348 316 __def_gfpflag_names, {-1, NULL} }; ··· 391 325 .trace = print_synth_event 392 326 }; 393 327 328 + static unsigned int trace_string(struct synth_trace_event *entry, 329 + struct synth_event *event, 330 + char *str_val, 331 + bool is_dynamic, 332 + unsigned int data_size, 333 + unsigned int *n_u64) 334 + { 335 + unsigned int len = 0; 336 + char *str_field; 337 + 338 + if (is_dynamic) { 339 + u32 data_offset; 340 + 341 + data_offset = offsetof(typeof(*entry), fields); 342 + data_offset += event->n_u64 * sizeof(u64); 343 + data_offset += data_size; 344 + 345 + str_field = (char *)entry + data_offset; 346 + 347 + len = strlen(str_val) + 1; 348 + strscpy(str_field, str_val, len); 349 + 350 + data_offset |= len << 16; 351 + *(u32 *)&entry->fields[*n_u64] = data_offset; 352 + 353 + (*n_u64)++; 354 + } else { 355 + str_field = (char *)&entry->fields[*n_u64]; 356 + 357 + strscpy(str_field, str_val, STR_VAR_LEN_MAX); 358 + (*n_u64) += STR_VAR_LEN_MAX / sizeof(u64); 359 + } 360 + 361 + return len; 362 + } 363 + 394 364 static notrace void trace_event_raw_event_synth(void *__data, 395 365 u64 *var_ref_vals, 396 366 unsigned int *var_ref_idx) 397 367 { 368 + unsigned int i, n_u64, val_idx, len, data_size = 0; 398 369 struct trace_event_file *trace_file = __data; 399 370 struct synth_trace_event *entry; 400 371 struct trace_event_buffer fbuffer; 401 372 struct trace_buffer *buffer; 402 373 struct synth_event *event; 403 - unsigned int i, n_u64, val_idx; 404 374 int fields_size = 0; 405 375 406 376 event = trace_file->event_call->data; ··· 445 343 return; 446 344 447 345 fields_size = event->n_u64 * sizeof(u64); 346 + 347 + for (i = 0; i < event->n_dynamic_fields; i++) { 348 + unsigned int field_pos = event->dynamic_fields[i]->field_pos; 349 + char *str_val; 350 + 351 + val_idx = var_ref_idx[field_pos]; 352 + str_val = (char *)(long)var_ref_vals[val_idx]; 353 + 354 + len = strlen(str_val) + 1; 355 + 356 + fields_size += len; 357 + } 448 358 449 359 /* 450 360 * Avoid ring buffer recursion detection, as this event ··· 474 360 val_idx = var_ref_idx[i]; 475 361 if (event->fields[i]->is_string) { 476 362 char *str_val = (char *)(long)var_ref_vals[val_idx]; 477 - char *str_field = (char *)&entry->fields[n_u64]; 478 363 479 - strscpy(str_field, str_val, STR_VAR_LEN_MAX); 480 - n_u64 += STR_VAR_LEN_MAX / sizeof(u64); 364 + len = trace_string(entry, event, str_val, 365 + event->fields[i]->is_dynamic, 366 + data_size, &n_u64); 367 + data_size += len; /* only dynamic string increments */ 481 368 } else { 482 369 struct synth_field *field = event->fields[i]; 483 370 u64 val = var_ref_vals[val_idx]; ··· 537 422 pos += snprintf(buf + pos, LEN_OR_ZERO, "\""); 538 423 539 424 for (i = 0; i < event->n_fields; i++) { 540 - pos += snprintf(buf + pos, LEN_OR_ZERO, 541 - ", REC->%s", event->fields[i]->name); 425 + if (event->fields[i]->is_string && 426 + event->fields[i]->is_dynamic) 427 + pos += snprintf(buf + pos, LEN_OR_ZERO, 428 + ", __get_str(%s)", event->fields[i]->name); 429 + else 430 + pos += snprintf(buf + pos, LEN_OR_ZERO, 431 + ", REC->%s", event->fields[i]->name); 542 432 } 543 433 544 434 #undef LEN_OR_ZERO ··· 585 465 struct synth_field *field; 586 466 const char *prefix = NULL, *field_type = argv[0], *field_name, *array; 587 467 int len, ret = 0; 468 + ssize_t size; 588 469 589 470 if (field_type[0] == ';') 590 471 field_type++; 591 472 592 473 if (!strcmp(field_type, "unsigned")) { 593 - if (argc < 3) 474 + if (argc < 3) { 475 + synth_err(SYNTH_ERR_INCOMPLETE_TYPE, errpos(field_type)); 594 476 return ERR_PTR(-EINVAL); 477 + } 595 478 prefix = "unsigned "; 596 479 field_type = argv[1]; 597 480 field_name = argv[2]; ··· 620 497 ret = -ENOMEM; 621 498 goto free; 622 499 } 500 + if (!is_good_name(field->name)) { 501 + synth_err(SYNTH_ERR_BAD_NAME, errpos(field_name)); 502 + ret = -EINVAL; 503 + goto free; 504 + } 623 505 624 506 if (field_type[0] == ';') 625 507 field_type++; 626 508 len = strlen(field_type) + 1; 627 - if (array) 628 - len += strlen(array); 509 + 510 + if (array) { 511 + int l = strlen(array); 512 + 513 + if (l && array[l - 1] == ';') 514 + l--; 515 + len += l; 516 + } 629 517 if (prefix) 630 518 len += strlen(prefix); 631 519 ··· 654 520 field->type[len - 1] = '\0'; 655 521 } 656 522 657 - field->size = synth_field_size(field->type); 658 - if (!field->size) { 523 + size = synth_field_size(field->type); 524 + if (size < 0) { 525 + synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type)); 659 526 ret = -EINVAL; 660 527 goto free; 528 + } else if (size == 0) { 529 + if (synth_field_is_string(field->type)) { 530 + char *type; 531 + 532 + type = kzalloc(sizeof("__data_loc ") + strlen(field->type) + 1, GFP_KERNEL); 533 + if (!type) { 534 + ret = -ENOMEM; 535 + goto free; 536 + } 537 + 538 + strcat(type, "__data_loc "); 539 + strcat(type, field->type); 540 + kfree(field->type); 541 + field->type = type; 542 + 543 + field->is_dynamic = true; 544 + size = sizeof(u64); 545 + } else { 546 + synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type)); 547 + ret = -EINVAL; 548 + goto free; 549 + } 661 550 } 551 + field->size = size; 662 552 663 553 if (synth_field_is_string(field->type)) 664 554 field->is_string = true; 665 555 666 556 field->is_signed = synth_field_signed(field->type); 667 - 668 557 out: 669 558 return field; 670 559 free: ··· 818 661 free_synth_field(event->fields[i]); 819 662 820 663 kfree(event->fields); 664 + kfree(event->dynamic_fields); 821 665 kfree(event->name); 822 666 kfree(event->class.system); 823 667 free_synth_tracepoint(event->tp); ··· 829 671 static struct synth_event *alloc_synth_event(const char *name, int n_fields, 830 672 struct synth_field **fields) 831 673 { 674 + unsigned int i, j, n_dynamic_fields = 0; 832 675 struct synth_event *event; 833 - unsigned int i; 834 676 835 677 event = kzalloc(sizeof(*event), GFP_KERNEL); 836 678 if (!event) { ··· 852 694 goto out; 853 695 } 854 696 697 + for (i = 0; i < n_fields; i++) 698 + if (fields[i]->is_dynamic) 699 + n_dynamic_fields++; 700 + 701 + if (n_dynamic_fields) { 702 + event->dynamic_fields = kcalloc(n_dynamic_fields, 703 + sizeof(*event->dynamic_fields), 704 + GFP_KERNEL); 705 + if (!event->dynamic_fields) { 706 + free_synth_event(event); 707 + event = ERR_PTR(-ENOMEM); 708 + goto out; 709 + } 710 + } 711 + 855 712 dyn_event_init(&event->devent, &synth_event_ops); 856 713 857 - for (i = 0; i < n_fields; i++) 714 + for (i = 0, j = 0; i < n_fields; i++) { 858 715 event->fields[i] = fields[i]; 859 716 717 + if (fields[i]->is_dynamic) { 718 + event->dynamic_fields[j] = fields[i]; 719 + event->dynamic_fields[j]->field_pos = i; 720 + event->dynamic_fields[j++] = fields[i]; 721 + event->n_dynamic_fields++; 722 + } 723 + } 860 724 event->n_fields = n_fields; 861 725 out: 862 726 return event; ··· 890 710 int size; 891 711 892 712 size = synth_field_size((char *)arg_pair->lhs); 713 + if (size == 0) { 714 + if (strstr((char *)arg_pair->lhs, "[")) 715 + return 0; 716 + } 893 717 894 718 return size ? 0 : -EINVAL; 895 719 } ··· 1155 971 } 1156 972 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start); 1157 973 974 + static int save_cmdstr(int argc, const char *name, const char **argv) 975 + { 976 + struct seq_buf s; 977 + char *buf; 978 + int i; 979 + 980 + buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL); 981 + if (!buf) 982 + return -ENOMEM; 983 + 984 + seq_buf_init(&s, buf, MAX_DYNEVENT_CMD_LEN); 985 + 986 + seq_buf_puts(&s, name); 987 + 988 + for (i = 0; i < argc; i++) { 989 + seq_buf_putc(&s, ' '); 990 + seq_buf_puts(&s, argv[i]); 991 + } 992 + 993 + if (!seq_buf_buffer_left(&s)) { 994 + synth_err(SYNTH_ERR_CMD_TOO_LONG, 0); 995 + kfree(buf); 996 + return -EINVAL; 997 + } 998 + buf[s.len] = 0; 999 + last_cmd_set(buf); 1000 + 1001 + kfree(buf); 1002 + return 0; 1003 + } 1004 + 1158 1005 static int __create_synth_event(int argc, const char *name, const char **argv) 1159 1006 { 1160 1007 struct synth_field *field, *fields[SYNTH_FIELDS_MAX]; 1161 1008 struct synth_event *event = NULL; 1162 1009 int i, consumed = 0, n_fields = 0, ret = 0; 1010 + 1011 + ret = save_cmdstr(argc, name, argv); 1012 + if (ret) 1013 + return ret; 1163 1014 1164 1015 /* 1165 1016 * Argument syntax: ··· 1203 984 * where 'field' = type field_name 1204 985 */ 1205 986 1206 - if (name[0] == '\0' || argc < 1) 987 + if (name[0] == '\0' || argc < 1) { 988 + synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0); 1207 989 return -EINVAL; 990 + } 1208 991 1209 992 mutex_lock(&event_mutex); 1210 993 994 + if (!is_good_name(name)) { 995 + synth_err(SYNTH_ERR_BAD_NAME, errpos(name)); 996 + ret = -EINVAL; 997 + goto out; 998 + } 999 + 1211 1000 event = find_synth_event(name); 1212 1001 if (event) { 1002 + synth_err(SYNTH_ERR_EVENT_EXISTS, errpos(name)); 1213 1003 ret = -EEXIST; 1214 1004 goto out; 1215 1005 } ··· 1227 999 if (strcmp(argv[i], ";") == 0) 1228 1000 continue; 1229 1001 if (n_fields == SYNTH_FIELDS_MAX) { 1002 + synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0); 1230 1003 ret = -EINVAL; 1231 1004 goto err; 1232 1005 } ··· 1242 1013 } 1243 1014 1244 1015 if (i < argc && strcmp(argv[i], ";") != 0) { 1016 + synth_err(SYNTH_ERR_INVALID_FIELD, errpos(argv[i])); 1245 1017 ret = -EINVAL; 1246 1018 goto err; 1247 1019 } ··· 1428 1198 EXPORT_SYMBOL_GPL(synth_event_cmd_init); 1429 1199 1430 1200 static inline int 1431 - __synth_event_trace_start(struct trace_event_file *file, 1432 - struct synth_event_trace_state *trace_state) 1201 + __synth_event_trace_init(struct trace_event_file *file, 1202 + struct synth_event_trace_state *trace_state) 1433 1203 { 1434 - int entry_size, fields_size = 0; 1435 1204 int ret = 0; 1436 1205 1437 1206 memset(trace_state, '\0', sizeof(*trace_state)); ··· 1440 1211 * ENABLED bit is set (which attaches the probe thus allowing 1441 1212 * this code to be called, etc). Because this is called 1442 1213 * directly by the user, we don't have that but we still need 1443 - * to honor not logging when disabled. For the the iterated 1214 + * to honor not logging when disabled. For the iterated 1444 1215 * trace case, we save the enabed state upon start and just 1445 1216 * ignore the following data calls. 1446 1217 */ ··· 1452 1223 } 1453 1224 1454 1225 trace_state->event = file->event_call->data; 1226 + out: 1227 + return ret; 1228 + } 1229 + 1230 + static inline int 1231 + __synth_event_trace_start(struct trace_event_file *file, 1232 + struct synth_event_trace_state *trace_state, 1233 + int dynamic_fields_size) 1234 + { 1235 + int entry_size, fields_size = 0; 1236 + int ret = 0; 1455 1237 1456 1238 fields_size = trace_state->event->n_u64 * sizeof(u64); 1239 + fields_size += dynamic_fields_size; 1457 1240 1458 1241 /* 1459 1242 * Avoid ring buffer recursion detection, as this event ··· 1482 1241 ring_buffer_nest_end(trace_state->buffer); 1483 1242 ret = -EINVAL; 1484 1243 } 1485 - out: 1244 + 1486 1245 return ret; 1487 1246 } 1488 1247 ··· 1515 1274 */ 1516 1275 int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...) 1517 1276 { 1277 + unsigned int i, n_u64, len, data_size = 0; 1518 1278 struct synth_event_trace_state state; 1519 - unsigned int i, n_u64; 1520 1279 va_list args; 1521 1280 int ret; 1522 1281 1523 - ret = __synth_event_trace_start(file, &state); 1282 + ret = __synth_event_trace_init(file, &state); 1524 1283 if (ret) { 1525 1284 if (ret == -ENOENT) 1526 1285 ret = 0; /* just disabled, not really an error */ 1527 1286 return ret; 1528 1287 } 1529 1288 1289 + if (state.event->n_dynamic_fields) { 1290 + va_start(args, n_vals); 1291 + 1292 + for (i = 0; i < state.event->n_fields; i++) { 1293 + u64 val = va_arg(args, u64); 1294 + 1295 + if (state.event->fields[i]->is_string && 1296 + state.event->fields[i]->is_dynamic) { 1297 + char *str_val = (char *)(long)val; 1298 + 1299 + data_size += strlen(str_val) + 1; 1300 + } 1301 + } 1302 + 1303 + va_end(args); 1304 + } 1305 + 1306 + ret = __synth_event_trace_start(file, &state, data_size); 1307 + if (ret) 1308 + return ret; 1309 + 1530 1310 if (n_vals != state.event->n_fields) { 1531 1311 ret = -EINVAL; 1532 1312 goto out; 1533 1313 } 1314 + 1315 + data_size = 0; 1534 1316 1535 1317 va_start(args, n_vals); 1536 1318 for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) { ··· 1563 1299 1564 1300 if (state.event->fields[i]->is_string) { 1565 1301 char *str_val = (char *)(long)val; 1566 - char *str_field = (char *)&state.entry->fields[n_u64]; 1567 1302 1568 - strscpy(str_field, str_val, STR_VAR_LEN_MAX); 1569 - n_u64 += STR_VAR_LEN_MAX / sizeof(u64); 1303 + len = trace_string(state.entry, state.event, str_val, 1304 + state.event->fields[i]->is_dynamic, 1305 + data_size, &n_u64); 1306 + data_size += len; /* only dynamic string increments */ 1570 1307 } else { 1571 1308 struct synth_field *field = state.event->fields[i]; 1572 1309 ··· 1620 1355 int synth_event_trace_array(struct trace_event_file *file, u64 *vals, 1621 1356 unsigned int n_vals) 1622 1357 { 1358 + unsigned int i, n_u64, field_pos, len, data_size = 0; 1623 1359 struct synth_event_trace_state state; 1624 - unsigned int i, n_u64; 1360 + char *str_val; 1625 1361 int ret; 1626 1362 1627 - ret = __synth_event_trace_start(file, &state); 1363 + ret = __synth_event_trace_init(file, &state); 1628 1364 if (ret) { 1629 1365 if (ret == -ENOENT) 1630 1366 ret = 0; /* just disabled, not really an error */ 1631 1367 return ret; 1632 1368 } 1633 1369 1370 + if (state.event->n_dynamic_fields) { 1371 + for (i = 0; i < state.event->n_dynamic_fields; i++) { 1372 + field_pos = state.event->dynamic_fields[i]->field_pos; 1373 + str_val = (char *)(long)vals[field_pos]; 1374 + len = strlen(str_val) + 1; 1375 + data_size += len; 1376 + } 1377 + } 1378 + 1379 + ret = __synth_event_trace_start(file, &state, data_size); 1380 + if (ret) 1381 + return ret; 1382 + 1634 1383 if (n_vals != state.event->n_fields) { 1635 1384 ret = -EINVAL; 1636 1385 goto out; 1637 1386 } 1638 1387 1388 + data_size = 0; 1389 + 1639 1390 for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) { 1640 1391 if (state.event->fields[i]->is_string) { 1641 1392 char *str_val = (char *)(long)vals[i]; 1642 - char *str_field = (char *)&state.entry->fields[n_u64]; 1643 1393 1644 - strscpy(str_field, str_val, STR_VAR_LEN_MAX); 1645 - n_u64 += STR_VAR_LEN_MAX / sizeof(u64); 1394 + len = trace_string(state.entry, state.event, str_val, 1395 + state.event->fields[i]->is_dynamic, 1396 + data_size, &n_u64); 1397 + data_size += len; /* only dynamic string increments */ 1646 1398 } else { 1647 1399 struct synth_field *field = state.event->fields[i]; 1648 1400 u64 val = vals[i]; ··· 1727 1445 if (!trace_state) 1728 1446 return -EINVAL; 1729 1447 1730 - ret = __synth_event_trace_start(file, trace_state); 1731 - if (ret == -ENOENT) 1732 - ret = 0; /* just disabled, not really an error */ 1448 + ret = __synth_event_trace_init(file, trace_state); 1449 + if (ret) { 1450 + if (ret == -ENOENT) 1451 + ret = 0; /* just disabled, not really an error */ 1452 + return ret; 1453 + } 1454 + 1455 + if (trace_state->event->n_dynamic_fields) 1456 + return -ENOTSUPP; 1457 + 1458 + ret = __synth_event_trace_start(file, trace_state, 0); 1733 1459 1734 1460 return ret; 1735 1461 } ··· 1797 1507 if (field->is_string) { 1798 1508 char *str_val = (char *)(long)val; 1799 1509 char *str_field; 1510 + 1511 + if (field->is_dynamic) { /* add_val can't do dynamic strings */ 1512 + ret = -EINVAL; 1513 + goto out; 1514 + } 1800 1515 1801 1516 if (!str_val) { 1802 1517 ret = -EINVAL; ··· 1974 1679 { 1975 1680 struct synth_field *field; 1976 1681 unsigned int i; 1682 + char *type, *t; 1977 1683 1978 1684 seq_printf(m, "%s\t", event->name); 1979 1685 1980 1686 for (i = 0; i < event->n_fields; i++) { 1981 1687 field = event->fields[i]; 1982 1688 1689 + type = field->type; 1690 + t = strstr(type, "__data_loc"); 1691 + if (t) { /* __data_loc belongs in format but not event desc */ 1692 + t += sizeof("__data_loc"); 1693 + type = t; 1694 + } 1695 + 1983 1696 /* parameter values */ 1984 - seq_printf(m, "%s %s%s", field->type, field->name, 1697 + seq_printf(m, "%s %s%s", type, field->name, 1985 1698 i == event->n_fields - 1 ? "" : "; "); 1986 1699 } 1987 1700 ··· 2057 1754 .release = seq_release, 2058 1755 }; 2059 1756 2060 - static __init int trace_events_synth_init(void) 1757 + /* 1758 + * Register dynevent at core_initcall. This allows kernel to setup kprobe 1759 + * events in postcore_initcall without tracefs. 1760 + */ 1761 + static __init int trace_events_synth_init_early(void) 2061 1762 { 2062 - struct dentry *entry = NULL; 2063 - struct dentry *d_tracer; 2064 1763 int err = 0; 2065 1764 2066 1765 err = dyn_event_register(&synth_event_ops); 2067 - if (err) { 1766 + if (err) 2068 1767 pr_warn("Could not register synth_event_ops\n"); 2069 - return err; 2070 - } 2071 1768 2072 - d_tracer = tracing_init_dentry(); 2073 - if (IS_ERR(d_tracer)) { 2074 - err = PTR_ERR(d_tracer); 1769 + return err; 1770 + } 1771 + core_initcall(trace_events_synth_init_early); 1772 + 1773 + static __init int trace_events_synth_init(void) 1774 + { 1775 + struct dentry *entry = NULL; 1776 + int err = 0; 1777 + err = tracing_init_dentry(); 1778 + if (err) 2075 1779 goto err; 2076 - } 2077 1780 2078 - entry = tracefs_create_file("synthetic_events", 0644, d_tracer, 1781 + entry = tracefs_create_file("synthetic_events", 0644, NULL, 2079 1782 NULL, &synth_events_fops); 2080 1783 if (!entry) { 2081 1784 err = -ENODEV;
+14 -8
kernel/trace/trace_functions.c
··· 34 34 TRACE_FUNC_OPT_STACK = 0x1, 35 35 }; 36 36 37 - static int allocate_ftrace_ops(struct trace_array *tr) 37 + int ftrace_allocate_ftrace_ops(struct trace_array *tr) 38 38 { 39 39 struct ftrace_ops *ops; 40 + 41 + /* The top level array uses the "global_ops" */ 42 + if (tr->flags & TRACE_ARRAY_FL_GLOBAL) 43 + return 0; 40 44 41 45 ops = kzalloc(sizeof(*ops), GFP_KERNEL); 42 46 if (!ops) ··· 52 48 53 49 tr->ops = ops; 54 50 ops->private = tr; 51 + 55 52 return 0; 56 53 } 57 54 55 + void ftrace_free_ftrace_ops(struct trace_array *tr) 56 + { 57 + kfree(tr->ops); 58 + tr->ops = NULL; 59 + } 58 60 59 61 int ftrace_create_function_files(struct trace_array *tr, 60 62 struct dentry *parent) 61 63 { 62 - int ret; 63 - 64 64 /* 65 65 * The top level array uses the "global_ops", and the files are 66 66 * created on boot up. ··· 72 64 if (tr->flags & TRACE_ARRAY_FL_GLOBAL) 73 65 return 0; 74 66 75 - ret = allocate_ftrace_ops(tr); 76 - if (ret) 77 - return ret; 67 + if (!tr->ops) 68 + return -EINVAL; 78 69 79 70 ftrace_create_filter_files(tr->ops, parent); 80 71 ··· 83 76 void ftrace_destroy_function_files(struct trace_array *tr) 84 77 { 85 78 ftrace_destroy_filter_files(tr->ops); 86 - kfree(tr->ops); 87 - tr->ops = NULL; 79 + ftrace_free_ftrace_ops(tr); 88 80 } 89 81 90 82 static int function_trace_init(struct trace_array *tr)
+4 -4
kernel/trace/trace_functions_graph.c
··· 1336 1336 1337 1337 static __init int init_graph_tracefs(void) 1338 1338 { 1339 - struct dentry *d_tracer; 1339 + int ret; 1340 1340 1341 - d_tracer = tracing_init_dentry(); 1342 - if (IS_ERR(d_tracer)) 1341 + ret = tracing_init_dentry(); 1342 + if (ret) 1343 1343 return 0; 1344 1344 1345 - trace_create_file("max_graph_depth", 0644, d_tracer, 1345 + trace_create_file("max_graph_depth", 0644, NULL, 1346 1346 NULL, &graph_depth_fops); 1347 1347 1348 1348 return 0;
+4 -4
kernel/trace/trace_hwlat.c
··· 538 538 */ 539 539 static int init_tracefs(void) 540 540 { 541 - struct dentry *d_tracer; 541 + int ret; 542 542 struct dentry *top_dir; 543 543 544 - d_tracer = tracing_init_dentry(); 545 - if (IS_ERR(d_tracer)) 544 + ret = tracing_init_dentry(); 545 + if (ret) 546 546 return -ENOMEM; 547 547 548 - top_dir = tracefs_create_dir("hwlat_detector", d_tracer); 548 + top_dir = tracefs_create_dir("hwlat_detector", NULL); 549 549 if (!top_dir) 550 550 return -ENOMEM; 551 551
+25 -9
kernel/trace/trace_kprobe.c
··· 718 718 * p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS] 719 719 * - Add kretprobe: 720 720 * r[MAXACTIVE][:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS] 721 + * Or 722 + * p:[GRP/]EVENT] [MOD:]KSYM[+0]%return [FETCHARGS] 723 + * 721 724 * Fetch args: 722 725 * $retval : fetch return value 723 726 * $stack : fetch stack address ··· 750 747 switch (argv[0][0]) { 751 748 case 'r': 752 749 is_return = true; 753 - flags |= TPARG_FL_RETURN; 754 750 break; 755 751 case 'p': 756 752 break; ··· 807 805 symbol = kstrdup(argv[1], GFP_KERNEL); 808 806 if (!symbol) 809 807 return -ENOMEM; 808 + 809 + tmp = strchr(symbol, '%'); 810 + if (tmp) { 811 + if (!strcmp(tmp, "%return")) { 812 + *tmp = '\0'; 813 + is_return = true; 814 + } else { 815 + trace_probe_log_err(tmp - symbol, BAD_ADDR_SUFFIX); 816 + goto parse_error; 817 + } 818 + } 819 + 810 820 /* TODO: support .init module functions */ 811 821 ret = traceprobe_split_symbol_offset(symbol, &offset); 812 822 if (ret || offset < 0 || offset > UINT_MAX) { 813 823 trace_probe_log_err(0, BAD_PROBE_ADDR); 814 824 goto parse_error; 815 825 } 826 + if (is_return) 827 + flags |= TPARG_FL_RETURN; 816 828 if (kprobe_on_func_entry(NULL, symbol, offset)) 817 829 flags |= TPARG_FL_FENTRY; 818 830 if (offset && is_return && !(flags & TPARG_FL_FENTRY)) { ··· 1897 1881 } 1898 1882 1899 1883 /* 1900 - * Register dynevent at subsys_initcall. This allows kernel to setup kprobe 1901 - * events in fs_initcall without tracefs. 1884 + * Register dynevent at core_initcall. This allows kernel to setup kprobe 1885 + * events in postcore_initcall without tracefs. 1902 1886 */ 1903 1887 static __init int init_kprobe_trace_early(void) 1904 1888 { ··· 1913 1897 1914 1898 return 0; 1915 1899 } 1916 - subsys_initcall(init_kprobe_trace_early); 1900 + core_initcall(init_kprobe_trace_early); 1917 1901 1918 1902 /* Make a tracefs interface for controlling probe points */ 1919 1903 static __init int init_kprobe_trace(void) 1920 1904 { 1921 - struct dentry *d_tracer; 1905 + int ret; 1922 1906 struct dentry *entry; 1923 1907 1924 - d_tracer = tracing_init_dentry(); 1925 - if (IS_ERR(d_tracer)) 1908 + ret = tracing_init_dentry(); 1909 + if (ret) 1926 1910 return 0; 1927 1911 1928 - entry = tracefs_create_file("kprobe_events", 0644, d_tracer, 1912 + entry = tracefs_create_file("kprobe_events", 0644, NULL, 1929 1913 NULL, &kprobe_events_ops); 1930 1914 1931 1915 /* Event list interface */ ··· 1933 1917 pr_warn("Could not create tracefs 'kprobe_events' entry\n"); 1934 1918 1935 1919 /* Profile interface */ 1936 - entry = tracefs_create_file("kprobe_profile", 0444, d_tracer, 1920 + entry = tracefs_create_file("kprobe_profile", 0444, NULL, 1937 1921 NULL, &kprobe_profile_ops); 1938 1922 1939 1923 if (!entry)
+4 -4
kernel/trace/trace_printk.c
··· 367 367 368 368 static __init int init_trace_printk_function_export(void) 369 369 { 370 - struct dentry *d_tracer; 370 + int ret; 371 371 372 - d_tracer = tracing_init_dentry(); 373 - if (IS_ERR(d_tracer)) 372 + ret = tracing_init_dentry(); 373 + if (ret) 374 374 return 0; 375 375 376 - trace_create_file("printk_formats", 0444, d_tracer, 376 + trace_create_file("printk_formats", 0444, NULL, 377 377 NULL, &ftrace_formats_fops); 378 378 379 379 return 0;
+1 -13
kernel/trace/trace_probe.h
··· 16 16 #include <linux/tracefs.h> 17 17 #include <linux/types.h> 18 18 #include <linux/string.h> 19 - #include <linux/ctype.h> 20 19 #include <linux/ptrace.h> 21 20 #include <linux/perf_event.h> 22 21 #include <linux/kprobes.h> ··· 347 348 #define trace_probe_for_each_link_rcu(pos, tp) \ 348 349 list_for_each_entry_rcu(pos, &(tp)->event->files, list) 349 350 350 - /* Check the name is good for event/group/fields */ 351 - static inline bool is_good_name(const char *name) 352 - { 353 - if (!isalpha(*name) && *name != '_') 354 - return false; 355 - while (*++name != '\0') { 356 - if (!isalpha(*name) && !isdigit(*name) && *name != '_') 357 - return false; 358 - } 359 - return true; 360 - } 361 - 362 351 #define TPARG_FL_RETURN BIT(0) 363 352 #define TPARG_FL_KERNEL BIT(1) 364 353 #define TPARG_FL_FENTRY BIT(2) ··· 391 404 C(MAXACT_TOO_BIG, "Maxactive is too big"), \ 392 405 C(BAD_PROBE_ADDR, "Invalid probed address or symbol"), \ 393 406 C(BAD_RETPROBE, "Retprobe address must be an function entry"), \ 407 + C(BAD_ADDR_SUFFIX, "Invalid probed address suffix"), \ 394 408 C(NO_GROUP_NAME, "Group name is not specified"), \ 395 409 C(GROUP_TOO_LONG, "Group name is too long"), \ 396 410 C(BAD_GROUP_NAME, "Group name must follow the same rules as C identifiers"), \
+6 -6
kernel/trace/trace_stack.c
··· 554 554 555 555 static __init int stack_trace_init(void) 556 556 { 557 - struct dentry *d_tracer; 557 + int ret; 558 558 559 - d_tracer = tracing_init_dentry(); 560 - if (IS_ERR(d_tracer)) 559 + ret = tracing_init_dentry(); 560 + if (ret) 561 561 return 0; 562 562 563 - trace_create_file("stack_max_size", 0644, d_tracer, 563 + trace_create_file("stack_max_size", 0644, NULL, 564 564 &stack_trace_max_size, &stack_max_size_fops); 565 565 566 - trace_create_file("stack_trace", 0444, d_tracer, 566 + trace_create_file("stack_trace", 0444, NULL, 567 567 NULL, &stack_trace_fops); 568 568 569 569 #ifdef CONFIG_DYNAMIC_FTRACE 570 - trace_create_file("stack_trace_filter", 0644, d_tracer, 570 + trace_create_file("stack_trace_filter", 0644, NULL, 571 571 &trace_ops, &stack_trace_filter_fops); 572 572 #endif 573 573
+4 -4
kernel/trace/trace_stat.c
··· 276 276 277 277 static int tracing_stat_init(void) 278 278 { 279 - struct dentry *d_tracing; 279 + int ret; 280 280 281 - d_tracing = tracing_init_dentry(); 282 - if (IS_ERR(d_tracing)) 281 + ret = tracing_init_dentry(); 282 + if (ret) 283 283 return -ENODEV; 284 284 285 - stat_dir = tracefs_create_dir("trace_stat", d_tracing); 285 + stat_dir = tracefs_create_dir("trace_stat", NULL); 286 286 if (!stat_dir) { 287 287 pr_warn("Could not create tracefs 'trace_stat' entry\n"); 288 288 return -ENOMEM;
+5 -1
kernel/trace/trace_synth.h
··· 7 7 #define SYNTH_SYSTEM "synthetic" 8 8 #define SYNTH_FIELDS_MAX 32 9 9 10 - #define STR_VAR_LEN_MAX 32 /* must be multiple of sizeof(u64) */ 10 + #define STR_VAR_LEN_MAX MAX_FILTER_STR_VAL /* must be multiple of sizeof(u64) */ 11 11 12 12 struct synth_field { 13 13 char *type; ··· 16 16 unsigned int offset; 17 17 bool is_signed; 18 18 bool is_string; 19 + bool is_dynamic; 20 + bool field_pos; 19 21 }; 20 22 21 23 struct synth_event { ··· 26 24 char *name; 27 25 struct synth_field **fields; 28 26 unsigned int n_fields; 27 + struct synth_field **dynamic_fields; 28 + unsigned int n_dynamic_fields; 29 29 unsigned int n_u64; 30 30 struct trace_event_class class; 31 31 struct trace_event_call call;
+18 -6
kernel/trace/trace_uprobe.c
··· 528 528 529 529 /* 530 530 * Argument syntax: 531 - * - Add uprobe: p|r[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] 531 + * - Add uprobe: p|r[:[GRP/]EVENT] PATH:OFFSET[%return][(REF)] [FETCHARGS] 532 532 */ 533 533 static int trace_uprobe_create(int argc, const char **argv) 534 534 { ··· 613 613 ret = kstrtoul(rctr, 0, &ref_ctr_offset); 614 614 if (ret) { 615 615 trace_probe_log_err(rctr - filename, BAD_REFCNT); 616 + goto fail_address_parse; 617 + } 618 + } 619 + 620 + /* Check if there is %return suffix */ 621 + tmp = strchr(arg, '%'); 622 + if (tmp) { 623 + if (!strcmp(tmp, "%return")) { 624 + *tmp = '\0'; 625 + is_return = true; 626 + } else { 627 + trace_probe_log_err(tmp - filename, BAD_ADDR_SUFFIX); 628 + ret = -EINVAL; 616 629 goto fail_address_parse; 617 630 } 618 631 } ··· 1638 1625 /* Make a trace interface for controling probe points */ 1639 1626 static __init int init_uprobe_trace(void) 1640 1627 { 1641 - struct dentry *d_tracer; 1642 1628 int ret; 1643 1629 1644 1630 ret = dyn_event_register(&trace_uprobe_ops); 1645 1631 if (ret) 1646 1632 return ret; 1647 1633 1648 - d_tracer = tracing_init_dentry(); 1649 - if (IS_ERR(d_tracer)) 1634 + ret = tracing_init_dentry(); 1635 + if (ret) 1650 1636 return 0; 1651 1637 1652 - trace_create_file("uprobe_events", 0644, d_tracer, 1638 + trace_create_file("uprobe_events", 0644, NULL, 1653 1639 NULL, &uprobe_events_ops); 1654 1640 /* Profile interface */ 1655 - trace_create_file("uprobe_profile", 0444, d_tracer, 1641 + trace_create_file("uprobe_profile", 0444, NULL, 1656 1642 NULL, &uprobe_profile_ops); 1657 1643 return 0; 1658 1644 }
+1 -1
kernel/trace/tracing_map.c
··· 260 260 * to use cmp_fn. 261 261 * 262 262 * A key can be a subset of a compound key; for that purpose, the 263 - * offset param is used to describe where within the the compound key 263 + * offset param is used to describe where within the compound key 264 264 * the key referenced by this key field resides. 265 265 * 266 266 * Return: The index identifying the field in the map and associated
+105 -42
tools/bootconfig/main.c
··· 14 14 #include <linux/kernel.h> 15 15 #include <linux/bootconfig.h> 16 16 17 - static int xbc_show_value(struct xbc_node *node) 17 + static int xbc_show_value(struct xbc_node *node, bool semicolon) 18 18 { 19 - const char *val; 19 + const char *val, *eol; 20 20 char q; 21 21 int i = 0; 22 22 23 + eol = semicolon ? ";\n" : "\n"; 23 24 xbc_array_for_each_value(node, val) { 24 25 if (strchr(val, '"')) 25 26 q = '\''; 26 27 else 27 28 q = '"'; 28 - printf("%c%s%c%s", q, val, q, node->next ? ", " : ";\n"); 29 + printf("%c%s%c%s", q, val, q, node->next ? ", " : eol); 29 30 i++; 30 31 } 31 32 return i; ··· 54 53 continue; 55 54 } else if (cnode && xbc_node_is_value(cnode)) { 56 55 printf("%s = ", xbc_node_get_data(node)); 57 - xbc_show_value(cnode); 56 + xbc_show_value(cnode, true); 58 57 } else { 59 58 printf("%s;\n", xbc_node_get_data(node)); 60 59 } ··· 78 77 } 79 78 } 80 79 80 + static void xbc_show_list(void) 81 + { 82 + char key[XBC_KEYLEN_MAX]; 83 + struct xbc_node *leaf; 84 + const char *val; 85 + int ret = 0; 86 + 87 + xbc_for_each_key_value(leaf, val) { 88 + ret = xbc_node_compose_key(leaf, key, XBC_KEYLEN_MAX); 89 + if (ret < 0) 90 + break; 91 + printf("%s = ", key); 92 + if (!val || val[0] == '\0') { 93 + printf("\"\"\n"); 94 + continue; 95 + } 96 + xbc_show_value(xbc_node_get_child(leaf), false); 97 + } 98 + } 99 + 81 100 /* Simple real checksum */ 82 - int checksum(unsigned char *buf, int len) 101 + static int checksum(unsigned char *buf, int len) 83 102 { 84 103 int i, sum = 0; 85 104 ··· 111 90 112 91 #define PAGE_SIZE 4096 113 92 114 - int load_xbc_fd(int fd, char **buf, int size) 93 + static int load_xbc_fd(int fd, char **buf, int size) 115 94 { 116 95 int ret; 117 96 ··· 128 107 } 129 108 130 109 /* Return the read size or -errno */ 131 - int load_xbc_file(const char *path, char **buf) 110 + static int load_xbc_file(const char *path, char **buf) 132 111 { 133 112 struct stat stat; 134 113 int fd, ret; ··· 147 126 return ret; 148 127 } 149 128 150 - int load_xbc_from_initrd(int fd, char **buf) 129 + static int load_xbc_from_initrd(int fd, char **buf) 151 130 { 152 131 struct stat stat; 153 132 int ret; ··· 216 195 return size; 217 196 } 218 197 219 - int show_xbc(const char *path) 198 + static void show_xbc_error(const char *data, const char *msg, int pos) 199 + { 200 + int lin = 1, col, i; 201 + 202 + if (pos < 0) { 203 + pr_err("Error: %s.\n", msg); 204 + return; 205 + } 206 + 207 + /* Note that pos starts from 0 but lin and col should start from 1. */ 208 + col = pos + 1; 209 + for (i = 0; i < pos; i++) { 210 + if (data[i] == '\n') { 211 + lin++; 212 + col = pos - i; 213 + } 214 + } 215 + pr_err("Parse Error: %s at %d:%d\n", msg, lin, col); 216 + 217 + } 218 + 219 + static int init_xbc_with_error(char *buf, int len) 220 + { 221 + char *copy = strdup(buf); 222 + const char *msg; 223 + int ret, pos; 224 + 225 + if (!copy) 226 + return -ENOMEM; 227 + 228 + ret = xbc_init(buf, &msg, &pos); 229 + if (ret < 0) 230 + show_xbc_error(copy, msg, pos); 231 + free(copy); 232 + 233 + return ret; 234 + } 235 + 236 + static int show_xbc(const char *path, bool list) 220 237 { 221 238 int ret, fd; 222 239 char *buf = NULL; 240 + struct stat st; 241 + 242 + ret = stat(path, &st); 243 + if (ret < 0) { 244 + pr_err("Failed to stat %s: %d\n", path, -errno); 245 + return -errno; 246 + } 223 247 224 248 fd = open(path, O_RDONLY); 225 249 if (fd < 0) { ··· 273 207 } 274 208 275 209 ret = load_xbc_from_initrd(fd, &buf); 210 + close(fd); 276 211 if (ret < 0) { 277 212 pr_err("Failed to load a boot config from initrd: %d\n", ret); 278 213 goto out; 279 214 } 280 - xbc_show_compact_tree(); 215 + /* Assume a bootconfig file if it is enough small */ 216 + if (ret == 0 && st.st_size <= XBC_DATA_MAX) { 217 + ret = load_xbc_file(path, &buf); 218 + if (ret < 0) { 219 + pr_err("Failed to load a boot config: %d\n", ret); 220 + goto out; 221 + } 222 + if (init_xbc_with_error(buf, ret) < 0) 223 + goto out; 224 + } 225 + if (list) 226 + xbc_show_list(); 227 + else 228 + xbc_show_compact_tree(); 281 229 ret = 0; 282 230 out: 283 - close(fd); 284 231 free(buf); 285 232 286 233 return ret; 287 234 } 288 235 289 - int delete_xbc(const char *path) 236 + static int delete_xbc(const char *path) 290 237 { 291 238 struct stat stat; 292 239 int ret = 0, fd, size; ··· 330 251 return ret; 331 252 } 332 253 333 - static void show_xbc_error(const char *data, const char *msg, int pos) 334 - { 335 - int lin = 1, col, i; 336 - 337 - if (pos < 0) { 338 - pr_err("Error: %s.\n", msg); 339 - return; 340 - } 341 - 342 - /* Note that pos starts from 0 but lin and col should start from 1. */ 343 - col = pos + 1; 344 - for (i = 0; i < pos; i++) { 345 - if (data[i] == '\n') { 346 - lin++; 347 - col = pos - i; 348 - } 349 - } 350 - pr_err("Parse Error: %s at %d:%d\n", msg, lin, col); 351 - 352 - } 353 - 354 - int apply_xbc(const char *path, const char *xbc_path) 254 + static int apply_xbc(const char *path, const char *xbc_path) 355 255 { 356 256 u32 size, csum; 357 257 char *buf, *data; ··· 407 349 return ret; 408 350 } 409 351 410 - int usage(void) 352 + static int usage(void) 411 353 { 412 354 printf("Usage: bootconfig [OPTIONS] <INITRD>\n" 355 + "Or bootconfig <CONFIG>\n" 413 356 " Apply, delete or show boot config to initrd.\n" 414 357 " Options:\n" 415 358 " -a <config>: Apply boot config to initrd\n" 416 - " -d : Delete boot config file from initrd\n\n" 417 - " If no option is given, show current applied boot config.\n"); 359 + " -d : Delete boot config file from initrd\n" 360 + " -l : list boot config in initrd or file\n\n" 361 + " If no option is given, show the bootconfig in the given file.\n"); 418 362 return -1; 419 363 } 420 364 ··· 424 364 { 425 365 char *path = NULL; 426 366 char *apply = NULL; 427 - bool delete = false; 367 + bool delete = false, list = false; 428 368 int opt; 429 369 430 - while ((opt = getopt(argc, argv, "hda:")) != -1) { 370 + while ((opt = getopt(argc, argv, "hda:l")) != -1) { 431 371 switch (opt) { 432 372 case 'd': 433 373 delete = true; ··· 435 375 case 'a': 436 376 apply = optarg; 437 377 break; 378 + case 'l': 379 + list = true; 380 + break; 438 381 case 'h': 439 382 default: 440 383 return usage(); 441 384 } 442 385 } 443 386 444 - if (apply && delete) { 445 - pr_err("Error: You can not specify both -a and -d at once.\n"); 387 + if ((apply && delete) || (delete && list) || (apply && list)) { 388 + pr_err("Error: You can give one of -a, -d or -l at once.\n"); 446 389 return usage(); 447 390 } 448 391 ··· 461 398 else if (delete) 462 399 return delete_xbc(path); 463 400 464 - return show_xbc(path); 401 + return show_xbc(path, list); 465 402 }
+199
tools/bootconfig/scripts/bconf2ftrace.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0-only 3 + 4 + usage() { 5 + echo "Ftrace boottime trace test tool" 6 + echo "Usage: $0 [--apply|--init] [--debug] BOOTCONFIG-FILE" 7 + echo " --apply: Test actual apply to tracefs (need sudo)" 8 + echo " --init: Initialize ftrace before applying (imply --apply)" 9 + exit 1 10 + } 11 + 12 + [ $# -eq 0 ] && usage 13 + 14 + BCONF= 15 + DEBUG= 16 + APPLY= 17 + INIT= 18 + while [ x"$1" != x ]; do 19 + case "$1" in 20 + "--debug") 21 + DEBUG=$1;; 22 + "--apply") 23 + APPLY=$1;; 24 + "--init") 25 + APPLY=$1 26 + INIT=$1;; 27 + *) 28 + [ ! -f $1 ] && usage 29 + BCONF=$1;; 30 + esac 31 + shift 1 32 + done 33 + 34 + if [ x"$APPLY" != x ]; then 35 + if [ `id -u` -ne 0 ]; then 36 + echo "This must be run by root user. Try sudo." 1>&2 37 + exec sudo $0 $DEBUG $APPLY $BCONF 38 + fi 39 + fi 40 + 41 + run_cmd() { # command 42 + echo "$*" 43 + if [ x"$APPLY" != x ]; then # apply command 44 + eval $* 45 + fi 46 + } 47 + 48 + if [ x"$DEBUG" != x ]; then 49 + set -x 50 + fi 51 + 52 + TRACEFS=`grep -m 1 -w tracefs /proc/mounts | cut -f 2 -d " "` 53 + if [ -z "$TRACEFS" ]; then 54 + if ! grep -wq debugfs /proc/mounts; then 55 + echo "Error: No tracefs/debugfs was mounted." 1>&2 56 + exit 1 57 + fi 58 + TRACEFS=`grep -m 1 -w debugfs /proc/mounts | cut -f 2 -d " "`/tracing 59 + if [ ! -d $TRACEFS ]; then 60 + echo "Error: ftrace is not enabled on this kernel." 1>&2 61 + exit 1 62 + fi 63 + fi 64 + 65 + if [ x"$INIT" != x ]; then 66 + . `dirname $0`/ftrace.sh 67 + (cd $TRACEFS; initialize_ftrace) 68 + fi 69 + 70 + . `dirname $0`/xbc.sh 71 + 72 + ######## main ######### 73 + set -e 74 + 75 + xbc_init $BCONF 76 + 77 + set_value_of() { # key file 78 + if xbc_has_key $1; then 79 + val=`xbc_get_val $1 1` 80 + run_cmd "echo '$val' >> $2" 81 + fi 82 + } 83 + 84 + set_array_of() { # key file 85 + if xbc_has_key $1; then 86 + xbc_get_val $1 | while read line; do 87 + run_cmd "echo '$line' >> $2" 88 + done 89 + fi 90 + } 91 + 92 + compose_synth() { # event_name branch 93 + echo -n "$1 " 94 + xbc_get_val $2 | while read field; do echo -n "$field; "; done 95 + } 96 + 97 + setup_event() { # prefix group event [instance] 98 + branch=$1.$2.$3 99 + if [ "$4" ]; then 100 + eventdir="$TRACEFS/instances/$4/events/$2/$3" 101 + else 102 + eventdir="$TRACEFS/events/$2/$3" 103 + fi 104 + case $2 in 105 + kprobes) 106 + xbc_get_val ${branch}.probes | while read line; do 107 + run_cmd "echo 'p:kprobes/$3 $line' >> $TRACEFS/kprobe_events" 108 + done 109 + ;; 110 + synthetic) 111 + run_cmd "echo '`compose_synth $3 ${branch}.fields`' >> $TRACEFS/synthetic_events" 112 + ;; 113 + esac 114 + 115 + set_value_of ${branch}.filter ${eventdir}/filter 116 + set_array_of ${branch}.actions ${eventdir}/trigger 117 + 118 + if xbc_has_key ${branch}.enable; then 119 + run_cmd "echo 1 > ${eventdir}/enable" 120 + fi 121 + } 122 + 123 + setup_events() { # prefix("ftrace" or "ftrace.instance.INSTANCE") [instance] 124 + prefix="${1}.event" 125 + if xbc_has_branch ${1}.event; then 126 + for grpev in `xbc_subkeys ${1}.event 2`; do 127 + setup_event $prefix ${grpev%.*} ${grpev#*.} $2 128 + done 129 + fi 130 + } 131 + 132 + size2kb() { # size[KB|MB] 133 + case $1 in 134 + *KB) 135 + echo ${1%KB};; 136 + *MB) 137 + expr ${1%MB} \* 1024;; 138 + *) 139 + expr $1 / 1024 ;; 140 + esac 141 + } 142 + 143 + setup_instance() { # [instance] 144 + if [ "$1" ]; then 145 + instance="ftrace.instance.${1}" 146 + instancedir=$TRACEFS/instances/$1 147 + else 148 + instance="ftrace" 149 + instancedir=$TRACEFS 150 + fi 151 + 152 + set_array_of ${instance}.options ${instancedir}/trace_options 153 + set_value_of ${instance}.trace_clock ${instancedir}/trace_clock 154 + set_value_of ${instance}.cpumask ${instancedir}/tracing_cpumask 155 + set_value_of ${instance}.tracer ${instancedir}/current_tracer 156 + set_array_of ${instance}.ftrace.filters \ 157 + ${instancedir}/set_ftrace_filter 158 + set_array_of ${instance}.ftrace.notrace \ 159 + ${instancedir}/set_ftrace_notrace 160 + 161 + if xbc_has_key ${instance}.alloc_snapshot; then 162 + run_cmd "echo 1 > ${instancedir}/snapshot" 163 + fi 164 + 165 + if xbc_has_key ${instance}.buffer_size; then 166 + size=`xbc_get_val ${instance}.buffer_size 1` 167 + size=`eval size2kb $size` 168 + run_cmd "echo $size >> ${instancedir}/buffer_size_kb" 169 + fi 170 + 171 + setup_events ${instance} $1 172 + set_array_of ${instance}.events ${instancedir}/set_event 173 + } 174 + 175 + # ftrace global configs (kernel.*) 176 + if xbc_has_key "kernel.dump_on_oops"; then 177 + dump_mode=`xbc_get_val "kernel.dump_on_oops" 1` 178 + [ "$dump_mode" ] && dump_mode=`eval echo $dump_mode` || dump_mode=1 179 + run_cmd "echo \"$dump_mode\" > /proc/sys/kernel/ftrace_dump_on_oops" 180 + fi 181 + 182 + set_value_of kernel.fgraph_max_depth $TRACEFS/max_graph_depth 183 + set_array_of kernel.fgraph_filters $TRACEFS/set_graph_function 184 + set_array_of kernel.fgraph_notraces $TRACEFS/set_graph_notrace 185 + 186 + # Per-instance/per-event configs 187 + if ! xbc_has_branch "ftrace" ; then 188 + exit 0 189 + fi 190 + 191 + setup_instance # root instance 192 + 193 + if xbc_has_branch "ftrace.instance"; then 194 + for i in `xbc_subkeys "ftrace.instance" 1`; do 195 + run_cmd "mkdir -p $TRACEFS/instances/$i" 196 + setup_instance $i 197 + done 198 + fi 199 +
+109
tools/bootconfig/scripts/ftrace.sh
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + 3 + clear_trace() { # reset trace output 4 + echo > trace 5 + } 6 + 7 + disable_tracing() { # stop trace recording 8 + echo 0 > tracing_on 9 + } 10 + 11 + enable_tracing() { # start trace recording 12 + echo 1 > tracing_on 13 + } 14 + 15 + reset_tracer() { # reset the current tracer 16 + echo nop > current_tracer 17 + } 18 + 19 + reset_trigger_file() { 20 + # remove action triggers first 21 + grep -H ':on[^:]*(' $@ | 22 + while read line; do 23 + cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["` 24 + file=`echo $line | cut -f1 -d:` 25 + echo "!$cmd" >> $file 26 + done 27 + grep -Hv ^# $@ | 28 + while read line; do 29 + cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["` 30 + file=`echo $line | cut -f1 -d:` 31 + echo "!$cmd" > $file 32 + done 33 + } 34 + 35 + reset_trigger() { # reset all current setting triggers 36 + if [ -d events/synthetic ]; then 37 + reset_trigger_file events/synthetic/*/trigger 38 + fi 39 + reset_trigger_file events/*/*/trigger 40 + } 41 + 42 + reset_events_filter() { # reset all current setting filters 43 + grep -v ^none events/*/*/filter | 44 + while read line; do 45 + echo 0 > `echo $line | cut -f1 -d:` 46 + done 47 + } 48 + 49 + reset_ftrace_filter() { # reset all triggers in set_ftrace_filter 50 + if [ ! -f set_ftrace_filter ]; then 51 + return 0 52 + fi 53 + echo > set_ftrace_filter 54 + grep -v '^#' set_ftrace_filter | while read t; do 55 + tr=`echo $t | cut -d: -f2` 56 + if [ "$tr" = "" ]; then 57 + continue 58 + fi 59 + if ! grep -q "$t" set_ftrace_filter; then 60 + continue; 61 + fi 62 + name=`echo $t | cut -d: -f1 | cut -d' ' -f1` 63 + if [ $tr = "enable_event" -o $tr = "disable_event" ]; then 64 + tr=`echo $t | cut -d: -f2-4` 65 + limit=`echo $t | cut -d: -f5` 66 + else 67 + tr=`echo $t | cut -d: -f2` 68 + limit=`echo $t | cut -d: -f3` 69 + fi 70 + if [ "$limit" != "unlimited" ]; then 71 + tr="$tr:$limit" 72 + fi 73 + echo "!$name:$tr" > set_ftrace_filter 74 + done 75 + } 76 + 77 + disable_events() { 78 + echo 0 > events/enable 79 + } 80 + 81 + clear_synthetic_events() { # reset all current synthetic events 82 + grep -v ^# synthetic_events | 83 + while read line; do 84 + echo "!$line" >> synthetic_events 85 + done 86 + } 87 + 88 + initialize_ftrace() { # Reset ftrace to initial-state 89 + # As the initial state, ftrace will be set to nop tracer, 90 + # no events, no triggers, no filters, no function filters, 91 + # no probes, and tracing on. 92 + disable_tracing 93 + reset_tracer 94 + reset_trigger 95 + reset_events_filter 96 + reset_ftrace_filter 97 + disable_events 98 + [ -f set_event_pid ] && echo > set_event_pid 99 + [ -f set_ftrace_pid ] && echo > set_ftrace_pid 100 + [ -f set_ftrace_notrace ] && echo > set_ftrace_notrace 101 + [ -f set_graph_function ] && echo | tee set_graph_* 102 + [ -f stack_trace_filter ] && echo > stack_trace_filter 103 + [ -f kprobe_events ] && echo > kprobe_events 104 + [ -f uprobe_events ] && echo > uprobe_events 105 + [ -f synthetic_events ] && echo > synthetic_events 106 + [ -f snapshot ] && echo 0 > snapshot 107 + clear_trace 108 + enable_tracing 109 + }
+244
tools/bootconfig/scripts/ftrace2bconf.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0-only 3 + 4 + usage() { 5 + echo "Dump boot-time tracing bootconfig from ftrace" 6 + echo "Usage: $0 [--debug] [ > BOOTCONFIG-FILE]" 7 + exit 1 8 + } 9 + 10 + DEBUG= 11 + while [ x"$1" != x ]; do 12 + case "$1" in 13 + "--debug") 14 + DEBUG=$1;; 15 + -*) 16 + usage 17 + ;; 18 + esac 19 + shift 1 20 + done 21 + 22 + if [ x"$DEBUG" != x ]; then 23 + set -x 24 + fi 25 + 26 + TRACEFS=`grep -m 1 -w tracefs /proc/mounts | cut -f 2 -d " "` 27 + if [ -z "$TRACEFS" ]; then 28 + if ! grep -wq debugfs /proc/mounts; then 29 + echo "Error: No tracefs/debugfs was mounted." 30 + exit 1 31 + fi 32 + TRACEFS=`grep -m 1 -w debugfs /proc/mounts | cut -f 2 -d " "`/tracing 33 + if [ ! -d $TRACEFS ]; then 34 + echo "Error: ftrace is not enabled on this kernel." 1>&2 35 + exit 1 36 + fi 37 + fi 38 + 39 + ######## main ######### 40 + 41 + set -e 42 + 43 + emit_kv() { # key =|+= value 44 + echo "$@" 45 + } 46 + 47 + global_options() { 48 + val=`cat $TRACEFS/max_graph_depth` 49 + [ $val != 0 ] && emit_kv kernel.fgraph_max_depth = $val 50 + if grep -qv "^#" $TRACEFS/set_graph_function $TRACEFS/set_graph_notrace ; then 51 + cat 1>&2 << EOF 52 + # WARN: kernel.fgraph_filters and kernel.fgraph_notrace are not supported, since the wild card expression was expanded and lost from memory. 53 + EOF 54 + fi 55 + } 56 + 57 + kprobe_event_options() { 58 + cat $TRACEFS/kprobe_events | while read p args; do 59 + case $p in 60 + r*) 61 + cat 1>&2 << EOF 62 + # WARN: A return probe found but it is not supported by bootconfig. Skip it. 63 + EOF 64 + continue;; 65 + esac 66 + p=${p#*:} 67 + event=${p#*/} 68 + group=${p%/*} 69 + if [ $group != "kprobes" ]; then 70 + cat 1>&2 << EOF 71 + # WARN: kprobes group name $group is changed to "kprobes" for bootconfig. 72 + EOF 73 + fi 74 + emit_kv $PREFIX.event.kprobes.$event.probes += $args 75 + done 76 + } 77 + 78 + synth_event_options() { 79 + cat $TRACEFS/synthetic_events | while read event fields; do 80 + emit_kv $PREFIX.event.synthetic.$event.fields = `echo $fields | sed "s/;/,/g"` 81 + done 82 + } 83 + 84 + # Variables resolver 85 + DEFINED_VARS= 86 + UNRESOLVED_EVENTS= 87 + 88 + defined_vars() { # event-dir 89 + grep "^hist" $1/trigger | grep -o ':[a-zA-Z0-9]*=' 90 + } 91 + referred_vars() { 92 + grep "^hist" $1/trigger | grep -o '$[a-zA-Z0-9]*' 93 + } 94 + 95 + per_event_options() { # event-dir 96 + evdir=$1 97 + # Check the special event which has no filter and no trigger 98 + [ ! -f $evdir/filter ] && return 99 + 100 + if grep -q "^hist:" $evdir/trigger; then 101 + # hist action can refer the undefined variables 102 + __vars=`defined_vars $evdir` 103 + for v in `referred_vars $evdir`; do 104 + if echo $DEFINED_VARS $__vars | grep -vqw ${v#$}; then 105 + # $v is not defined yet, defer it 106 + UNRESOLVED_EVENTS="$UNRESOLVED_EVENTS $evdir" 107 + return; 108 + fi 109 + done 110 + DEFINED_VARS="$DEFINED_VARS "`defined_vars $evdir` 111 + fi 112 + grep -v "^#" $evdir/trigger | while read action active; do 113 + emit_kv $PREFIX.event.$group.$event.actions += \'$action\' 114 + done 115 + 116 + # enable is not checked; this is done by set_event in the instance. 117 + val=`cat $evdir/filter` 118 + if [ "$val" != "none" ]; then 119 + emit_kv $PREFIX.event.$group.$event.filter = "$val" 120 + fi 121 + } 122 + 123 + retry_unresolved() { 124 + unresolved=$UNRESOLVED_EVENTS 125 + UNRESOLVED_EVENTS= 126 + for evdir in $unresolved; do 127 + event=${evdir##*/} 128 + group=${evdir%/*}; group=${group##*/} 129 + per_event_options $evdir 130 + done 131 + } 132 + 133 + event_options() { 134 + # PREFIX and INSTANCE must be set 135 + if [ $PREFIX = "ftrace" ]; then 136 + # define the dynamic events 137 + kprobe_event_options 138 + synth_event_options 139 + fi 140 + for group in `ls $INSTANCE/events/` ; do 141 + [ ! -d $INSTANCE/events/$group ] && continue 142 + for event in `ls $INSTANCE/events/$group/` ;do 143 + [ ! -d $INSTANCE/events/$group/$event ] && continue 144 + per_event_options $INSTANCE/events/$group/$event 145 + done 146 + done 147 + retry=0 148 + while [ $retry -lt 3 ]; do 149 + retry_unresolved 150 + retry=$((retry + 1)) 151 + done 152 + if [ "$UNRESOLVED_EVENTS" ]; then 153 + cat 1>&2 << EOF 154 + ! ERROR: hist triggers in $UNRESOLVED_EVENTS use some undefined variables. 155 + EOF 156 + fi 157 + } 158 + 159 + is_default_trace_option() { # option 160 + grep -qw $1 << EOF 161 + print-parent 162 + nosym-offset 163 + nosym-addr 164 + noverbose 165 + noraw 166 + nohex 167 + nobin 168 + noblock 169 + trace_printk 170 + annotate 171 + nouserstacktrace 172 + nosym-userobj 173 + noprintk-msg-only 174 + context-info 175 + nolatency-format 176 + record-cmd 177 + norecord-tgid 178 + overwrite 179 + nodisable_on_free 180 + irq-info 181 + markers 182 + noevent-fork 183 + nopause-on-trace 184 + function-trace 185 + nofunction-fork 186 + nodisplay-graph 187 + nostacktrace 188 + notest_nop_accept 189 + notest_nop_refuse 190 + EOF 191 + } 192 + 193 + instance_options() { # [instance-name] 194 + if [ $# -eq 0 ]; then 195 + PREFIX="ftrace" 196 + INSTANCE=$TRACEFS 197 + else 198 + PREFIX="ftrace.instance.$1" 199 + INSTANCE=$TRACEFS/instances/$1 200 + fi 201 + val= 202 + for i in `cat $INSTANCE/trace_options`; do 203 + is_default_trace_option $i && continue 204 + val="$val, $i" 205 + done 206 + [ "$val" ] && emit_kv $PREFIX.options = "${val#,}" 207 + val="local" 208 + for i in `cat $INSTANCE/trace_clock` ; do 209 + [ "${i#*]}" ] && continue 210 + i=${i%]}; val=${i#[} 211 + done 212 + [ $val != "local" ] && emit_kv $PREFIX.trace_clock = $val 213 + val=`cat $INSTANCE/buffer_size_kb` 214 + if echo $val | grep -vq "expanded" ; then 215 + emit_kv $PREFIX.buffer_size = $val"KB" 216 + fi 217 + if grep -q "is allocated" $INSTANCE/snapshot ; then 218 + emit_kv $PREFIX.alloc_snapshot 219 + fi 220 + val=`cat $INSTANCE/tracing_cpumask` 221 + if [ `echo $val | sed -e s/f//g`x != x ]; then 222 + emit_kv $PREFIX.cpumask = $val 223 + fi 224 + 225 + val= 226 + for i in `cat $INSTANCE/set_event`; do 227 + val="$val, $i" 228 + done 229 + [ "$val" ] && emit_kv $PREFIX.events = "${val#,}" 230 + val=`cat $INSTANCE/current_tracer` 231 + [ $val != nop ] && emit_kv $PREFIX.tracer = $val 232 + if grep -qv "^#" $INSTANCE/set_ftrace_filter $INSTANCE/set_ftrace_notrace; then 233 + cat 1>&2 << EOF 234 + # WARN: kernel.ftrace.filters and kernel.ftrace.notrace are not supported, since the wild card expression was expanded and lost from memory. 235 + EOF 236 + fi 237 + event_options 238 + } 239 + 240 + global_options 241 + instance_options 242 + for i in `ls $TRACEFS/instances` ; do 243 + instance_options $i 244 + done
+56
tools/bootconfig/scripts/xbc.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0-only 3 + 4 + # bootconfig utility functions 5 + 6 + XBC_TMPFILE= 7 + XBC_BASEDIR=`dirname $0` 8 + BOOTCONFIG=${BOOTCONFIG:=$XBC_BASEDIR/../bootconfig} 9 + if [ ! -x "$BOOTCONFIG" ]; then 10 + BOOTCONFIG=`which bootconfig` 11 + if [ -z "$BOOTCONFIG" ]; then 12 + echo "Erorr: bootconfig command is not found" 1>&2 13 + exit 1 14 + fi 15 + fi 16 + 17 + xbc_cleanup() { 18 + if [ "$XBC_TMPFILE" ]; then 19 + rm -f "$XBC_TMPFILE" 20 + fi 21 + } 22 + 23 + xbc_init() { # bootconfig-file 24 + xbc_cleanup 25 + XBC_TMPFILE=`mktemp bconf-XXXX` 26 + trap xbc_cleanup EXIT TERM 27 + 28 + $BOOTCONFIG -l $1 > $XBC_TMPFILE || exit 1 29 + } 30 + 31 + nr_args() { # args 32 + echo $# 33 + } 34 + 35 + xbc_get_val() { # key [maxnum] 36 + if [ "$2" ]; then 37 + MAXOPT="-L $2" 38 + fi 39 + grep "^$1 =" $XBC_TMPFILE | cut -d= -f2- | \ 40 + sed -e 's/", /" /g' -e "s/',/' /g" | \ 41 + xargs $MAXOPT -n 1 echo 42 + } 43 + 44 + xbc_has_key() { # key 45 + grep -q "^$1 =" $XBC_TMPFILE 46 + } 47 + 48 + xbc_has_branch() { # prefix-key 49 + grep -q "^$1" $XBC_TMPFILE 50 + } 51 + 52 + xbc_subkeys() { # prefix-key depth 53 + __keys=`echo $1 | sed "s/\./ /g"` 54 + __s=`nr_args $__keys` 55 + grep "^$1" $XBC_TMPFILE | cut -d= -f1| cut -d. -f$((__s + 1))-$((__s + $2)) | uniq 56 + }
+6
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
··· 97 97 check_error '^p:kprobes/testevent kernel_clone abcd=\1' # SAME_PROBE 98 98 fi 99 99 100 + # %return suffix errors 101 + if grep -q "place (kretprobe): .*%return.*" README; then 102 + check_error 'p vfs_read^%hoge' # BAD_ADDR_SUFFIX 103 + check_error 'p ^vfs_read+10%return' # BAD_RETPROBE 104 + fi 105 + 100 106 exit 0
+21
tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_return_suffix.tc
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # description: Kretprobe %%return suffix test 4 + # requires: kprobe_events '<symbol>[+<offset>]%return':README 5 + 6 + # Test for kretprobe by "r" 7 + echo 'r:myprobeaccept vfs_read' > kprobe_events 8 + RESULT1=`cat kprobe_events` 9 + 10 + # Test for kretprobe by "%return" 11 + echo 'p:myprobeaccept vfs_read%return' > kprobe_events 12 + RESULT2=`cat kprobe_events` 13 + 14 + if [ "$RESULT1" != "$RESULT2" ]; then 15 + echo "Error: %return suffix didn't make a return probe." 16 + echo "r-command: $RESULT1" 17 + echo "%return: $RESULT2" 18 + exit_fail 19 + fi 20 + 21 + echo > kprobe_events
+6
tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc
··· 17 17 check_error 'p /bin/sh:10 ^@+ab' # BAD_FILE_OFFS 18 18 check_error 'p /bin/sh:10 ^@symbol' # SYM_ON_UPROBE 19 19 20 + # %return suffix error 21 + if grep -q "place (uprobe): .*%return.*" README; then 22 + check_error 'p /bin/sh:10^%hoge' # BAD_ADDR_SUFFIX 23 + check_error 'p /bin/sh:10(10)^%return' # BAD_REFCNT_SUFFIX 24 + fi 25 + 20 26 exit 0
+4 -4
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc
··· 25 25 echo 'hist:keys=pid:ts1=common_timestamp.usecs if comm=="ping"' >> events/sched/sched_wakeup/trigger 26 26 echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts1:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid) if next_comm=="ping"' > events/sched/sched_switch/trigger 27 27 28 - echo 'waking+wakeup_latency u64 lat; pid_t pid' >> synthetic_events 29 - echo 'hist:keys=pid,lat:sort=pid,lat:ww_lat=$waking_lat+$wakeup_lat:onmatch(synthetic.wakeup_latency).waking+wakeup_latency($ww_lat,pid)' >> events/synthetic/wakeup_latency/trigger 30 - echo 'hist:keys=pid,lat:sort=pid,lat' >> events/synthetic/waking+wakeup_latency/trigger 28 + echo 'waking_plus_wakeup_latency u64 lat; pid_t pid' >> synthetic_events 29 + echo 'hist:keys=pid,lat:sort=pid,lat:ww_lat=$waking_lat+$wakeup_lat:onmatch(synthetic.wakeup_latency).waking_plus_wakeup_latency($ww_lat,pid)' >> events/synthetic/wakeup_latency/trigger 30 + echo 'hist:keys=pid,lat:sort=pid,lat' >> events/synthetic/waking_plus_wakeup_latency/trigger 31 31 32 32 ping $LOCALHOST -c 3 33 - if ! grep -q "pid:" events/synthetic/waking+wakeup_latency/hist; then 33 + if ! grep -q "pid:" events/synthetic/waking_plus_wakeup_latency/hist; then 34 34 fail "Failed to create combined histogram" 35 35 fi 36 36
+31
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-dynstring.tc
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # description: event trigger - test inter-event histogram trigger trace action with dynamic string param 4 + # requires: set_event synthetic_events events/sched/sched_process_exec/hist "char name[]' >> synthetic_events":README 5 + 6 + fail() { #msg 7 + echo $1 8 + exit_fail 9 + } 10 + 11 + echo "Test create synthetic event" 12 + 13 + echo 'ping_test_latency u64 lat; char filename[]' > synthetic_events 14 + if [ ! -d events/synthetic/ping_test_latency ]; then 15 + fail "Failed to create ping_test_latency synthetic event" 16 + fi 17 + 18 + echo "Test create histogram for synthetic event using trace action and dynamic strings" 19 + echo "Test histogram dynamic string variables,simple expression support and trace action" 20 + 21 + echo 'hist:key=pid:filenamevar=filename:ts0=common_timestamp.usecs' > events/sched/sched_process_exec/trigger 22 + echo 'hist:key=pid:lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_process_exec).ping_test_latency($lat,$filenamevar) if comm == "ping"' > events/sched/sched_process_exit/trigger 23 + echo 'hist:keys=filename,lat:sort=filename,lat' > events/synthetic/ping_test_latency/trigger 24 + 25 + ping $LOCALHOST -c 5 26 + 27 + if ! grep -q "ping" events/synthetic/ping_test_latency/hist; then 28 + fail "Failed to create dynamic string trace action inter-event histogram" 29 + fi 30 + 31 + exit 0
+19
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # description: event trigger - test synthetic_events syntax parser errors 4 + # requires: synthetic_events error_log 5 + 6 + check_error() { # command-with-error-pos-by-^ 7 + ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events' 8 + } 9 + 10 + check_error 'myevent ^chr arg' # INVALID_TYPE 11 + check_error 'myevent ^char str[];; int v' # INVALID_TYPE 12 + check_error 'myevent char ^str]; int v' # INVALID_NAME 13 + check_error 'myevent char ^str;[]' # INVALID_NAME 14 + check_error 'myevent ^char str[; int v' # INVALID_TYPE 15 + check_error '^mye;vent char str[]' # BAD_NAME 16 + check_error 'myevent char str[]; ^int' # INVALID_FIELD 17 + check_error '^myevent' # INCOMPLETE_CMD 18 + 19 + exit 0