aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/tracepoint.c
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>2014-04-08 17:26:21 -0400
committerSteven Rostedt <rostedt@goodmis.org>2014-04-08 20:43:28 -0400
commitde7b2973903c6cc50b31ee5682a69b2219b9919d (patch)
treea5b9d78102854b0073f5893cafb29920f8fb55e1 /kernel/tracepoint.c
parent68114e5eb862ad0a7a261b91497281b026102715 (diff)
tracepoint: Use struct pointer instead of name hash for reg/unreg tracepoints
Register/unregister tracepoint probes with struct tracepoint pointer rather than tracepoint name. This change, which vastly simplifies tracepoint.c, has been proposed by Steven Rostedt. It also removes 8.8kB (mostly of text) to the vmlinux size. From this point on, the tracers need to pass a struct tracepoint pointer to probe register/unregister. A probe can now only be connected to a tracepoint that exists. Moreover, tracers are responsible for unregistering the probe before the module containing its associated tracepoint is unloaded. text data bss dec hex filename 10443444 4282528 10391552 25117524 17f4354 vmlinux.orig 10434930 4282848 10391552 25109330 17f2352 vmlinux Link: http://lkml.kernel.org/r/1396992381-23785-2-git-send-email-mathieu.desnoyers@efficios.com CC: Ingo Molnar <mingo@kernel.org> CC: Frederic Weisbecker <fweisbec@gmail.com> CC: Andrew Morton <akpm@linux-foundation.org> CC: Frank Ch. Eigler <fche@redhat.com> CC: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> [ SDR - fixed return val in void func in tracepoint_module_going() ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/tracepoint.c')
-rw-r--r--kernel/tracepoint.c511
1 files changed, 220 insertions, 291 deletions
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 50f8329c2042..01b3bd84daa1 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2008 Mathieu Desnoyers 2 * Copyright (C) 2008-2014 Mathieu Desnoyers
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
@@ -33,39 +33,27 @@ extern struct tracepoint * const __stop___tracepoints_ptrs[];
33/* Set to 1 to enable tracepoint debug output */ 33/* Set to 1 to enable tracepoint debug output */
34static const int tracepoint_debug; 34static const int tracepoint_debug;
35 35
36#ifdef CONFIG_MODULES
36/* 37/*
37 * Tracepoints mutex protects the builtin and module tracepoints and the hash 38 * Tracepoint module list mutex protects the local module list.
38 * table, as well as the local module list.
39 */ 39 */
40static DEFINE_MUTEX(tracepoints_mutex); 40static DEFINE_MUTEX(tracepoint_module_list_mutex);
41 41
42#ifdef CONFIG_MODULES 42/* Local list of struct tp_module */
43/* Local list of struct module */
44static LIST_HEAD(tracepoint_module_list); 43static LIST_HEAD(tracepoint_module_list);
45#endif /* CONFIG_MODULES */ 44#endif /* CONFIG_MODULES */
46 45
47/* 46/*
48 * Tracepoint hash table, containing the active tracepoints. 47 * tracepoints_mutex protects the builtin and module tracepoints.
49 * Protected by tracepoints_mutex. 48 * tracepoints_mutex nests inside tracepoint_module_list_mutex.
50 */ 49 */
51#define TRACEPOINT_HASH_BITS 6 50static DEFINE_MUTEX(tracepoints_mutex);
52#define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
53static struct hlist_head tracepoint_table[TRACEPOINT_TABLE_SIZE];
54 51
55/* 52/*
56 * Note about RCU : 53 * Note about RCU :
57 * It is used to delay the free of multiple probes array until a quiescent 54 * It is used to delay the free of multiple probes array until a quiescent
58 * state is reached. 55 * state is reached.
59 * Tracepoint entries modifications are protected by the tracepoints_mutex.
60 */ 56 */
61struct tracepoint_entry {
62 struct hlist_node hlist;
63 struct tracepoint_func *funcs;
64 int refcount; /* Number of times armed. 0 if disarmed. */
65 int enabled; /* Tracepoint enabled */
66 char name[0];
67};
68
69struct tp_probes { 57struct tp_probes {
70 struct rcu_head rcu; 58 struct rcu_head rcu;
71 struct tracepoint_func probes[0]; 59 struct tracepoint_func probes[0];
@@ -92,34 +80,33 @@ static inline void release_probes(struct tracepoint_func *old)
92 } 80 }
93} 81}
94 82
95static void debug_print_probes(struct tracepoint_entry *entry) 83static void debug_print_probes(struct tracepoint_func *funcs)
96{ 84{
97 int i; 85 int i;
98 86
99 if (!tracepoint_debug || !entry->funcs) 87 if (!tracepoint_debug || !funcs)
100 return; 88 return;
101 89
102 for (i = 0; entry->funcs[i].func; i++) 90 for (i = 0; funcs[i].func; i++)
103 printk(KERN_DEBUG "Probe %d : %p\n", i, entry->funcs[i].func); 91 printk(KERN_DEBUG "Probe %d : %p\n", i, funcs[i].func);
104} 92}
105 93
106static struct tracepoint_func * 94static struct tracepoint_func *func_add(struct tracepoint_func **funcs,
107tracepoint_entry_add_probe(struct tracepoint_entry *entry, 95 struct tracepoint_func *tp_func)
108 void *probe, void *data)
109{ 96{
110 int nr_probes = 0; 97 int nr_probes = 0;
111 struct tracepoint_func *old, *new; 98 struct tracepoint_func *old, *new;
112 99
113 if (WARN_ON(!probe)) 100 if (WARN_ON(!tp_func->func))
114 return ERR_PTR(-EINVAL); 101 return ERR_PTR(-EINVAL);
115 102
116 debug_print_probes(entry); 103 debug_print_probes(*funcs);
117 old = entry->funcs; 104 old = *funcs;
118 if (old) { 105 if (old) {
119 /* (N -> N+1), (N != 0, 1) probes */ 106 /* (N -> N+1), (N != 0, 1) probes */
120 for (nr_probes = 0; old[nr_probes].func; nr_probes++) 107 for (nr_probes = 0; old[nr_probes].func; nr_probes++)
121 if (old[nr_probes].func == probe && 108 if (old[nr_probes].func == tp_func->func &&
122 old[nr_probes].data == data) 109 old[nr_probes].data == tp_func->data)
123 return ERR_PTR(-EEXIST); 110 return ERR_PTR(-EEXIST);
124 } 111 }
125 /* + 2 : one for new probe, one for NULL func */ 112 /* + 2 : one for new probe, one for NULL func */
@@ -128,33 +115,30 @@ tracepoint_entry_add_probe(struct tracepoint_entry *entry,
128 return ERR_PTR(-ENOMEM); 115 return ERR_PTR(-ENOMEM);
129 if (old) 116 if (old)
130 memcpy(new, old, nr_probes * sizeof(struct tracepoint_func)); 117 memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
131 new[nr_probes].func = probe; 118 new[nr_probes] = *tp_func;
132 new[nr_probes].data = data;
133 new[nr_probes + 1].func = NULL; 119 new[nr_probes + 1].func = NULL;
134 entry->refcount = nr_probes + 1; 120 *funcs = new;
135 entry->funcs = new; 121 debug_print_probes(*funcs);
136 debug_print_probes(entry);
137 return old; 122 return old;
138} 123}
139 124
140static void * 125static void *func_remove(struct tracepoint_func **funcs,
141tracepoint_entry_remove_probe(struct tracepoint_entry *entry, 126 struct tracepoint_func *tp_func)
142 void *probe, void *data)
143{ 127{
144 int nr_probes = 0, nr_del = 0, i; 128 int nr_probes = 0, nr_del = 0, i;
145 struct tracepoint_func *old, *new; 129 struct tracepoint_func *old, *new;
146 130
147 old = entry->funcs; 131 old = *funcs;
148 132
149 if (!old) 133 if (!old)
150 return ERR_PTR(-ENOENT); 134 return ERR_PTR(-ENOENT);
151 135
152 debug_print_probes(entry); 136 debug_print_probes(*funcs);
153 /* (N -> M), (N > 1, M >= 0) probes */ 137 /* (N -> M), (N > 1, M >= 0) probes */
154 if (probe) { 138 if (tp_func->func) {
155 for (nr_probes = 0; old[nr_probes].func; nr_probes++) { 139 for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
156 if (old[nr_probes].func == probe && 140 if (old[nr_probes].func == tp_func->func &&
157 old[nr_probes].data == data) 141 old[nr_probes].data == tp_func->data)
158 nr_del++; 142 nr_del++;
159 } 143 }
160 } 144 }
@@ -165,9 +149,8 @@ tracepoint_entry_remove_probe(struct tracepoint_entry *entry,
165 */ 149 */
166 if (nr_probes - nr_del == 0) { 150 if (nr_probes - nr_del == 0) {
167 /* N -> 0, (N > 1) */ 151 /* N -> 0, (N > 1) */
168 entry->funcs = NULL; 152 *funcs = NULL;
169 entry->refcount = 0; 153 debug_print_probes(*funcs);
170 debug_print_probes(entry);
171 return old; 154 return old;
172 } else { 155 } else {
173 int j = 0; 156 int j = 0;
@@ -177,91 +160,34 @@ tracepoint_entry_remove_probe(struct tracepoint_entry *entry,
177 if (new == NULL) 160 if (new == NULL)
178 return ERR_PTR(-ENOMEM); 161 return ERR_PTR(-ENOMEM);
179 for (i = 0; old[i].func; i++) 162 for (i = 0; old[i].func; i++)
180 if (old[i].func != probe || old[i].data != data) 163 if (old[i].func != tp_func->func
164 || old[i].data != tp_func->data)
181 new[j++] = old[i]; 165 new[j++] = old[i];
182 new[nr_probes - nr_del].func = NULL; 166 new[nr_probes - nr_del].func = NULL;
183 entry->refcount = nr_probes - nr_del; 167 *funcs = new;
184 entry->funcs = new;
185 } 168 }
186 debug_print_probes(entry); 169 debug_print_probes(*funcs);
187 return old; 170 return old;
188} 171}
189 172
190/* 173/*
191 * Get tracepoint if the tracepoint is present in the tracepoint hash table. 174 * Add the probe function to a tracepoint.
192 * Must be called with tracepoints_mutex held.
193 * Returns NULL if not present.
194 */ 175 */
195static struct tracepoint_entry *get_tracepoint(const char *name) 176static int tracepoint_add_func(struct tracepoint *tp,
177 struct tracepoint_func *func)
196{ 178{
197 struct hlist_head *head; 179 struct tracepoint_func *old, *tp_funcs;
198 struct tracepoint_entry *e;
199 u32 hash = jhash(name, strlen(name), 0);
200
201 head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
202 hlist_for_each_entry(e, head, hlist) {
203 if (!strcmp(name, e->name))
204 return e;
205 }
206 return NULL;
207}
208 180
209/* 181 if (tp->regfunc && !static_key_enabled(&tp->key))
210 * Add the tracepoint to the tracepoint hash table. Must be called with 182 tp->regfunc();
211 * tracepoints_mutex held.
212 */
213static struct tracepoint_entry *add_tracepoint(const char *name)
214{
215 struct hlist_head *head;
216 struct tracepoint_entry *e;
217 size_t name_len = strlen(name) + 1;
218 u32 hash = jhash(name, name_len-1, 0);
219
220 head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
221 hlist_for_each_entry(e, head, hlist) {
222 if (!strcmp(name, e->name)) {
223 printk(KERN_NOTICE
224 "tracepoint %s busy\n", name);
225 return ERR_PTR(-EEXIST); /* Already there */
226 }
227 }
228 /*
229 * Using kmalloc here to allocate a variable length element. Could
230 * cause some memory fragmentation if overused.
231 */
232 e = kmalloc(sizeof(struct tracepoint_entry) + name_len, GFP_KERNEL);
233 if (!e)
234 return ERR_PTR(-ENOMEM);
235 memcpy(&e->name[0], name, name_len);
236 e->funcs = NULL;
237 e->refcount = 0;
238 e->enabled = 0;
239 hlist_add_head(&e->hlist, head);
240 return e;
241}
242 183
243/* 184 tp_funcs = tp->funcs;
244 * Remove the tracepoint from the tracepoint hash table. Must be called with 185 old = func_add(&tp_funcs, func);
245 * mutex_lock held. 186 if (IS_ERR(old)) {
246 */ 187 WARN_ON_ONCE(1);
247static inline void remove_tracepoint(struct tracepoint_entry *e) 188 return PTR_ERR(old);
248{ 189 }
249 hlist_del(&e->hlist); 190 release_probes(old);
250 kfree(e);
251}
252
253/*
254 * Sets the probe callback corresponding to one tracepoint.
255 */
256static void set_tracepoint(struct tracepoint_entry **entry,
257 struct tracepoint *elem, int active)
258{
259 WARN_ON(strcmp((*entry)->name, elem->name) != 0);
260
261 if (elem->regfunc && !static_key_enabled(&elem->key) && active)
262 elem->regfunc();
263 else if (elem->unregfunc && static_key_enabled(&elem->key) && !active)
264 elem->unregfunc();
265 191
266 /* 192 /*
267 * rcu_assign_pointer has a smp_wmb() which makes sure that the new 193 * rcu_assign_pointer has a smp_wmb() which makes sure that the new
@@ -270,199 +196,163 @@ static void set_tracepoint(struct tracepoint_entry **entry,
270 * include/linux/tracepoints.h. A matching smp_read_barrier_depends() 196 * include/linux/tracepoints.h. A matching smp_read_barrier_depends()
271 * is used. 197 * is used.
272 */ 198 */
273 rcu_assign_pointer(elem->funcs, (*entry)->funcs); 199 rcu_assign_pointer(tp->funcs, tp_funcs);
274 if (active && !static_key_enabled(&elem->key)) 200 if (!static_key_enabled(&tp->key))
275 static_key_slow_inc(&elem->key); 201 static_key_slow_inc(&tp->key);
276 else if (!active && static_key_enabled(&elem->key)) 202 return 0;
277 static_key_slow_dec(&elem->key);
278} 203}
279 204
280/* 205/*
281 * Disable a tracepoint and its probe callback. 206 * Remove a probe function from a tracepoint.
282 * Note: only waiting an RCU period after setting elem->call to the empty 207 * Note: only waiting an RCU period after setting elem->call to the empty
283 * function insures that the original callback is not used anymore. This insured 208 * function insures that the original callback is not used anymore. This insured
284 * by preempt_disable around the call site. 209 * by preempt_disable around the call site.
285 */ 210 */
286static void disable_tracepoint(struct tracepoint *elem) 211static int tracepoint_remove_func(struct tracepoint *tp,
212 struct tracepoint_func *func)
287{ 213{
288 if (elem->unregfunc && static_key_enabled(&elem->key)) 214 struct tracepoint_func *old, *tp_funcs;
289 elem->unregfunc();
290
291 if (static_key_enabled(&elem->key))
292 static_key_slow_dec(&elem->key);
293 rcu_assign_pointer(elem->funcs, NULL);
294}
295 215
296/** 216 tp_funcs = tp->funcs;
297 * tracepoint_update_probe_range - Update a probe range 217 old = func_remove(&tp_funcs, func);
298 * @begin: beginning of the range 218 if (IS_ERR(old)) {
299 * @end: end of the range 219 WARN_ON_ONCE(1);
300 * 220 return PTR_ERR(old);
301 * Updates the probe callback corresponding to a range of tracepoints.
302 * Called with tracepoints_mutex held.
303 */
304static void tracepoint_update_probe_range(struct tracepoint * const *begin,
305 struct tracepoint * const *end)
306{
307 struct tracepoint * const *iter;
308 struct tracepoint_entry *mark_entry;
309
310 if (!begin)
311 return;
312
313 for (iter = begin; iter < end; iter++) {
314 mark_entry = get_tracepoint((*iter)->name);
315 if (mark_entry) {
316 set_tracepoint(&mark_entry, *iter,
317 !!mark_entry->refcount);
318 mark_entry->enabled = !!mark_entry->refcount;
319 } else {
320 disable_tracepoint(*iter);
321 }
322 } 221 }
323} 222 release_probes(old);
324
325#ifdef CONFIG_MODULES
326void module_update_tracepoints(void)
327{
328 struct tp_module *tp_mod;
329
330 list_for_each_entry(tp_mod, &tracepoint_module_list, list)
331 tracepoint_update_probe_range(tp_mod->tracepoints_ptrs,
332 tp_mod->tracepoints_ptrs + tp_mod->num_tracepoints);
333}
334#else /* CONFIG_MODULES */
335void module_update_tracepoints(void)
336{
337}
338#endif /* CONFIG_MODULES */
339 223
224 if (!tp_funcs) {
225 /* Removed last function */
226 if (tp->unregfunc && static_key_enabled(&tp->key))
227 tp->unregfunc();
340 228
341/* 229 if (static_key_enabled(&tp->key))
342 * Update probes, removing the faulty probes. 230 static_key_slow_dec(&tp->key);
343 * Called with tracepoints_mutex held.
344 */
345static void tracepoint_update_probes(void)
346{
347 /* Core kernel tracepoints */
348 tracepoint_update_probe_range(__start___tracepoints_ptrs,
349 __stop___tracepoints_ptrs);
350 /* tracepoints in modules. */
351 module_update_tracepoints();
352}
353
354static struct tracepoint_func *
355tracepoint_add_probe(const char *name, void *probe, void *data)
356{
357 struct tracepoint_entry *entry;
358 struct tracepoint_func *old;
359
360 entry = get_tracepoint(name);
361 if (!entry) {
362 entry = add_tracepoint(name);
363 if (IS_ERR(entry))
364 return (struct tracepoint_func *)entry;
365 } 231 }
366 old = tracepoint_entry_add_probe(entry, probe, data); 232 rcu_assign_pointer(tp->funcs, tp_funcs);
367 if (IS_ERR(old) && !entry->refcount) 233 return 0;
368 remove_tracepoint(entry);
369 return old;
370} 234}
371 235
372/** 236/**
373 * tracepoint_probe_register - Connect a probe to a tracepoint 237 * tracepoint_probe_register - Connect a probe to a tracepoint
374 * @name: tracepoint name 238 * @tp: tracepoint
375 * @probe: probe handler 239 * @probe: probe handler
376 * @data: probe private data
377 *
378 * Returns:
379 * - 0 if the probe was successfully registered, and tracepoint
380 * callsites are currently loaded for that probe,
381 * - -ENODEV if the probe was successfully registered, but no tracepoint
382 * callsite is currently loaded for that probe,
383 * - other negative error value on error.
384 *
385 * When tracepoint_probe_register() returns either 0 or -ENODEV,
386 * parameters @name, @probe, and @data may be used by the tracepoint
387 * infrastructure until the probe is unregistered.
388 * 240 *
389 * The probe address must at least be aligned on the architecture pointer size. 241 * Returns 0 if ok, error value on error.
242 * Note: if @tp is within a module, the caller is responsible for
243 * unregistering the probe before the module is gone. This can be
244 * performed either with a tracepoint module going notifier, or from
245 * within module exit functions.
390 */ 246 */
391int tracepoint_probe_register(const char *name, void *probe, void *data) 247int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data)
392{ 248{
393 struct tracepoint_func *old; 249 struct tracepoint_func tp_func;
394 struct tracepoint_entry *entry; 250 int ret;
395 int ret = 0;
396 251
397 mutex_lock(&tracepoints_mutex); 252 mutex_lock(&tracepoints_mutex);
398 old = tracepoint_add_probe(name, probe, data); 253 tp_func.func = probe;
399 if (IS_ERR(old)) { 254 tp_func.data = data;
400 mutex_unlock(&tracepoints_mutex); 255 ret = tracepoint_add_func(tp, &tp_func);
401 return PTR_ERR(old);
402 }
403 tracepoint_update_probes(); /* may update entry */
404 entry = get_tracepoint(name);
405 /* Make sure the entry was enabled */
406 if (!entry || !entry->enabled)
407 ret = -ENODEV;
408 mutex_unlock(&tracepoints_mutex); 256 mutex_unlock(&tracepoints_mutex);
409 release_probes(old);
410 return ret; 257 return ret;
411} 258}
412EXPORT_SYMBOL_GPL(tracepoint_probe_register); 259EXPORT_SYMBOL_GPL(tracepoint_probe_register);
413 260
414static struct tracepoint_func *
415tracepoint_remove_probe(const char *name, void *probe, void *data)
416{
417 struct tracepoint_entry *entry;
418 struct tracepoint_func *old;
419
420 entry = get_tracepoint(name);
421 if (!entry)
422 return ERR_PTR(-ENOENT);
423 old = tracepoint_entry_remove_probe(entry, probe, data);
424 if (IS_ERR(old))
425 return old;
426 if (!entry->refcount)
427 remove_tracepoint(entry);
428 return old;
429}
430
431/** 261/**
432 * tracepoint_probe_unregister - Disconnect a probe from a tracepoint 262 * tracepoint_probe_unregister - Disconnect a probe from a tracepoint
433 * @name: tracepoint name 263 * @tp: tracepoint
434 * @probe: probe function pointer 264 * @probe: probe function pointer
435 * @data: probe private data
436 * 265 *
437 * We do not need to call a synchronize_sched to make sure the probes have 266 * Returns 0 if ok, error value on error.
438 * finished running before doing a module unload, because the module unload
439 * itself uses stop_machine(), which insures that every preempt disabled section
440 * have finished.
441 */ 267 */
442int tracepoint_probe_unregister(const char *name, void *probe, void *data) 268int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data)
443{ 269{
444 struct tracepoint_func *old; 270 struct tracepoint_func tp_func;
271 int ret;
445 272
446 mutex_lock(&tracepoints_mutex); 273 mutex_lock(&tracepoints_mutex);
447 old = tracepoint_remove_probe(name, probe, data); 274 tp_func.func = probe;
448 if (IS_ERR(old)) { 275 tp_func.data = data;
449 mutex_unlock(&tracepoints_mutex); 276 ret = tracepoint_remove_func(tp, &tp_func);
450 return PTR_ERR(old);
451 }
452 tracepoint_update_probes(); /* may update entry */
453 mutex_unlock(&tracepoints_mutex); 277 mutex_unlock(&tracepoints_mutex);
454 release_probes(old); 278 return ret;
455 return 0;
456} 279}
457EXPORT_SYMBOL_GPL(tracepoint_probe_unregister); 280EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
458 281
459
460#ifdef CONFIG_MODULES 282#ifdef CONFIG_MODULES
461bool trace_module_has_bad_taint(struct module *mod) 283bool trace_module_has_bad_taint(struct module *mod)
462{ 284{
463 return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP)); 285 return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP));
464} 286}
465 287
288static BLOCKING_NOTIFIER_HEAD(tracepoint_notify_list);
289
290/**
291 * register_tracepoint_notifier - register tracepoint coming/going notifier
292 * @nb: notifier block
293 *
294 * Notifiers registered with this function are called on module
295 * coming/going with the tracepoint_module_list_mutex held.
296 * The notifier block callback should expect a "struct tp_module" data
297 * pointer.
298 */
299int register_tracepoint_module_notifier(struct notifier_block *nb)
300{
301 struct tp_module *tp_mod;
302 int ret;
303
304 mutex_lock(&tracepoint_module_list_mutex);
305 ret = blocking_notifier_chain_register(&tracepoint_notify_list, nb);
306 if (ret)
307 goto end;
308 list_for_each_entry(tp_mod, &tracepoint_module_list, list)
309 (void) nb->notifier_call(nb, MODULE_STATE_COMING, tp_mod);
310end:
311 mutex_unlock(&tracepoint_module_list_mutex);
312 return ret;
313}
314EXPORT_SYMBOL_GPL(register_tracepoint_module_notifier);
315
316/**
317 * unregister_tracepoint_notifier - unregister tracepoint coming/going notifier
318 * @nb: notifier block
319 *
320 * The notifier block callback should expect a "struct tp_module" data
321 * pointer.
322 */
323int unregister_tracepoint_module_notifier(struct notifier_block *nb)
324{
325 struct tp_module *tp_mod;
326 int ret;
327
328 mutex_lock(&tracepoint_module_list_mutex);
329 ret = blocking_notifier_chain_unregister(&tracepoint_notify_list, nb);
330 if (ret)
331 goto end;
332 list_for_each_entry(tp_mod, &tracepoint_module_list, list)
333 (void) nb->notifier_call(nb, MODULE_STATE_GOING, tp_mod);
334end:
335 mutex_unlock(&tracepoint_module_list_mutex);
336 return ret;
337
338}
339EXPORT_SYMBOL_GPL(unregister_tracepoint_module_notifier);
340
341/*
342 * Ensure the tracer unregistered the module's probes before the module
343 * teardown is performed. Prevents leaks of probe and data pointers.
344 */
345static void tp_module_going_check_quiescent(struct tracepoint * const *begin,
346 struct tracepoint * const *end)
347{
348 struct tracepoint * const *iter;
349
350 if (!begin)
351 return;
352 for (iter = begin; iter < end; iter++)
353 WARN_ON_ONCE((*iter)->funcs);
354}
355
466static int tracepoint_module_coming(struct module *mod) 356static int tracepoint_module_coming(struct module *mod)
467{ 357{
468 struct tp_module *tp_mod; 358 struct tp_module *tp_mod;
@@ -478,7 +368,7 @@ static int tracepoint_module_coming(struct module *mod)
478 */ 368 */
479 if (trace_module_has_bad_taint(mod)) 369 if (trace_module_has_bad_taint(mod))
480 return 0; 370 return 0;
481 mutex_lock(&tracepoints_mutex); 371 mutex_lock(&tracepoint_module_list_mutex);
482 tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL); 372 tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL);
483 if (!tp_mod) { 373 if (!tp_mod) {
484 ret = -ENOMEM; 374 ret = -ENOMEM;
@@ -487,27 +377,33 @@ static int tracepoint_module_coming(struct module *mod)
487 tp_mod->num_tracepoints = mod->num_tracepoints; 377 tp_mod->num_tracepoints = mod->num_tracepoints;
488 tp_mod->tracepoints_ptrs = mod->tracepoints_ptrs; 378 tp_mod->tracepoints_ptrs = mod->tracepoints_ptrs;
489 list_add_tail(&tp_mod->list, &tracepoint_module_list); 379 list_add_tail(&tp_mod->list, &tracepoint_module_list);
490 tracepoint_update_probe_range(mod->tracepoints_ptrs, 380 blocking_notifier_call_chain(&tracepoint_notify_list,
491 mod->tracepoints_ptrs + mod->num_tracepoints); 381 MODULE_STATE_COMING, tp_mod);
492end: 382end:
493 mutex_unlock(&tracepoints_mutex); 383 mutex_unlock(&tracepoint_module_list_mutex);
494 return ret; 384 return ret;
495} 385}
496 386
497static int tracepoint_module_going(struct module *mod) 387static void tracepoint_module_going(struct module *mod)
498{ 388{
499 struct tp_module *pos; 389 struct tp_module *tp_mod;
500 390
501 if (!mod->num_tracepoints) 391 if (!mod->num_tracepoints)
502 return 0; 392 return;
503 393
504 mutex_lock(&tracepoints_mutex); 394 mutex_lock(&tracepoint_module_list_mutex);
505 tracepoint_update_probe_range(mod->tracepoints_ptrs, 395 list_for_each_entry(tp_mod, &tracepoint_module_list, list) {
506 mod->tracepoints_ptrs + mod->num_tracepoints); 396 if (tp_mod->tracepoints_ptrs == mod->tracepoints_ptrs) {
507 list_for_each_entry(pos, &tracepoint_module_list, list) { 397 blocking_notifier_call_chain(&tracepoint_notify_list,
508 if (pos->tracepoints_ptrs == mod->tracepoints_ptrs) { 398 MODULE_STATE_GOING, tp_mod);
509 list_del(&pos->list); 399 list_del(&tp_mod->list);
510 kfree(pos); 400 kfree(tp_mod);
401 /*
402 * Called the going notifier before checking for
403 * quiescence.
404 */
405 tp_module_going_check_quiescent(mod->tracepoints_ptrs,
406 mod->tracepoints_ptrs + mod->num_tracepoints);
511 break; 407 break;
512 } 408 }
513 } 409 }
@@ -517,12 +413,11 @@ static int tracepoint_module_going(struct module *mod)
517 * flag on "going", in case a module taints the kernel only after being 413 * flag on "going", in case a module taints the kernel only after being
518 * loaded. 414 * loaded.
519 */ 415 */
520 mutex_unlock(&tracepoints_mutex); 416 mutex_unlock(&tracepoint_module_list_mutex);
521 return 0;
522} 417}
523 418
524int tracepoint_module_notify(struct notifier_block *self, 419static int tracepoint_module_notify(struct notifier_block *self,
525 unsigned long val, void *data) 420 unsigned long val, void *data)
526{ 421{
527 struct module *mod = data; 422 struct module *mod = data;
528 int ret = 0; 423 int ret = 0;
@@ -534,24 +429,58 @@ int tracepoint_module_notify(struct notifier_block *self,
534 case MODULE_STATE_LIVE: 429 case MODULE_STATE_LIVE:
535 break; 430 break;
536 case MODULE_STATE_GOING: 431 case MODULE_STATE_GOING:
537 ret = tracepoint_module_going(mod); 432 tracepoint_module_going(mod);
433 break;
434 case MODULE_STATE_UNFORMED:
538 break; 435 break;
539 } 436 }
540 return ret; 437 return ret;
541} 438}
542 439
543struct notifier_block tracepoint_module_nb = { 440static struct notifier_block tracepoint_module_nb = {
544 .notifier_call = tracepoint_module_notify, 441 .notifier_call = tracepoint_module_notify,
545 .priority = 0, 442 .priority = 0,
546}; 443};
547 444
548static int init_tracepoints(void) 445static __init int init_tracepoints(void)
549{ 446{
550 return register_module_notifier(&tracepoint_module_nb); 447 int ret;
448
449 ret = register_module_notifier(&tracepoint_module_nb);
450 if (ret) {
451 pr_warning("Failed to register tracepoint module enter notifier\n");
452 }
453 return ret;
551} 454}
552__initcall(init_tracepoints); 455__initcall(init_tracepoints);
553#endif /* CONFIG_MODULES */ 456#endif /* CONFIG_MODULES */
554 457
458static void for_each_tracepoint_range(struct tracepoint * const *begin,
459 struct tracepoint * const *end,
460 void (*fct)(struct tracepoint *tp, void *priv),
461 void *priv)
462{
463 struct tracepoint * const *iter;
464
465 if (!begin)
466 return;
467 for (iter = begin; iter < end; iter++)
468 fct(*iter, priv);
469}
470
471/**
472 * for_each_kernel_tracepoint - iteration on all kernel tracepoints
473 * @fct: callback
474 * @priv: private data
475 */
476void for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv),
477 void *priv)
478{
479 for_each_tracepoint_range(__start___tracepoints_ptrs,
480 __stop___tracepoints_ptrs, fct, priv);
481}
482EXPORT_SYMBOL_GPL(for_each_kernel_tracepoint);
483
555#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS 484#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
556 485
557/* NB: reg/unreg are called while guarded with the tracepoints_mutex */ 486/* NB: reg/unreg are called while guarded with the tracepoints_mutex */