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); | 
