aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/marker.h45
-rw-r--r--init/Kconfig1
-rw-r--r--kernel/marker.c53
3 files changed, 96 insertions, 3 deletions
diff --git a/include/linux/marker.h b/include/linux/marker.h
index 05ec0df37089..57a307018ceb 100644
--- a/include/linux/marker.h
+++ b/include/linux/marker.h
@@ -49,6 +49,8 @@ struct marker {
49 void (*call)(const struct marker *mdata, void *call_private, ...); 49 void (*call)(const struct marker *mdata, void *call_private, ...);
50 struct marker_probe_closure single; 50 struct marker_probe_closure single;
51 struct marker_probe_closure *multi; 51 struct marker_probe_closure *multi;
52 const char *tp_name; /* Optional tracepoint name */
53 void *tp_cb; /* Optional tracepoint callback */
52} __attribute__((aligned(8))); 54} __attribute__((aligned(8)));
53 55
54#ifdef CONFIG_MARKERS 56#ifdef CONFIG_MARKERS
@@ -73,7 +75,7 @@ struct marker {
73 __attribute__((section("__markers"), aligned(8))) = \ 75 __attribute__((section("__markers"), aligned(8))) = \
74 { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \ 76 { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \
75 0, 0, marker_probe_cb, \ 77 0, 0, marker_probe_cb, \
76 { __mark_empty_function, NULL}, NULL }; \ 78 { __mark_empty_function, NULL}, NULL, NULL, NULL }; \
77 __mark_check_format(format, ## args); \ 79 __mark_check_format(format, ## args); \
78 if (unlikely(__mark_##name.state)) { \ 80 if (unlikely(__mark_##name.state)) { \
79 (*__mark_##name.call) \ 81 (*__mark_##name.call) \
@@ -81,11 +83,38 @@ struct marker {
81 } \ 83 } \
82 } while (0) 84 } while (0)
83 85
86#define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \
87 do { \
88 void __check_tp_type(void) \
89 { \
90 register_trace_##tp_name(tp_cb); \
91 } \
92 static const char __mstrtab_##name[] \
93 __attribute__((section("__markers_strings"))) \
94 = #name "\0" format; \
95 static struct marker __mark_##name \
96 __attribute__((section("__markers"), aligned(8))) = \
97 { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \
98 0, 0, marker_probe_cb, \
99 { __mark_empty_function, NULL}, NULL, #tp_name, tp_cb };\
100 __mark_check_format(format, ## args); \
101 (*__mark_##name.call)(&__mark_##name, call_private, \
102 ## args); \
103 } while (0)
104
84extern void marker_update_probe_range(struct marker *begin, 105extern void marker_update_probe_range(struct marker *begin,
85 struct marker *end); 106 struct marker *end);
86#else /* !CONFIG_MARKERS */ 107#else /* !CONFIG_MARKERS */
87#define __trace_mark(generic, name, call_private, format, args...) \ 108#define __trace_mark(generic, name, call_private, format, args...) \
88 __mark_check_format(format, ## args) 109 __mark_check_format(format, ## args)
110#define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \
111 do { \
112 void __check_tp_type(void) \
113 { \
114 register_trace_##tp_name(tp_cb); \
115 } \
116 __mark_check_format(format, ## args); \
117 } while (0)
89static inline void marker_update_probe_range(struct marker *begin, 118static inline void marker_update_probe_range(struct marker *begin,
90 struct marker *end) 119 struct marker *end)
91{ } 120{ }
@@ -118,6 +147,20 @@ static inline void marker_update_probe_range(struct marker *begin,
118 __trace_mark(1, name, NULL, format, ## args) 147 __trace_mark(1, name, NULL, format, ## args)
119 148
120/** 149/**
150 * trace_mark_tp - Marker in a tracepoint callback
151 * @name: marker name, not quoted.
152 * @tp_name: tracepoint name, not quoted.
153 * @tp_cb: tracepoint callback. Should have an associated global symbol so it
154 * is not optimized away by the compiler (should not be static).
155 * @format: format string
156 * @args...: variable argument list
157 *
158 * Places a marker in a tracepoint callback.
159 */
160#define trace_mark_tp(name, tp_name, tp_cb, format, args...) \
161 __trace_mark_tp(name, NULL, tp_name, tp_cb, format, ## args)
162
163/**
121 * MARK_NOARGS - Format string for a marker with no argument. 164 * MARK_NOARGS - Format string for a marker with no argument.
122 */ 165 */
123#define MARK_NOARGS " " 166#define MARK_NOARGS " "
diff --git a/init/Kconfig b/init/Kconfig
index 86b00c53fade..f5bacb438711 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -808,6 +808,7 @@ config TRACEPOINTS
808 808
809config MARKERS 809config MARKERS
810 bool "Activate markers" 810 bool "Activate markers"
811 depends on TRACEPOINTS
811 help 812 help
812 Place an empty function call at each marker site. Can be 813 Place an empty function call at each marker site. Can be
813 dynamically changed for a probe function. 814 dynamically changed for a probe function.
diff --git a/kernel/marker.c b/kernel/marker.c
index 348e70cc355a..c14ec26a9b9f 100644
--- a/kernel/marker.c
+++ b/kernel/marker.c
@@ -479,7 +479,7 @@ static int marker_set_format(struct marker_entry *entry, const char *format)
479static int set_marker(struct marker_entry *entry, struct marker *elem, 479static int set_marker(struct marker_entry *entry, struct marker *elem,
480 int active) 480 int active)
481{ 481{
482 int ret; 482 int ret = 0;
483 WARN_ON(strcmp(entry->name, elem->name) != 0); 483 WARN_ON(strcmp(entry->name, elem->name) != 0);
484 484
485 if (entry->format) { 485 if (entry->format) {
@@ -531,9 +531,40 @@ static int set_marker(struct marker_entry *entry, struct marker *elem,
531 */ 531 */
532 smp_wmb(); 532 smp_wmb();
533 elem->ptype = entry->ptype; 533 elem->ptype = entry->ptype;
534
535 if (elem->tp_name && (active ^ elem->state)) {
536 WARN_ON(!elem->tp_cb);
537 /*
538 * It is ok to directly call the probe registration because type
539 * checking has been done in the __trace_mark_tp() macro.
540 */
541
542 if (active) {
543 /*
544 * try_module_get should always succeed because we hold
545 * lock_module() to get the tp_cb address.
546 */
547 ret = try_module_get(__module_text_address(
548 (unsigned long)elem->tp_cb));
549 BUG_ON(!ret);
550 ret = tracepoint_probe_register_noupdate(
551 elem->tp_name,
552 elem->tp_cb);
553 } else {
554 ret = tracepoint_probe_unregister_noupdate(
555 elem->tp_name,
556 elem->tp_cb);
557 /*
558 * tracepoint_probe_update_all() must be called
559 * before the module containing tp_cb is unloaded.
560 */
561 module_put(__module_text_address(
562 (unsigned long)elem->tp_cb));
563 }
564 }
534 elem->state = active; 565 elem->state = active;
535 566
536 return 0; 567 return ret;
537} 568}
538 569
539/* 570/*
@@ -544,7 +575,24 @@ static int set_marker(struct marker_entry *entry, struct marker *elem,
544 */ 575 */
545static void disable_marker(struct marker *elem) 576static void disable_marker(struct marker *elem)
546{ 577{
578 int ret;
579
547 /* leave "call" as is. It is known statically. */ 580 /* leave "call" as is. It is known statically. */
581 if (elem->tp_name && elem->state) {
582 WARN_ON(!elem->tp_cb);
583 /*
584 * It is ok to directly call the probe registration because type
585 * checking has been done in the __trace_mark_tp() macro.
586 */
587 ret = tracepoint_probe_unregister_noupdate(elem->tp_name,
588 elem->tp_cb);
589 WARN_ON(ret);
590 /*
591 * tracepoint_probe_update_all() must be called
592 * before the module containing tp_cb is unloaded.
593 */
594 module_put(__module_text_address((unsigned long)elem->tp_cb));
595 }
548 elem->state = 0; 596 elem->state = 0;
549 elem->single.func = __mark_empty_function; 597 elem->single.func = __mark_empty_function;
550 /* Update the function before setting the ptype */ 598 /* Update the function before setting the ptype */
@@ -608,6 +656,7 @@ static void marker_update_probes(void)
608 marker_update_probe_range(__start___markers, __stop___markers); 656 marker_update_probe_range(__start___markers, __stop___markers);
609 /* Markers in modules. */ 657 /* Markers in modules. */
610 module_update_markers(); 658 module_update_markers();
659 tracepoint_probe_update_all();
611} 660}
612 661
613/** 662/**