Commit | Line | Data |
---|---|---|
b7cdc182 | 1 | /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only) |
9f36eaed | 2 | * |
a90917c3 | 3 | * lttng-probes.c |
02119ee5 | 4 | * |
02119ee5 | 5 | * Holds LTTng probes registry. |
17baffe2 | 6 | * |
886d51a3 | 7 | * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
02119ee5 MD |
8 | */ |
9 | ||
10 | #include <linux/module.h> | |
11 | #include <linux/list.h> | |
12 | #include <linux/mutex.h> | |
271b6681 | 13 | #include <linux/seq_file.h> |
02119ee5 | 14 | |
2df37e95 | 15 | #include <lttng/events.h> |
e8c0bbd3 | 16 | #include <lttng/events-internal.h> |
02119ee5 | 17 | |
3c997079 MD |
18 | /* |
19 | * probe list is protected by sessions lock. | |
20 | */ | |
21 | static LIST_HEAD(_probe_list); | |
22 | ||
23 | /* | |
24 | * List of probes registered by not yet processed. | |
25 | */ | |
26 | static LIST_HEAD(lazy_probe_init); | |
02119ee5 | 27 | |
3c997079 | 28 | /* |
196bfc6a | 29 | * lazy_nesting counter ensures we don't notify lazy probe registration |
3c997079 MD |
30 | * fixup while we are performing the fixup. It is protected by the |
31 | * sessions lock. | |
32 | */ | |
33 | static int lazy_nesting; | |
34 | ||
114667d5 MD |
35 | DEFINE_PER_CPU(struct lttng_dynamic_len_stack, lttng_dynamic_len_stack); |
36 | ||
37 | EXPORT_PER_CPU_SYMBOL_GPL(lttng_dynamic_len_stack); | |
38 | ||
3c997079 MD |
39 | /* |
40 | * Called under sessions lock. | |
41 | */ | |
85a9ca7f | 42 | static |
437d5aa5 | 43 | int check_event_provider(struct lttng_kernel_probe_desc *desc) |
02119ee5 | 44 | { |
0c87bcc6 | 45 | int i, mismatch = 0; |
3c997079 | 46 | size_t provider_name_len; |
02119ee5 | 47 | |
437d5aa5 | 48 | provider_name_len = strnlen(desc->provider_name, |
606828e4 | 49 | LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1); |
3c997079 | 50 | for (i = 0; i < desc->nr_events; i++) { |
021153c0 | 51 | /* |
0c87bcc6 | 52 | * The event name needs to start with provider name + _ + |
021153c0 MD |
53 | * one or more letter. |
54 | */ | |
0c87bcc6 HZ |
55 | if (strncmp(desc->event_desc[i]->event_name, desc->provider_name, provider_name_len)) |
56 | mismatch = 1; | |
57 | else if (strlen(desc->event_desc[i]->event_name) <= provider_name_len + 1) | |
58 | mismatch = 1; | |
59 | else if (desc->event_desc[i]->event_name[provider_name_len] != '_') | |
60 | mismatch = 1; | |
61 | ||
62 | if (mismatch) { | |
63 | printk(KERN_WARNING "LTTng: event provider mismatch: " | |
64 | "The event name needs to start with provider " | |
65 | "name + _ + one or more letter, " | |
66 | "provider: %s, event name: %s\n", | |
67 | desc->provider_name, desc->event_desc[i]->event_name); | |
68 | return 0; | |
69 | } | |
3c997079 MD |
70 | } |
71 | return 1; | |
72 | } | |
73 | ||
74 | /* | |
75 | * Called under sessions lock. | |
76 | */ | |
77 | static | |
437d5aa5 | 78 | void lttng_lazy_probe_register(struct lttng_kernel_probe_desc *desc) |
3c997079 | 79 | { |
437d5aa5 | 80 | struct lttng_kernel_probe_desc *iter; |
3c997079 MD |
81 | struct list_head *probe_list; |
82 | ||
83 | /* | |
84 | * Each provider enforce that every event name begins with the | |
85 | * provider name. Check this in an assertion for extra | |
86 | * carefulness. This ensures we cannot have duplicate event | |
87 | * names across providers. | |
88 | */ | |
89 | WARN_ON_ONCE(!check_event_provider(desc)); | |
90 | ||
91 | /* | |
92 | * The provider ensures there are no duplicate event names. | |
93 | * Duplicated TRACEPOINT_EVENT event names would generate a | |
94 | * compile-time error due to duplicated symbol names. | |
95 | */ | |
96 | ||
97 | /* | |
437d5aa5 | 98 | * We sort the providers by struct lttng_kernel_probe_desc pointer |
3c997079 MD |
99 | * address. |
100 | */ | |
101 | probe_list = &_probe_list; | |
102 | list_for_each_entry_reverse(iter, probe_list, head) { | |
103 | BUG_ON(iter == desc); /* Should never be in the list twice */ | |
104 | if (iter < desc) { | |
105 | /* We belong to the location right after iter. */ | |
106 | list_add(&desc->head, &iter->head); | |
107 | goto desc_added; | |
85a9ca7f | 108 | } |
02119ee5 | 109 | } |
3c997079 MD |
110 | /* We should be added at the head of the list */ |
111 | list_add(&desc->head, probe_list); | |
112 | desc_added: | |
33a39a3c | 113 | pr_debug("LTTng: just registered probe %s containing %u events\n", |
437d5aa5 | 114 | desc->provider_name, desc->nr_events); |
3c997079 MD |
115 | } |
116 | ||
117 | /* | |
118 | * Called under sessions lock. | |
119 | */ | |
120 | static | |
121 | void fixup_lazy_probes(void) | |
122 | { | |
437d5aa5 | 123 | struct lttng_kernel_probe_desc *iter, *tmp; |
3c997079 MD |
124 | int ret; |
125 | ||
126 | lazy_nesting++; | |
127 | list_for_each_entry_safe(iter, tmp, | |
128 | &lazy_probe_init, lazy_init_head) { | |
129 | lttng_lazy_probe_register(iter); | |
130 | iter->lazy = 0; | |
131 | list_del(&iter->lazy_init_head); | |
132 | } | |
133 | ret = lttng_fix_pending_events(); | |
134 | WARN_ON_ONCE(ret); | |
b01155ba FD |
135 | ret = lttng_fix_pending_event_notifiers(); |
136 | WARN_ON_ONCE(ret); | |
3c997079 MD |
137 | lazy_nesting--; |
138 | } | |
139 | ||
140 | /* | |
141 | * Called under sessions lock. | |
142 | */ | |
143 | struct list_head *lttng_get_probe_list_head(void) | |
144 | { | |
145 | if (!lazy_nesting && !list_empty(&lazy_probe_init)) | |
146 | fixup_lazy_probes(); | |
147 | return &_probe_list; | |
148 | } | |
149 | ||
150 | static | |
437d5aa5 | 151 | const struct lttng_kernel_probe_desc *find_provider(const char *provider) |
3c997079 | 152 | { |
437d5aa5 | 153 | struct lttng_kernel_probe_desc *iter; |
3c997079 MD |
154 | struct list_head *probe_list; |
155 | ||
156 | probe_list = lttng_get_probe_list_head(); | |
157 | list_for_each_entry(iter, probe_list, head) { | |
437d5aa5 | 158 | if (!strcmp(iter->provider_name, provider)) |
3c997079 MD |
159 | return iter; |
160 | } | |
02119ee5 MD |
161 | return NULL; |
162 | } | |
163 | ||
d1769981 | 164 | int lttng_kernel_probe_register(struct lttng_kernel_probe_desc *desc) |
02119ee5 | 165 | { |
02119ee5 | 166 | int ret = 0; |
02119ee5 | 167 | |
3c997079 MD |
168 | lttng_lock_sessions(); |
169 | ||
85a9ca7f | 170 | /* |
3c997079 | 171 | * Check if the provider has already been registered. |
85a9ca7f | 172 | */ |
437d5aa5 | 173 | if (find_provider(desc->provider_name)) { |
3c997079 MD |
174 | ret = -EEXIST; |
175 | goto end; | |
02119ee5 | 176 | } |
3c997079 MD |
177 | list_add(&desc->lazy_init_head, &lazy_probe_init); |
178 | desc->lazy = 1; | |
33a39a3c | 179 | pr_debug("LTTng: adding probe %s containing %u events to lazy registration list\n", |
437d5aa5 | 180 | desc->provider_name, desc->nr_events); |
3c997079 MD |
181 | /* |
182 | * If there is at least one active session, we need to register | |
183 | * the probe immediately, since we cannot delay event | |
184 | * registration because they are needed ASAP. | |
185 | */ | |
b01155ba | 186 | if (lttng_session_active() || lttng_event_notifier_active()) |
3c997079 | 187 | fixup_lazy_probes(); |
02119ee5 | 188 | end: |
3c997079 | 189 | lttng_unlock_sessions(); |
02119ee5 MD |
190 | return ret; |
191 | } | |
d1769981 | 192 | EXPORT_SYMBOL_GPL(lttng_kernel_probe_register); |
02119ee5 | 193 | |
d1769981 | 194 | void lttng_kernel_probe_unregister(struct lttng_kernel_probe_desc *desc) |
02119ee5 | 195 | { |
3c997079 MD |
196 | lttng_lock_sessions(); |
197 | if (!desc->lazy) | |
198 | list_del(&desc->head); | |
199 | else | |
200 | list_del(&desc->lazy_init_head); | |
437d5aa5 | 201 | pr_debug("LTTng: just unregistered probe %s\n", desc->provider_name); |
3c997079 | 202 | lttng_unlock_sessions(); |
02119ee5 | 203 | } |
d1769981 | 204 | EXPORT_SYMBOL_GPL(lttng_kernel_probe_unregister); |
02119ee5 | 205 | |
3c997079 MD |
206 | /* |
207 | * TODO: this is O(nr_probes * nb_events), could be faster. | |
208 | * Called with sessions lock held. | |
209 | */ | |
210 | static | |
437d5aa5 | 211 | const struct lttng_kernel_event_desc *find_event_desc(const char *name) |
3c997079 | 212 | { |
437d5aa5 | 213 | struct lttng_kernel_probe_desc *probe_desc; |
3c997079 MD |
214 | int i; |
215 | ||
216 | list_for_each_entry(probe_desc, &_probe_list, head) { | |
217 | for (i = 0; i < probe_desc->nr_events; i++) { | |
437d5aa5 | 218 | if (!strcmp(probe_desc->event_desc[i]->event_name, name)) |
3c997079 MD |
219 | return probe_desc->event_desc[i]; |
220 | } | |
221 | } | |
222 | return NULL; | |
223 | } | |
224 | ||
225 | /* | |
226 | * Called with sessions lock held. | |
227 | */ | |
437d5aa5 | 228 | const struct lttng_kernel_event_desc *lttng_event_desc_get(const char *name) |
02119ee5 | 229 | { |
437d5aa5 | 230 | const struct lttng_kernel_event_desc *event_desc; |
02119ee5 MD |
231 | int ret; |
232 | ||
0bcedee9 FD |
233 | event_desc = find_event_desc(name); |
234 | if (!event_desc) | |
c099397a | 235 | return NULL; |
0bcedee9 | 236 | ret = try_module_get(event_desc->owner); |
02119ee5 | 237 | WARN_ON_ONCE(!ret); |
0bcedee9 | 238 | return event_desc; |
02119ee5 | 239 | } |
0bcedee9 | 240 | EXPORT_SYMBOL_GPL(lttng_event_desc_get); |
02119ee5 | 241 | |
3c997079 MD |
242 | /* |
243 | * Called with sessions lock held. | |
244 | */ | |
437d5aa5 | 245 | void lttng_event_desc_put(const struct lttng_kernel_event_desc *event_desc) |
02119ee5 | 246 | { |
0bcedee9 | 247 | module_put(event_desc->owner); |
02119ee5 | 248 | } |
0bcedee9 | 249 | EXPORT_SYMBOL_GPL(lttng_event_desc_put); |
271b6681 MD |
250 | |
251 | static | |
252 | void *tp_list_start(struct seq_file *m, loff_t *pos) | |
253 | { | |
437d5aa5 | 254 | struct lttng_kernel_probe_desc *probe_desc; |
a1031097 | 255 | struct list_head *probe_list; |
271b6681 MD |
256 | int iter = 0, i; |
257 | ||
3c997079 | 258 | lttng_lock_sessions(); |
a1031097 MD |
259 | probe_list = lttng_get_probe_list_head(); |
260 | list_for_each_entry(probe_desc, probe_list, head) { | |
271b6681 MD |
261 | for (i = 0; i < probe_desc->nr_events; i++) { |
262 | if (iter++ >= *pos) | |
f7bdf4db | 263 | return (void *) probe_desc->event_desc[i]; |
271b6681 MD |
264 | } |
265 | } | |
266 | /* End of list */ | |
267 | return NULL; | |
268 | } | |
269 | ||
270 | static | |
271 | void *tp_list_next(struct seq_file *m, void *p, loff_t *ppos) | |
272 | { | |
437d5aa5 | 273 | struct lttng_kernel_probe_desc *probe_desc; |
a1031097 | 274 | struct list_head *probe_list; |
271b6681 MD |
275 | int iter = 0, i; |
276 | ||
277 | (*ppos)++; | |
a1031097 MD |
278 | probe_list = lttng_get_probe_list_head(); |
279 | list_for_each_entry(probe_desc, probe_list, head) { | |
271b6681 MD |
280 | for (i = 0; i < probe_desc->nr_events; i++) { |
281 | if (iter++ >= *ppos) | |
f7bdf4db | 282 | return (void *) probe_desc->event_desc[i]; |
271b6681 MD |
283 | } |
284 | } | |
285 | /* End of list */ | |
286 | return NULL; | |
287 | } | |
288 | ||
289 | static | |
290 | void tp_list_stop(struct seq_file *m, void *p) | |
291 | { | |
3c997079 | 292 | lttng_unlock_sessions(); |
271b6681 MD |
293 | } |
294 | ||
295 | static | |
296 | int tp_list_show(struct seq_file *m, void *p) | |
297 | { | |
437d5aa5 | 298 | const struct lttng_kernel_event_desc *probe_desc = p; |
271b6681 MD |
299 | |
300 | seq_printf(m, "event { name = %s; };\n", | |
437d5aa5 | 301 | probe_desc->event_name); |
271b6681 MD |
302 | return 0; |
303 | } | |
304 | ||
305 | static | |
306 | const struct seq_operations lttng_tracepoint_list_seq_ops = { | |
307 | .start = tp_list_start, | |
308 | .next = tp_list_next, | |
309 | .stop = tp_list_stop, | |
310 | .show = tp_list_show, | |
311 | }; | |
312 | ||
313 | static | |
314 | int lttng_tracepoint_list_open(struct inode *inode, struct file *file) | |
315 | { | |
316 | return seq_open(file, <tng_tracepoint_list_seq_ops); | |
317 | } | |
318 | ||
319 | const struct file_operations lttng_tracepoint_list_fops = { | |
2e54c205 | 320 | .owner = THIS_MODULE, |
271b6681 MD |
321 | .open = lttng_tracepoint_list_open, |
322 | .read = seq_read, | |
323 | .llseek = seq_lseek, | |
a51729c7 | 324 | .release = seq_release, |
271b6681 | 325 | }; |
114667d5 MD |
326 | |
327 | int lttng_probes_init(void) | |
328 | { | |
329 | int cpu; | |
330 | ||
331 | for_each_possible_cpu(cpu) | |
332 | per_cpu_ptr(<tng_dynamic_len_stack, cpu)->offset = 0; | |
333 | return 0; | |
334 | } |