diff options
Diffstat (limited to 'kernel/marker.c')
-rw-r--r-- | kernel/marker.c | 37 |
1 files changed, 18 insertions, 19 deletions
diff --git a/kernel/marker.c b/kernel/marker.c index 1abfb923b761..7d1faecd7a51 100644 --- a/kernel/marker.c +++ b/kernel/marker.c | |||
@@ -126,6 +126,11 @@ void marker_probe_cb(const struct marker *mdata, void *call_private, ...) | |||
126 | struct marker_probe_closure *multi; | 126 | struct marker_probe_closure *multi; |
127 | int i; | 127 | int i; |
128 | /* | 128 | /* |
129 | * Read mdata->ptype before mdata->multi. | ||
130 | */ | ||
131 | smp_rmb(); | ||
132 | multi = mdata->multi; | ||
133 | /* | ||
129 | * multi points to an array, therefore accessing the array | 134 | * multi points to an array, therefore accessing the array |
130 | * depends on reading multi. However, even in this case, | 135 | * depends on reading multi. However, even in this case, |
131 | * we must insure that the pointer is read _before_ the array | 136 | * we must insure that the pointer is read _before_ the array |
@@ -133,7 +138,6 @@ void marker_probe_cb(const struct marker *mdata, void *call_private, ...) | |||
133 | * in the fast path, so put the explicit barrier here. | 138 | * in the fast path, so put the explicit barrier here. |
134 | */ | 139 | */ |
135 | smp_read_barrier_depends(); | 140 | smp_read_barrier_depends(); |
136 | multi = mdata->multi; | ||
137 | for (i = 0; multi[i].func; i++) { | 141 | for (i = 0; multi[i].func; i++) { |
138 | va_start(args, call_private); | 142 | va_start(args, call_private); |
139 | multi[i].func(multi[i].probe_private, call_private, | 143 | multi[i].func(multi[i].probe_private, call_private, |
@@ -175,6 +179,11 @@ void marker_probe_cb_noarg(const struct marker *mdata, void *call_private, ...) | |||
175 | struct marker_probe_closure *multi; | 179 | struct marker_probe_closure *multi; |
176 | int i; | 180 | int i; |
177 | /* | 181 | /* |
182 | * Read mdata->ptype before mdata->multi. | ||
183 | */ | ||
184 | smp_rmb(); | ||
185 | multi = mdata->multi; | ||
186 | /* | ||
178 | * multi points to an array, therefore accessing the array | 187 | * multi points to an array, therefore accessing the array |
179 | * depends on reading multi. However, even in this case, | 188 | * depends on reading multi. However, even in this case, |
180 | * we must insure that the pointer is read _before_ the array | 189 | * we must insure that the pointer is read _before_ the array |
@@ -182,7 +191,6 @@ void marker_probe_cb_noarg(const struct marker *mdata, void *call_private, ...) | |||
182 | * in the fast path, so put the explicit barrier here. | 191 | * in the fast path, so put the explicit barrier here. |
183 | */ | 192 | */ |
184 | smp_read_barrier_depends(); | 193 | smp_read_barrier_depends(); |
185 | multi = mdata->multi; | ||
186 | for (i = 0; multi[i].func; i++) | 194 | for (i = 0; multi[i].func; i++) |
187 | multi[i].func(multi[i].probe_private, call_private, | 195 | multi[i].func(multi[i].probe_private, call_private, |
188 | mdata->format, &args); | 196 | mdata->format, &args); |
@@ -441,7 +449,7 @@ static int remove_marker(const char *name) | |||
441 | hlist_del(&e->hlist); | 449 | hlist_del(&e->hlist); |
442 | /* Make sure the call_rcu has been executed */ | 450 | /* Make sure the call_rcu has been executed */ |
443 | if (e->rcu_pending) | 451 | if (e->rcu_pending) |
444 | rcu_barrier(); | 452 | rcu_barrier_sched(); |
445 | kfree(e); | 453 | kfree(e); |
446 | return 0; | 454 | return 0; |
447 | } | 455 | } |
@@ -476,7 +484,7 @@ static int marker_set_format(struct marker_entry **entry, const char *format) | |||
476 | hlist_del(&(*entry)->hlist); | 484 | hlist_del(&(*entry)->hlist); |
477 | /* Make sure the call_rcu has been executed */ | 485 | /* Make sure the call_rcu has been executed */ |
478 | if ((*entry)->rcu_pending) | 486 | if ((*entry)->rcu_pending) |
479 | rcu_barrier(); | 487 | rcu_barrier_sched(); |
480 | kfree(*entry); | 488 | kfree(*entry); |
481 | *entry = e; | 489 | *entry = e; |
482 | trace_mark(core_marker_format, "name %s format %s", | 490 | trace_mark(core_marker_format, "name %s format %s", |
@@ -655,7 +663,7 @@ int marker_probe_register(const char *name, const char *format, | |||
655 | * make sure it's executed now. | 663 | * make sure it's executed now. |
656 | */ | 664 | */ |
657 | if (entry->rcu_pending) | 665 | if (entry->rcu_pending) |
658 | rcu_barrier(); | 666 | rcu_barrier_sched(); |
659 | old = marker_entry_add_probe(entry, probe, probe_private); | 667 | old = marker_entry_add_probe(entry, probe, probe_private); |
660 | if (IS_ERR(old)) { | 668 | if (IS_ERR(old)) { |
661 | ret = PTR_ERR(old); | 669 | ret = PTR_ERR(old); |
@@ -670,10 +678,7 @@ int marker_probe_register(const char *name, const char *format, | |||
670 | entry->rcu_pending = 1; | 678 | entry->rcu_pending = 1; |
671 | /* write rcu_pending before calling the RCU callback */ | 679 | /* write rcu_pending before calling the RCU callback */ |
672 | smp_wmb(); | 680 | smp_wmb(); |
673 | #ifdef CONFIG_PREEMPT_RCU | 681 | call_rcu_sched(&entry->rcu, free_old_closure); |
674 | synchronize_sched(); /* Until we have the call_rcu_sched() */ | ||
675 | #endif | ||
676 | call_rcu(&entry->rcu, free_old_closure); | ||
677 | end: | 682 | end: |
678 | mutex_unlock(&markers_mutex); | 683 | mutex_unlock(&markers_mutex); |
679 | return ret; | 684 | return ret; |
@@ -704,7 +709,7 @@ int marker_probe_unregister(const char *name, | |||
704 | if (!entry) | 709 | if (!entry) |
705 | goto end; | 710 | goto end; |
706 | if (entry->rcu_pending) | 711 | if (entry->rcu_pending) |
707 | rcu_barrier(); | 712 | rcu_barrier_sched(); |
708 | old = marker_entry_remove_probe(entry, probe, probe_private); | 713 | old = marker_entry_remove_probe(entry, probe, probe_private); |
709 | mutex_unlock(&markers_mutex); | 714 | mutex_unlock(&markers_mutex); |
710 | marker_update_probes(); /* may update entry */ | 715 | marker_update_probes(); /* may update entry */ |
@@ -716,10 +721,7 @@ int marker_probe_unregister(const char *name, | |||
716 | entry->rcu_pending = 1; | 721 | entry->rcu_pending = 1; |
717 | /* write rcu_pending before calling the RCU callback */ | 722 | /* write rcu_pending before calling the RCU callback */ |
718 | smp_wmb(); | 723 | smp_wmb(); |
719 | #ifdef CONFIG_PREEMPT_RCU | 724 | call_rcu_sched(&entry->rcu, free_old_closure); |
720 | synchronize_sched(); /* Until we have the call_rcu_sched() */ | ||
721 | #endif | ||
722 | call_rcu(&entry->rcu, free_old_closure); | ||
723 | remove_marker(name); /* Ignore busy error message */ | 725 | remove_marker(name); /* Ignore busy error message */ |
724 | ret = 0; | 726 | ret = 0; |
725 | end: | 727 | end: |
@@ -786,7 +788,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, | |||
786 | goto end; | 788 | goto end; |
787 | } | 789 | } |
788 | if (entry->rcu_pending) | 790 | if (entry->rcu_pending) |
789 | rcu_barrier(); | 791 | rcu_barrier_sched(); |
790 | old = marker_entry_remove_probe(entry, NULL, probe_private); | 792 | old = marker_entry_remove_probe(entry, NULL, probe_private); |
791 | mutex_unlock(&markers_mutex); | 793 | mutex_unlock(&markers_mutex); |
792 | marker_update_probes(); /* may update entry */ | 794 | marker_update_probes(); /* may update entry */ |
@@ -797,10 +799,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, | |||
797 | entry->rcu_pending = 1; | 799 | entry->rcu_pending = 1; |
798 | /* write rcu_pending before calling the RCU callback */ | 800 | /* write rcu_pending before calling the RCU callback */ |
799 | smp_wmb(); | 801 | smp_wmb(); |
800 | #ifdef CONFIG_PREEMPT_RCU | 802 | call_rcu_sched(&entry->rcu, free_old_closure); |
801 | synchronize_sched(); /* Until we have the call_rcu_sched() */ | ||
802 | #endif | ||
803 | call_rcu(&entry->rcu, free_old_closure); | ||
804 | remove_marker(entry->name); /* Ignore busy error message */ | 803 | remove_marker(entry->name); /* Ignore busy error message */ |
805 | end: | 804 | end: |
806 | mutex_unlock(&markers_mutex); | 805 | mutex_unlock(&markers_mutex); |