1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
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>
21 * Protect the tracepoint table. lttng_tracepoint_mutex nests within
22 * kernel/tracepoint.c tp_modlist_mutex. kernel/tracepoint.c
23 * tracepoint_mutex nests within lttng_tracepoint_mutex.
26 DEFINE_MUTEX(lttng_tracepoint_mutex
);
28 #define TRACEPOINT_HASH_BITS 6
29 #define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
31 struct hlist_head tracepoint_table
[TRACEPOINT_TABLE_SIZE
];
34 * The tracepoint entry is the node contained within the hash table. It
35 * is a mapping from the "string" key to the struct tracepoint pointer.
37 struct tracepoint_entry
{
38 struct hlist_node hlist
;
39 struct tracepoint
*tp
;
41 struct list_head probes
;
45 struct lttng_tp_probe
{
46 struct tracepoint_func tp_func
;
47 struct list_head list
;
51 int add_probe(struct tracepoint_entry
*e
, void *probe
, void *data
)
53 struct lttng_tp_probe
*p
;
56 list_for_each_entry(p
, &e
->probes
, list
) {
57 if (p
->tp_func
.func
== probe
&& p
->tp_func
.data
== data
) {
64 p
= kmalloc(sizeof(struct lttng_tp_probe
), GFP_KERNEL
);
67 p
->tp_func
.func
= probe
;
68 p
->tp_func
.data
= data
;
69 list_add(&p
->list
, &e
->probes
);
74 int remove_probe(struct tracepoint_entry
*e
, void *probe
, void *data
)
76 struct lttng_tp_probe
*p
;
79 list_for_each_entry(p
, &e
->probes
, list
) {
80 if (p
->tp_func
.func
== probe
&& p
->tp_func
.data
== data
) {
96 * Get tracepoint if the tracepoint is present in the tracepoint hash table.
97 * Must be called with lttng_tracepoint_mutex held.
98 * Returns NULL if not present.
101 struct tracepoint_entry
*get_tracepoint(const char *name
)
103 struct hlist_head
*head
;
104 struct tracepoint_entry
*e
;
105 u32 hash
= jhash(name
, strlen(name
), 0);
107 head
= &tracepoint_table
[hash
& (TRACEPOINT_TABLE_SIZE
- 1)];
108 hlist_for_each_entry(e
, head
, hlist
) {
109 if (!strcmp(name
, e
->name
))
116 * Add the tracepoint to the tracepoint hash table. Must be called with
117 * lttng_tracepoint_mutex held.
120 struct tracepoint_entry
*add_tracepoint(const char *name
)
122 struct hlist_head
*head
;
123 struct tracepoint_entry
*e
;
124 size_t name_len
= strlen(name
) + 1;
125 u32 hash
= jhash(name
, name_len
- 1, 0);
127 head
= &tracepoint_table
[hash
& (TRACEPOINT_TABLE_SIZE
- 1)];
128 hlist_for_each_entry(e
, head
, hlist
) {
129 if (!strcmp(name
, e
->name
)) {
131 "tracepoint %s busy\n", name
);
132 return ERR_PTR(-EEXIST
); /* Already there */
136 * Using kmalloc here to allocate a variable length element. Could
137 * cause some memory fragmentation if overused.
139 e
= kmalloc(sizeof(struct tracepoint_entry
) + name_len
, GFP_KERNEL
);
141 return ERR_PTR(-ENOMEM
);
142 memcpy(&e
->name
[0], name
, name_len
);
145 INIT_LIST_HEAD(&e
->probes
);
146 hlist_add_head(&e
->hlist
, head
);
151 * Remove the tracepoint from the tracepoint hash table. Must be called
152 * with lttng_tracepoint_mutex held.
155 void remove_tracepoint(struct tracepoint_entry
*e
)
157 hlist_del(&e
->hlist
);
161 int lttng_tracepoint_probe_register(const char *name
, void *probe
, void *data
)
163 struct tracepoint_entry
*e
;
166 mutex_lock(<tng_tracepoint_mutex
);
167 e
= get_tracepoint(name
);
169 e
= add_tracepoint(name
);
175 /* add (probe, data) to entry */
176 ret
= add_probe(e
, probe
, data
);
181 ret
= tracepoint_probe_register(e
->tp
, probe
, data
);
186 mutex_unlock(<tng_tracepoint_mutex
);
190 int lttng_tracepoint_probe_unregister(const char *name
, void *probe
, void *data
)
192 struct tracepoint_entry
*e
;
195 mutex_lock(<tng_tracepoint_mutex
);
196 e
= get_tracepoint(name
);
201 /* remove (probe, data) from entry */
202 ret
= remove_probe(e
, probe
, data
);
206 ret
= tracepoint_probe_unregister(e
->tp
, probe
, data
);
211 remove_tracepoint(e
);
213 mutex_unlock(<tng_tracepoint_mutex
);
217 #ifdef CONFIG_MODULES
220 int lttng_tracepoint_coming(struct tp_module
*tp_mod
)
224 mutex_lock(<tng_tracepoint_mutex
);
225 for (i
= 0; i
< tp_mod
->mod
->num_tracepoints
; i
++) {
226 struct tracepoint
*tp
;
227 struct tracepoint_entry
*e
;
228 struct lttng_tp_probe
*p
;
230 tp
= tracepoint_ptr_deref(&tp_mod
->mod
->tracepoints_ptrs
[i
]);
231 e
= get_tracepoint(tp
->name
);
233 e
= add_tracepoint(tp
->name
);
235 pr_warn("LTTng: error (%ld) adding tracepoint\n",
240 /* If already enabled, just check consistency */
242 WARN_ON(e
->tp
!= tp
);
247 /* register each (probe, data) */
248 list_for_each_entry(p
, &e
->probes
, list
) {
251 ret
= tracepoint_probe_register(e
->tp
,
252 p
->tp_func
.func
, p
->tp_func
.data
);
256 mutex_unlock(<tng_tracepoint_mutex
);
261 int lttng_tracepoint_going(struct tp_module
*tp_mod
)
265 mutex_lock(<tng_tracepoint_mutex
);
266 for (i
= 0; i
< tp_mod
->mod
->num_tracepoints
; i
++) {
267 struct tracepoint
*tp
;
268 struct tracepoint_entry
*e
;
269 struct lttng_tp_probe
*p
;
271 tp
= tracepoint_ptr_deref(&tp_mod
->mod
->tracepoints_ptrs
[i
]);
272 e
= get_tracepoint(tp
->name
);
275 /* unregister each (probe, data) */
276 list_for_each_entry(p
, &e
->probes
, list
) {
279 ret
= tracepoint_probe_unregister(e
->tp
,
280 p
->tp_func
.func
, p
->tp_func
.data
);
285 remove_tracepoint(e
);
287 mutex_unlock(<tng_tracepoint_mutex
);
292 int lttng_tracepoint_notify(struct notifier_block
*self
,
293 unsigned long val
, void *data
)
295 struct tp_module
*tp_mod
= data
;
299 case MODULE_STATE_COMING
:
300 ret
= lttng_tracepoint_coming(tp_mod
);
302 case MODULE_STATE_GOING
:
303 ret
= lttng_tracepoint_going(tp_mod
);
312 struct notifier_block lttng_tracepoint_notifier
= {
313 .notifier_call
= lttng_tracepoint_notify
,
318 int lttng_tracepoint_module_init(void)
320 return register_tracepoint_module_notifier(<tng_tracepoint_notifier
);
324 void lttng_tracepoint_module_exit(void)
326 WARN_ON(unregister_tracepoint_module_notifier(<tng_tracepoint_notifier
));
329 #else /* #ifdef CONFIG_MODULES */
332 int lttng_tracepoint_module_init(void)
338 void lttng_tracepoint_module_exit(void)
342 #endif /* #else #ifdef CONFIG_MODULES */
345 void lttng_kernel_tracepoint_add(struct tracepoint
*tp
, void *priv
)
347 struct tracepoint_entry
*e
;
348 struct lttng_tp_probe
*p
;
351 mutex_lock(<tng_tracepoint_mutex
);
352 e
= get_tracepoint(tp
->name
);
354 e
= add_tracepoint(tp
->name
);
356 pr_warn("LTTng: error (%ld) adding tracepoint\n",
358 *ret
= (int) PTR_ERR(e
);
362 /* If already enabled, just check consistency */
364 WARN_ON(e
->tp
!= tp
);
369 /* register each (probe, data) */
370 list_for_each_entry(p
, &e
->probes
, list
) {
373 ret
= tracepoint_probe_register(e
->tp
,
374 p
->tp_func
.func
, p
->tp_func
.data
);
378 mutex_unlock(<tng_tracepoint_mutex
);
382 void lttng_kernel_tracepoint_remove(struct tracepoint
*tp
, void *priv
)
384 struct tracepoint_entry
*e
;
387 mutex_lock(<tng_tracepoint_mutex
);
388 e
= get_tracepoint(tp
->name
);
389 if (!e
|| e
->refcount
!= 1 || !list_empty(&e
->probes
)) {
393 remove_tracepoint(e
);
395 mutex_unlock(<tng_tracepoint_mutex
);
398 int __init
lttng_tracepoint_init(void)
402 for_each_kernel_tracepoint(lttng_kernel_tracepoint_add
, &ret
);
405 ret
= lttng_tracepoint_module_init();
414 for_each_kernel_tracepoint(lttng_kernel_tracepoint_remove
,
422 void lttng_tracepoint_exit(void)
426 lttng_tracepoint_module_exit();
427 for_each_kernel_tracepoint(lttng_kernel_tracepoint_remove
, &ret
);
429 mutex_lock(<tng_tracepoint_mutex
);
430 for (i
= 0; i
< TRACEPOINT_TABLE_SIZE
; i
++) {
431 struct hlist_head
*head
= &tracepoint_table
[i
];
433 /* All tracepoints should be removed */
434 WARN_ON(!hlist_empty(head
));
436 mutex_unlock(<tng_tracepoint_mutex
);