1 /* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
5 * LTTng adaptation layer for Linux kernel 3.15+ tracepoints.
7 * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
10 #include <linux/mutex.h>
11 #include <linux/err.h>
12 #include <linux/notifier.h>
13 #include <linux/tracepoint.h>
14 #include <linux/slab.h>
15 #include <linux/jhash.h>
16 #include <linux/module.h>
18 #include <lttng-tracepoint.h>
19 #include <wrapper/list.h>
20 #include <wrapper/tracepoint.h>
23 * Protect the tracepoint table. lttng_tracepoint_mutex nests within
24 * kernel/tracepoint.c tp_modlist_mutex. kernel/tracepoint.c
25 * tracepoint_mutex nests within lttng_tracepoint_mutex.
28 DEFINE_MUTEX(lttng_tracepoint_mutex
);
30 #define TRACEPOINT_HASH_BITS 6
31 #define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
33 struct hlist_head tracepoint_table
[TRACEPOINT_TABLE_SIZE
];
36 * The tracepoint entry is the node contained within the hash table. It
37 * is a mapping from the "string" key to the struct tracepoint pointer.
39 struct tracepoint_entry
{
40 struct hlist_node hlist
;
41 struct tracepoint
*tp
;
43 struct list_head probes
;
47 struct lttng_tp_probe
{
48 struct tracepoint_func tp_func
;
49 struct list_head list
;
53 int add_probe(struct tracepoint_entry
*e
, void *probe
, void *data
)
55 struct lttng_tp_probe
*p
;
58 list_for_each_entry(p
, &e
->probes
, list
) {
59 if (p
->tp_func
.func
== probe
&& p
->tp_func
.data
== data
) {
66 p
= kmalloc(sizeof(struct lttng_tp_probe
), GFP_KERNEL
);
69 p
->tp_func
.func
= probe
;
70 p
->tp_func
.data
= data
;
71 list_add(&p
->list
, &e
->probes
);
76 int remove_probe(struct tracepoint_entry
*e
, void *probe
, void *data
)
78 struct lttng_tp_probe
*p
;
81 list_for_each_entry(p
, &e
->probes
, list
) {
82 if (p
->tp_func
.func
== probe
&& p
->tp_func
.data
== data
) {
98 * Get tracepoint if the tracepoint is present in the tracepoint hash table.
99 * Must be called with lttng_tracepoint_mutex held.
100 * Returns NULL if not present.
103 struct tracepoint_entry
*get_tracepoint(const char *name
)
105 struct hlist_head
*head
;
106 struct tracepoint_entry
*e
;
107 u32 hash
= jhash(name
, strlen(name
), 0);
109 head
= &tracepoint_table
[hash
& (TRACEPOINT_TABLE_SIZE
- 1)];
110 lttng_hlist_for_each_entry(e
, head
, hlist
) {
111 if (!strcmp(name
, e
->name
))
118 * Add the tracepoint to the tracepoint hash table. Must be called with
119 * lttng_tracepoint_mutex held.
122 struct tracepoint_entry
*add_tracepoint(const char *name
)
124 struct hlist_head
*head
;
125 struct tracepoint_entry
*e
;
126 size_t name_len
= strlen(name
) + 1;
127 u32 hash
= jhash(name
, name_len
- 1, 0);
129 head
= &tracepoint_table
[hash
& (TRACEPOINT_TABLE_SIZE
- 1)];
130 lttng_hlist_for_each_entry(e
, head
, hlist
) {
131 if (!strcmp(name
, e
->name
)) {
133 "tracepoint %s busy\n", name
);
134 return ERR_PTR(-EEXIST
); /* Already there */
138 * Using kmalloc here to allocate a variable length element. Could
139 * cause some memory fragmentation if overused.
141 e
= kmalloc(sizeof(struct tracepoint_entry
) + name_len
, GFP_KERNEL
);
143 return ERR_PTR(-ENOMEM
);
144 memcpy(&e
->name
[0], name
, name_len
);
147 INIT_LIST_HEAD(&e
->probes
);
148 hlist_add_head(&e
->hlist
, head
);
153 * Remove the tracepoint from the tracepoint hash table. Must be called
154 * with lttng_tracepoint_mutex held.
157 void remove_tracepoint(struct tracepoint_entry
*e
)
159 hlist_del(&e
->hlist
);
163 int lttng_tracepoint_probe_register(const char *name
, void *probe
, void *data
)
165 struct tracepoint_entry
*e
;
168 mutex_lock(<tng_tracepoint_mutex
);
169 e
= get_tracepoint(name
);
171 e
= add_tracepoint(name
);
177 /* add (probe, data) to entry */
178 ret
= add_probe(e
, probe
, data
);
183 ret
= tracepoint_probe_register(e
->tp
, probe
, data
);
188 mutex_unlock(<tng_tracepoint_mutex
);
192 int lttng_tracepoint_probe_unregister(const char *name
, void *probe
, void *data
)
194 struct tracepoint_entry
*e
;
197 mutex_lock(<tng_tracepoint_mutex
);
198 e
= get_tracepoint(name
);
203 /* remove (probe, data) from entry */
204 ret
= remove_probe(e
, probe
, data
);
208 ret
= tracepoint_probe_unregister(e
->tp
, probe
, data
);
213 remove_tracepoint(e
);
215 mutex_unlock(<tng_tracepoint_mutex
);
219 #ifdef CONFIG_MODULES
222 int lttng_tracepoint_coming(struct tp_module
*tp_mod
)
226 mutex_lock(<tng_tracepoint_mutex
);
227 for (i
= 0; i
< tp_mod
->mod
->num_tracepoints
; i
++) {
228 struct tracepoint
*tp
;
229 struct tracepoint_entry
*e
;
230 struct lttng_tp_probe
*p
;
232 tp
= lttng_tracepoint_ptr_deref(&tp_mod
->mod
->tracepoints_ptrs
[i
]);
233 e
= get_tracepoint(tp
->name
);
235 e
= add_tracepoint(tp
->name
);
237 pr_warn("LTTng: error (%ld) adding tracepoint\n",
242 /* If already enabled, just check consistency */
244 WARN_ON(e
->tp
!= tp
);
249 /* register each (probe, data) */
250 list_for_each_entry(p
, &e
->probes
, list
) {
253 ret
= tracepoint_probe_register(e
->tp
,
254 p
->tp_func
.func
, p
->tp_func
.data
);
258 mutex_unlock(<tng_tracepoint_mutex
);
263 int lttng_tracepoint_going(struct tp_module
*tp_mod
)
267 mutex_lock(<tng_tracepoint_mutex
);
268 for (i
= 0; i
< tp_mod
->mod
->num_tracepoints
; i
++) {
269 struct tracepoint
*tp
;
270 struct tracepoint_entry
*e
;
271 struct lttng_tp_probe
*p
;
273 tp
= lttng_tracepoint_ptr_deref(&tp_mod
->mod
->tracepoints_ptrs
[i
]);
274 e
= get_tracepoint(tp
->name
);
277 /* unregister each (probe, data) */
278 list_for_each_entry(p
, &e
->probes
, list
) {
281 ret
= tracepoint_probe_unregister(e
->tp
,
282 p
->tp_func
.func
, p
->tp_func
.data
);
287 remove_tracepoint(e
);
289 mutex_unlock(<tng_tracepoint_mutex
);
294 int lttng_tracepoint_notify(struct notifier_block
*self
,
295 unsigned long val
, void *data
)
297 struct tp_module
*tp_mod
= data
;
301 case MODULE_STATE_COMING
:
302 ret
= lttng_tracepoint_coming(tp_mod
);
304 case MODULE_STATE_GOING
:
305 ret
= lttng_tracepoint_going(tp_mod
);
314 struct notifier_block lttng_tracepoint_notifier
= {
315 .notifier_call
= lttng_tracepoint_notify
,
320 int lttng_tracepoint_module_init(void)
322 return register_tracepoint_module_notifier(<tng_tracepoint_notifier
);
326 void lttng_tracepoint_module_exit(void)
328 WARN_ON(unregister_tracepoint_module_notifier(<tng_tracepoint_notifier
));
331 #else /* #ifdef CONFIG_MODULES */
334 int lttng_tracepoint_module_init(void)
340 void lttng_tracepoint_module_exit(void)
344 #endif /* #else #ifdef CONFIG_MODULES */
347 void lttng_kernel_tracepoint_add(struct tracepoint
*tp
, void *priv
)
349 struct tracepoint_entry
*e
;
350 struct lttng_tp_probe
*p
;
353 mutex_lock(<tng_tracepoint_mutex
);
354 e
= get_tracepoint(tp
->name
);
356 e
= add_tracepoint(tp
->name
);
358 pr_warn("LTTng: error (%ld) adding tracepoint\n",
360 *ret
= (int) PTR_ERR(e
);
364 /* If already enabled, just check consistency */
366 WARN_ON(e
->tp
!= tp
);
371 /* register each (probe, data) */
372 list_for_each_entry(p
, &e
->probes
, list
) {
375 ret
= tracepoint_probe_register(e
->tp
,
376 p
->tp_func
.func
, p
->tp_func
.data
);
380 mutex_unlock(<tng_tracepoint_mutex
);
384 void lttng_kernel_tracepoint_remove(struct tracepoint
*tp
, void *priv
)
386 struct tracepoint_entry
*e
;
389 mutex_lock(<tng_tracepoint_mutex
);
390 e
= get_tracepoint(tp
->name
);
391 if (!e
|| e
->refcount
!= 1 || !list_empty(&e
->probes
)) {
395 remove_tracepoint(e
);
397 mutex_unlock(<tng_tracepoint_mutex
);
400 int __init
lttng_tracepoint_init(void)
404 for_each_kernel_tracepoint(lttng_kernel_tracepoint_add
, &ret
);
407 ret
= lttng_tracepoint_module_init();
416 for_each_kernel_tracepoint(lttng_kernel_tracepoint_remove
,
424 void lttng_tracepoint_exit(void)
428 lttng_tracepoint_module_exit();
429 for_each_kernel_tracepoint(lttng_kernel_tracepoint_remove
, &ret
);
431 mutex_lock(<tng_tracepoint_mutex
);
432 for (i
= 0; i
< TRACEPOINT_TABLE_SIZE
; i
++) {
433 struct hlist_head
*head
= &tracepoint_table
[i
];
435 /* All tracepoints should be removed */
436 WARN_ON(!hlist_empty(head
));
438 mutex_unlock(<tng_tracepoint_mutex
);