4 * LTTng adaptation layer for Linux kernel 3.15+ tracepoints.
6 * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <linux/mutex.h>
24 #include <linux/err.h>
25 #include <linux/notifier.h>
26 #include <linux/tracepoint.h>
27 #include <linux/slab.h>
28 #include <linux/jhash.h>
29 #include <linux/module.h>
31 #include <lttng-tracepoint.h>
32 #include <wrapper/list.h>
33 #include <wrapper/tracepoint.h>
36 * Protect the tracepoint table. lttng_tracepoint_mutex nests within
37 * kernel/tracepoint.c tp_modlist_mutex. kernel/tracepoint.c
38 * tracepoint_mutex nests within lttng_tracepoint_mutex.
41 DEFINE_MUTEX(lttng_tracepoint_mutex
);
43 #define TRACEPOINT_HASH_BITS 6
44 #define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
46 struct hlist_head tracepoint_table
[TRACEPOINT_TABLE_SIZE
];
49 * The tracepoint entry is the node contained within the hash table. It
50 * is a mapping from the "string" key to the struct tracepoint pointer.
52 struct tracepoint_entry
{
53 struct hlist_node hlist
;
54 struct tracepoint
*tp
;
56 struct list_head probes
;
60 struct lttng_tp_probe
{
61 struct tracepoint_func tp_func
;
62 struct list_head list
;
66 int add_probe(struct tracepoint_entry
*e
, void *probe
, void *data
)
68 struct lttng_tp_probe
*p
;
71 list_for_each_entry(p
, &e
->probes
, list
) {
72 if (p
->tp_func
.func
== probe
&& p
->tp_func
.data
== data
) {
79 p
= kmalloc(sizeof(struct lttng_tp_probe
), GFP_KERNEL
);
82 p
->tp_func
.func
= probe
;
83 p
->tp_func
.data
= data
;
84 list_add(&p
->list
, &e
->probes
);
89 int remove_probe(struct tracepoint_entry
*e
, void *probe
, void *data
)
91 struct lttng_tp_probe
*p
;
94 list_for_each_entry(p
, &e
->probes
, list
) {
95 if (p
->tp_func
.func
== probe
&& p
->tp_func
.data
== data
) {
111 * Get tracepoint if the tracepoint is present in the tracepoint hash table.
112 * Must be called with lttng_tracepoint_mutex held.
113 * Returns NULL if not present.
116 struct tracepoint_entry
*get_tracepoint(const char *name
)
118 struct hlist_head
*head
;
119 struct tracepoint_entry
*e
;
120 u32 hash
= jhash(name
, strlen(name
), 0);
122 head
= &tracepoint_table
[hash
& (TRACEPOINT_TABLE_SIZE
- 1)];
123 lttng_hlist_for_each_entry(e
, head
, hlist
) {
124 if (!strcmp(name
, e
->name
))
131 * Add the tracepoint to the tracepoint hash table. Must be called with
132 * lttng_tracepoint_mutex held.
135 struct tracepoint_entry
*add_tracepoint(const char *name
)
137 struct hlist_head
*head
;
138 struct tracepoint_entry
*e
;
139 size_t name_len
= strlen(name
) + 1;
140 u32 hash
= jhash(name
, name_len
- 1, 0);
142 head
= &tracepoint_table
[hash
& (TRACEPOINT_TABLE_SIZE
- 1)];
143 lttng_hlist_for_each_entry(e
, head
, hlist
) {
144 if (!strcmp(name
, e
->name
)) {
146 "tracepoint %s busy\n", name
);
147 return ERR_PTR(-EEXIST
); /* Already there */
151 * Using kmalloc here to allocate a variable length element. Could
152 * cause some memory fragmentation if overused.
154 e
= kmalloc(sizeof(struct tracepoint_entry
) + name_len
, GFP_KERNEL
);
156 return ERR_PTR(-ENOMEM
);
157 memcpy(&e
->name
[0], name
, name_len
);
160 INIT_LIST_HEAD(&e
->probes
);
161 hlist_add_head(&e
->hlist
, head
);
166 * Remove the tracepoint from the tracepoint hash table. Must be called
167 * with lttng_tracepoint_mutex held.
170 void remove_tracepoint(struct tracepoint_entry
*e
)
172 hlist_del(&e
->hlist
);
176 int lttng_tracepoint_probe_register(const char *name
, void *probe
, void *data
)
178 struct tracepoint_entry
*e
;
181 mutex_lock(<tng_tracepoint_mutex
);
182 e
= get_tracepoint(name
);
184 e
= add_tracepoint(name
);
190 /* add (probe, data) to entry */
191 ret
= add_probe(e
, probe
, data
);
196 ret
= tracepoint_probe_register(e
->tp
, probe
, data
);
201 mutex_unlock(<tng_tracepoint_mutex
);
205 int lttng_tracepoint_probe_unregister(const char *name
, void *probe
, void *data
)
207 struct tracepoint_entry
*e
;
210 mutex_lock(<tng_tracepoint_mutex
);
211 e
= get_tracepoint(name
);
216 /* remove (probe, data) from entry */
217 ret
= remove_probe(e
, probe
, data
);
221 ret
= tracepoint_probe_unregister(e
->tp
, probe
, data
);
226 remove_tracepoint(e
);
228 mutex_unlock(<tng_tracepoint_mutex
);
232 #ifdef CONFIG_MODULES
235 int lttng_tracepoint_coming(struct tp_module
*tp_mod
)
239 mutex_lock(<tng_tracepoint_mutex
);
240 for (i
= 0; i
< tp_mod
->mod
->num_tracepoints
; i
++) {
241 struct tracepoint
*tp
;
242 struct tracepoint_entry
*e
;
243 struct lttng_tp_probe
*p
;
245 tp
= lttng_tracepoint_ptr_deref(&tp_mod
->mod
->tracepoints_ptrs
[i
]);
246 e
= get_tracepoint(tp
->name
);
248 e
= add_tracepoint(tp
->name
);
250 pr_warn("LTTng: error (%ld) adding tracepoint\n",
255 /* If already enabled, just check consistency */
257 WARN_ON(e
->tp
!= tp
);
262 /* register each (probe, data) */
263 list_for_each_entry(p
, &e
->probes
, list
) {
266 ret
= tracepoint_probe_register(e
->tp
,
267 p
->tp_func
.func
, p
->tp_func
.data
);
271 mutex_unlock(<tng_tracepoint_mutex
);
276 int lttng_tracepoint_going(struct tp_module
*tp_mod
)
280 mutex_lock(<tng_tracepoint_mutex
);
281 for (i
= 0; i
< tp_mod
->mod
->num_tracepoints
; i
++) {
282 struct tracepoint
*tp
;
283 struct tracepoint_entry
*e
;
284 struct lttng_tp_probe
*p
;
286 tp
= lttng_tracepoint_ptr_deref(&tp_mod
->mod
->tracepoints_ptrs
[i
]);
287 e
= get_tracepoint(tp
->name
);
290 /* unregister each (probe, data) */
291 list_for_each_entry(p
, &e
->probes
, list
) {
294 ret
= tracepoint_probe_unregister(e
->tp
,
295 p
->tp_func
.func
, p
->tp_func
.data
);
300 remove_tracepoint(e
);
302 mutex_unlock(<tng_tracepoint_mutex
);
307 int lttng_tracepoint_notify(struct notifier_block
*self
,
308 unsigned long val
, void *data
)
310 struct tp_module
*tp_mod
= data
;
314 case MODULE_STATE_COMING
:
315 ret
= lttng_tracepoint_coming(tp_mod
);
317 case MODULE_STATE_GOING
:
318 ret
= lttng_tracepoint_going(tp_mod
);
327 struct notifier_block lttng_tracepoint_notifier
= {
328 .notifier_call
= lttng_tracepoint_notify
,
333 int lttng_tracepoint_module_init(void)
335 return register_tracepoint_module_notifier(<tng_tracepoint_notifier
);
339 void lttng_tracepoint_module_exit(void)
341 WARN_ON(unregister_tracepoint_module_notifier(<tng_tracepoint_notifier
));
344 #else /* #ifdef CONFIG_MODULES */
347 int lttng_tracepoint_module_init(void)
353 void lttng_tracepoint_module_exit(void)
357 #endif /* #else #ifdef CONFIG_MODULES */
360 void lttng_kernel_tracepoint_add(struct tracepoint
*tp
, void *priv
)
362 struct tracepoint_entry
*e
;
363 struct lttng_tp_probe
*p
;
366 mutex_lock(<tng_tracepoint_mutex
);
367 e
= get_tracepoint(tp
->name
);
369 e
= add_tracepoint(tp
->name
);
371 pr_warn("LTTng: error (%ld) adding tracepoint\n",
373 *ret
= (int) PTR_ERR(e
);
377 /* If already enabled, just check consistency */
379 WARN_ON(e
->tp
!= tp
);
384 /* register each (probe, data) */
385 list_for_each_entry(p
, &e
->probes
, list
) {
388 ret
= tracepoint_probe_register(e
->tp
,
389 p
->tp_func
.func
, p
->tp_func
.data
);
393 mutex_unlock(<tng_tracepoint_mutex
);
397 void lttng_kernel_tracepoint_remove(struct tracepoint
*tp
, void *priv
)
399 struct tracepoint_entry
*e
;
402 mutex_lock(<tng_tracepoint_mutex
);
403 e
= get_tracepoint(tp
->name
);
404 if (!e
|| e
->refcount
!= 1 || !list_empty(&e
->probes
)) {
408 remove_tracepoint(e
);
410 mutex_unlock(<tng_tracepoint_mutex
);
413 int __init
lttng_tracepoint_init(void)
417 for_each_kernel_tracepoint(lttng_kernel_tracepoint_add
, &ret
);
420 ret
= lttng_tracepoint_module_init();
429 for_each_kernel_tracepoint(lttng_kernel_tracepoint_remove
,
437 void lttng_tracepoint_exit(void)
441 lttng_tracepoint_module_exit();
442 for_each_kernel_tracepoint(lttng_kernel_tracepoint_remove
, &ret
);
444 mutex_lock(<tng_tracepoint_mutex
);
445 for (i
= 0; i
< TRACEPOINT_TABLE_SIZE
; i
++) {
446 struct hlist_head
*head
= &tracepoint_table
[i
];
448 /* All tracepoints should be removed */
449 WARN_ON(!hlist_empty(head
));
451 mutex_unlock(<tng_tracepoint_mutex
);