diff options
Diffstat (limited to 'kernel/marker.c')
-rw-r--r-- | kernel/marker.c | 52 |
1 files changed, 6 insertions, 46 deletions
diff --git a/kernel/marker.c b/kernel/marker.c index 7d1faecd7a51..9f76c4a622ec 100644 --- a/kernel/marker.c +++ b/kernel/marker.c | |||
@@ -60,9 +60,6 @@ struct marker_entry { | |||
60 | struct marker_probe_closure single; | 60 | struct marker_probe_closure single; |
61 | struct marker_probe_closure *multi; | 61 | struct marker_probe_closure *multi; |
62 | int refcount; /* Number of times armed. 0 if disarmed. */ | 62 | int refcount; /* Number of times armed. 0 if disarmed. */ |
63 | struct rcu_head rcu; | ||
64 | void *oldptr; | ||
65 | unsigned char rcu_pending:1; | ||
66 | unsigned char ptype:1; | 63 | unsigned char ptype:1; |
67 | char name[0]; /* Contains name'\0'format'\0' */ | 64 | char name[0]; /* Contains name'\0'format'\0' */ |
68 | }; | 65 | }; |
@@ -199,16 +196,6 @@ void marker_probe_cb_noarg(const struct marker *mdata, void *call_private, ...) | |||
199 | } | 196 | } |
200 | EXPORT_SYMBOL_GPL(marker_probe_cb_noarg); | 197 | EXPORT_SYMBOL_GPL(marker_probe_cb_noarg); |
201 | 198 | ||
202 | static void free_old_closure(struct rcu_head *head) | ||
203 | { | ||
204 | struct marker_entry *entry = container_of(head, | ||
205 | struct marker_entry, rcu); | ||
206 | kfree(entry->oldptr); | ||
207 | /* Make sure we free the data before setting the pending flag to 0 */ | ||
208 | smp_wmb(); | ||
209 | entry->rcu_pending = 0; | ||
210 | } | ||
211 | |||
212 | static void debug_print_probes(struct marker_entry *entry) | 199 | static void debug_print_probes(struct marker_entry *entry) |
213 | { | 200 | { |
214 | int i; | 201 | int i; |
@@ -417,7 +404,6 @@ static struct marker_entry *add_marker(const char *name, const char *format) | |||
417 | e->multi = NULL; | 404 | e->multi = NULL; |
418 | e->ptype = 0; | 405 | e->ptype = 0; |
419 | e->refcount = 0; | 406 | e->refcount = 0; |
420 | e->rcu_pending = 0; | ||
421 | hlist_add_head(&e->hlist, head); | 407 | hlist_add_head(&e->hlist, head); |
422 | return e; | 408 | return e; |
423 | } | 409 | } |
@@ -447,9 +433,6 @@ static int remove_marker(const char *name) | |||
447 | if (e->single.func != __mark_empty_function) | 433 | if (e->single.func != __mark_empty_function) |
448 | return -EBUSY; | 434 | return -EBUSY; |
449 | hlist_del(&e->hlist); | 435 | hlist_del(&e->hlist); |
450 | /* Make sure the call_rcu has been executed */ | ||
451 | if (e->rcu_pending) | ||
452 | rcu_barrier_sched(); | ||
453 | kfree(e); | 436 | kfree(e); |
454 | return 0; | 437 | return 0; |
455 | } | 438 | } |
@@ -479,12 +462,8 @@ static int marker_set_format(struct marker_entry **entry, const char *format) | |||
479 | e->multi = (*entry)->multi; | 462 | e->multi = (*entry)->multi; |
480 | e->ptype = (*entry)->ptype; | 463 | e->ptype = (*entry)->ptype; |
481 | e->refcount = (*entry)->refcount; | 464 | e->refcount = (*entry)->refcount; |
482 | e->rcu_pending = 0; | ||
483 | hlist_add_before(&e->hlist, &(*entry)->hlist); | 465 | hlist_add_before(&e->hlist, &(*entry)->hlist); |
484 | hlist_del(&(*entry)->hlist); | 466 | hlist_del(&(*entry)->hlist); |
485 | /* Make sure the call_rcu has been executed */ | ||
486 | if ((*entry)->rcu_pending) | ||
487 | rcu_barrier_sched(); | ||
488 | kfree(*entry); | 467 | kfree(*entry); |
489 | *entry = e; | 468 | *entry = e; |
490 | trace_mark(core_marker_format, "name %s format %s", | 469 | trace_mark(core_marker_format, "name %s format %s", |
@@ -658,12 +637,6 @@ int marker_probe_register(const char *name, const char *format, | |||
658 | goto end; | 637 | goto end; |
659 | } | 638 | } |
660 | } | 639 | } |
661 | /* | ||
662 | * If we detect that a call_rcu is pending for this marker, | ||
663 | * make sure it's executed now. | ||
664 | */ | ||
665 | if (entry->rcu_pending) | ||
666 | rcu_barrier_sched(); | ||
667 | old = marker_entry_add_probe(entry, probe, probe_private); | 640 | old = marker_entry_add_probe(entry, probe, probe_private); |
668 | if (IS_ERR(old)) { | 641 | if (IS_ERR(old)) { |
669 | ret = PTR_ERR(old); | 642 | ret = PTR_ERR(old); |
@@ -671,14 +644,11 @@ int marker_probe_register(const char *name, const char *format, | |||
671 | } | 644 | } |
672 | mutex_unlock(&markers_mutex); | 645 | mutex_unlock(&markers_mutex); |
673 | marker_update_probes(); /* may update entry */ | 646 | marker_update_probes(); /* may update entry */ |
647 | synchronize_sched(); | ||
648 | kfree(old); | ||
674 | mutex_lock(&markers_mutex); | 649 | mutex_lock(&markers_mutex); |
675 | entry = get_marker(name); | 650 | entry = get_marker(name); |
676 | WARN_ON(!entry); | 651 | WARN_ON(!entry); |
677 | entry->oldptr = old; | ||
678 | entry->rcu_pending = 1; | ||
679 | /* write rcu_pending before calling the RCU callback */ | ||
680 | smp_wmb(); | ||
681 | call_rcu_sched(&entry->rcu, free_old_closure); | ||
682 | end: | 652 | end: |
683 | mutex_unlock(&markers_mutex); | 653 | mutex_unlock(&markers_mutex); |
684 | return ret; | 654 | return ret; |
@@ -708,20 +678,15 @@ int marker_probe_unregister(const char *name, | |||
708 | entry = get_marker(name); | 678 | entry = get_marker(name); |
709 | if (!entry) | 679 | if (!entry) |
710 | goto end; | 680 | goto end; |
711 | if (entry->rcu_pending) | ||
712 | rcu_barrier_sched(); | ||
713 | old = marker_entry_remove_probe(entry, probe, probe_private); | 681 | old = marker_entry_remove_probe(entry, probe, probe_private); |
714 | mutex_unlock(&markers_mutex); | 682 | mutex_unlock(&markers_mutex); |
715 | marker_update_probes(); /* may update entry */ | 683 | marker_update_probes(); /* may update entry */ |
684 | synchronize_sched(); | ||
685 | kfree(old); | ||
716 | mutex_lock(&markers_mutex); | 686 | mutex_lock(&markers_mutex); |
717 | entry = get_marker(name); | 687 | entry = get_marker(name); |
718 | if (!entry) | 688 | if (!entry) |
719 | goto end; | 689 | goto end; |
720 | entry->oldptr = old; | ||
721 | entry->rcu_pending = 1; | ||
722 | /* write rcu_pending before calling the RCU callback */ | ||
723 | smp_wmb(); | ||
724 | call_rcu_sched(&entry->rcu, free_old_closure); | ||
725 | remove_marker(name); /* Ignore busy error message */ | 690 | remove_marker(name); /* Ignore busy error message */ |
726 | ret = 0; | 691 | ret = 0; |
727 | end: | 692 | end: |
@@ -787,19 +752,14 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, | |||
787 | ret = -ENOENT; | 752 | ret = -ENOENT; |
788 | goto end; | 753 | goto end; |
789 | } | 754 | } |
790 | if (entry->rcu_pending) | ||
791 | rcu_barrier_sched(); | ||
792 | old = marker_entry_remove_probe(entry, NULL, probe_private); | 755 | old = marker_entry_remove_probe(entry, NULL, probe_private); |
793 | mutex_unlock(&markers_mutex); | 756 | mutex_unlock(&markers_mutex); |
794 | marker_update_probes(); /* may update entry */ | 757 | marker_update_probes(); /* may update entry */ |
758 | synchronize_sched(); | ||
759 | kfree(old); | ||
795 | mutex_lock(&markers_mutex); | 760 | mutex_lock(&markers_mutex); |
796 | entry = get_marker_from_private_data(probe, probe_private); | 761 | entry = get_marker_from_private_data(probe, probe_private); |
797 | WARN_ON(!entry); | 762 | WARN_ON(!entry); |
798 | entry->oldptr = old; | ||
799 | entry->rcu_pending = 1; | ||
800 | /* write rcu_pending before calling the RCU callback */ | ||
801 | smp_wmb(); | ||
802 | call_rcu_sched(&entry->rcu, free_old_closure); | ||
803 | remove_marker(entry->name); /* Ignore busy error message */ | 763 | remove_marker(entry->name); /* Ignore busy error message */ |
804 | end: | 764 | end: |
805 | mutex_unlock(&markers_mutex); | 765 | mutex_unlock(&markers_mutex); |