Fix: timer_expire_entry changed in 4.19.312
[lttng-modules.git] / src / lttng-probes.c
CommitLineData
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 */
21static LIST_HEAD(_probe_list);
22
23/*
24 * List of probes registered by not yet processed.
25 */
26static 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 */
33static int lazy_nesting;
34
114667d5
MD
35DEFINE_PER_CPU(struct lttng_dynamic_len_stack, lttng_dynamic_len_stack);
36
37EXPORT_PER_CPU_SYMBOL_GPL(lttng_dynamic_len_stack);
38
3c997079
MD
39/*
40 * Called under sessions lock.
41 */
85a9ca7f 42static
437d5aa5 43int 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 */
77static
437d5aa5 78void 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);
112desc_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 */
120static
121void 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 */
143struct 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
150static
437d5aa5 151const 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 164int 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 188end:
3c997079 189 lttng_unlock_sessions();
02119ee5
MD
190 return ret;
191}
d1769981 192EXPORT_SYMBOL_GPL(lttng_kernel_probe_register);
02119ee5 193
d1769981 194void 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 204EXPORT_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 */
210static
437d5aa5 211const 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 228const 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 240EXPORT_SYMBOL_GPL(lttng_event_desc_get);
02119ee5 241
3c997079
MD
242/*
243 * Called with sessions lock held.
244 */
437d5aa5 245void lttng_event_desc_put(const struct lttng_kernel_event_desc *event_desc)
02119ee5 246{
0bcedee9 247 module_put(event_desc->owner);
02119ee5 248}
0bcedee9 249EXPORT_SYMBOL_GPL(lttng_event_desc_put);
271b6681
MD
250
251static
252void *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
270static
271void *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
289static
290void tp_list_stop(struct seq_file *m, void *p)
291{
3c997079 292 lttng_unlock_sessions();
271b6681
MD
293}
294
295static
296int 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
305static
306const 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
313static
314int lttng_tracepoint_list_open(struct inode *inode, struct file *file)
315{
316 return seq_open(file, &lttng_tracepoint_list_seq_ops);
317}
318
319const 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
327int lttng_probes_init(void)
328{
329 int cpu;
330
331 for_each_possible_cpu(cpu)
332 per_cpu_ptr(&lttng_dynamic_len_stack, cpu)->offset = 0;
333 return 0;
334}
This page took 0.074768 seconds and 4 git commands to generate.