diff options
Diffstat (limited to 'kernel/tracepoint.c')
-rw-r--r-- | kernel/tracepoint.c | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index c77f3eceea25..b219f1449c54 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c | |||
@@ -25,9 +25,10 @@ | |||
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/jump_label.h> | ||
28 | 29 | ||
29 | extern struct tracepoint __start___tracepoints[]; | 30 | extern struct tracepoint * const __start___tracepoints_ptrs[]; |
30 | extern struct tracepoint __stop___tracepoints[]; | 31 | extern struct tracepoint * const __stop___tracepoints_ptrs[]; |
31 | 32 | ||
32 | /* Set to 1 to enable tracepoint debug output */ | 33 | /* Set to 1 to enable tracepoint debug output */ |
33 | static const int tracepoint_debug; | 34 | static const int tracepoint_debug; |
@@ -250,9 +251,9 @@ static void set_tracepoint(struct tracepoint_entry **entry, | |||
250 | { | 251 | { |
251 | WARN_ON(strcmp((*entry)->name, elem->name) != 0); | 252 | WARN_ON(strcmp((*entry)->name, elem->name) != 0); |
252 | 253 | ||
253 | if (elem->regfunc && !elem->state && active) | 254 | if (elem->regfunc && !jump_label_enabled(&elem->key) && active) |
254 | elem->regfunc(); | 255 | elem->regfunc(); |
255 | else if (elem->unregfunc && elem->state && !active) | 256 | else if (elem->unregfunc && jump_label_enabled(&elem->key) && !active) |
256 | elem->unregfunc(); | 257 | elem->unregfunc(); |
257 | 258 | ||
258 | /* | 259 | /* |
@@ -263,7 +264,10 @@ static void set_tracepoint(struct tracepoint_entry **entry, | |||
263 | * is used. | 264 | * is used. |
264 | */ | 265 | */ |
265 | rcu_assign_pointer(elem->funcs, (*entry)->funcs); | 266 | rcu_assign_pointer(elem->funcs, (*entry)->funcs); |
266 | elem->state = active; | 267 | if (active && !jump_label_enabled(&elem->key)) |
268 | jump_label_inc(&elem->key); | ||
269 | else if (!active && jump_label_enabled(&elem->key)) | ||
270 | jump_label_dec(&elem->key); | ||
267 | } | 271 | } |
268 | 272 | ||
269 | /* | 273 | /* |
@@ -274,10 +278,11 @@ static void set_tracepoint(struct tracepoint_entry **entry, | |||
274 | */ | 278 | */ |
275 | static void disable_tracepoint(struct tracepoint *elem) | 279 | static void disable_tracepoint(struct tracepoint *elem) |
276 | { | 280 | { |
277 | if (elem->unregfunc && elem->state) | 281 | if (elem->unregfunc && jump_label_enabled(&elem->key)) |
278 | elem->unregfunc(); | 282 | elem->unregfunc(); |
279 | 283 | ||
280 | elem->state = 0; | 284 | if (jump_label_enabled(&elem->key)) |
285 | jump_label_dec(&elem->key); | ||
281 | rcu_assign_pointer(elem->funcs, NULL); | 286 | rcu_assign_pointer(elem->funcs, NULL); |
282 | } | 287 | } |
283 | 288 | ||
@@ -288,10 +293,10 @@ static void disable_tracepoint(struct tracepoint *elem) | |||
288 | * | 293 | * |
289 | * Updates the probe callback corresponding to a range of tracepoints. | 294 | * Updates the probe callback corresponding to a range of tracepoints. |
290 | */ | 295 | */ |
291 | void | 296 | void tracepoint_update_probe_range(struct tracepoint * const *begin, |
292 | tracepoint_update_probe_range(struct tracepoint *begin, struct tracepoint *end) | 297 | struct tracepoint * const *end) |
293 | { | 298 | { |
294 | struct tracepoint *iter; | 299 | struct tracepoint * const *iter; |
295 | struct tracepoint_entry *mark_entry; | 300 | struct tracepoint_entry *mark_entry; |
296 | 301 | ||
297 | if (!begin) | 302 | if (!begin) |
@@ -299,12 +304,12 @@ tracepoint_update_probe_range(struct tracepoint *begin, struct tracepoint *end) | |||
299 | 304 | ||
300 | mutex_lock(&tracepoints_mutex); | 305 | mutex_lock(&tracepoints_mutex); |
301 | for (iter = begin; iter < end; iter++) { | 306 | for (iter = begin; iter < end; iter++) { |
302 | mark_entry = get_tracepoint(iter->name); | 307 | mark_entry = get_tracepoint((*iter)->name); |
303 | if (mark_entry) { | 308 | if (mark_entry) { |
304 | set_tracepoint(&mark_entry, iter, | 309 | set_tracepoint(&mark_entry, *iter, |
305 | !!mark_entry->refcount); | 310 | !!mark_entry->refcount); |
306 | } else { | 311 | } else { |
307 | disable_tracepoint(iter); | 312 | disable_tracepoint(*iter); |
308 | } | 313 | } |
309 | } | 314 | } |
310 | mutex_unlock(&tracepoints_mutex); | 315 | mutex_unlock(&tracepoints_mutex); |
@@ -316,8 +321,8 @@ tracepoint_update_probe_range(struct tracepoint *begin, struct tracepoint *end) | |||
316 | static void tracepoint_update_probes(void) | 321 | static void tracepoint_update_probes(void) |
317 | { | 322 | { |
318 | /* Core kernel tracepoints */ | 323 | /* Core kernel tracepoints */ |
319 | tracepoint_update_probe_range(__start___tracepoints, | 324 | tracepoint_update_probe_range(__start___tracepoints_ptrs, |
320 | __stop___tracepoints); | 325 | __stop___tracepoints_ptrs); |
321 | /* tracepoints in modules. */ | 326 | /* tracepoints in modules. */ |
322 | module_update_tracepoints(); | 327 | module_update_tracepoints(); |
323 | } | 328 | } |
@@ -504,8 +509,8 @@ EXPORT_SYMBOL_GPL(tracepoint_probe_update_all); | |||
504 | * Will return the first tracepoint in the range if the input tracepoint is | 509 | * Will return the first tracepoint in the range if the input tracepoint is |
505 | * NULL. | 510 | * NULL. |
506 | */ | 511 | */ |
507 | int tracepoint_get_iter_range(struct tracepoint **tracepoint, | 512 | int tracepoint_get_iter_range(struct tracepoint * const **tracepoint, |
508 | struct tracepoint *begin, struct tracepoint *end) | 513 | struct tracepoint * const *begin, struct tracepoint * const *end) |
509 | { | 514 | { |
510 | if (!*tracepoint && begin != end) { | 515 | if (!*tracepoint && begin != end) { |
511 | *tracepoint = begin; | 516 | *tracepoint = begin; |
@@ -524,7 +529,8 @@ static void tracepoint_get_iter(struct tracepoint_iter *iter) | |||
524 | /* Core kernel tracepoints */ | 529 | /* Core kernel tracepoints */ |
525 | if (!iter->module) { | 530 | if (!iter->module) { |
526 | found = tracepoint_get_iter_range(&iter->tracepoint, | 531 | found = tracepoint_get_iter_range(&iter->tracepoint, |
527 | __start___tracepoints, __stop___tracepoints); | 532 | __start___tracepoints_ptrs, |
533 | __stop___tracepoints_ptrs); | ||
528 | if (found) | 534 | if (found) |
529 | goto end; | 535 | goto end; |
530 | } | 536 | } |
@@ -575,8 +581,8 @@ int tracepoint_module_notify(struct notifier_block *self, | |||
575 | switch (val) { | 581 | switch (val) { |
576 | case MODULE_STATE_COMING: | 582 | case MODULE_STATE_COMING: |
577 | case MODULE_STATE_GOING: | 583 | case MODULE_STATE_GOING: |
578 | tracepoint_update_probe_range(mod->tracepoints, | 584 | tracepoint_update_probe_range(mod->tracepoints_ptrs, |
579 | mod->tracepoints + mod->num_tracepoints); | 585 | mod->tracepoints_ptrs + mod->num_tracepoints); |
580 | break; | 586 | break; |
581 | } | 587 | } |
582 | return 0; | 588 | return 0; |