diff options
Diffstat (limited to 'kernel/marker.c')
| -rw-r--r-- | kernel/marker.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/kernel/marker.c b/kernel/marker.c index 7d1faecd7a5..e9c6b2bc940 100644 --- a/kernel/marker.c +++ b/kernel/marker.c | |||
| @@ -62,7 +62,7 @@ struct marker_entry { | |||
| 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; | 63 | struct rcu_head rcu; |
| 64 | void *oldptr; | 64 | void *oldptr; |
| 65 | unsigned char rcu_pending:1; | 65 | int rcu_pending; |
| 66 | unsigned char ptype:1; | 66 | unsigned char ptype:1; |
| 67 | char name[0]; /* Contains name'\0'format'\0' */ | 67 | char name[0]; /* Contains name'\0'format'\0' */ |
| 68 | }; | 68 | }; |
| @@ -103,11 +103,11 @@ void marker_probe_cb(const struct marker *mdata, void *call_private, ...) | |||
| 103 | char ptype; | 103 | char ptype; |
| 104 | 104 | ||
| 105 | /* | 105 | /* |
| 106 | * preempt_disable does two things : disabling preemption to make sure | 106 | * rcu_read_lock_sched does two things : disabling preemption to make |
| 107 | * the teardown of the callbacks can be done correctly when they are in | 107 | * sure the teardown of the callbacks can be done correctly when they |
| 108 | * modules and they insure RCU read coherency. | 108 | * are in modules and they insure RCU read coherency. |
| 109 | */ | 109 | */ |
| 110 | preempt_disable(); | 110 | rcu_read_lock_sched(); |
| 111 | ptype = mdata->ptype; | 111 | ptype = mdata->ptype; |
| 112 | if (likely(!ptype)) { | 112 | if (likely(!ptype)) { |
| 113 | marker_probe_func *func; | 113 | marker_probe_func *func; |
| @@ -145,7 +145,7 @@ void marker_probe_cb(const struct marker *mdata, void *call_private, ...) | |||
| 145 | va_end(args); | 145 | va_end(args); |
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | preempt_enable(); | 148 | rcu_read_unlock_sched(); |
| 149 | } | 149 | } |
| 150 | EXPORT_SYMBOL_GPL(marker_probe_cb); | 150 | EXPORT_SYMBOL_GPL(marker_probe_cb); |
| 151 | 151 | ||
| @@ -162,7 +162,7 @@ void marker_probe_cb_noarg(const struct marker *mdata, void *call_private, ...) | |||
| 162 | va_list args; /* not initialized */ | 162 | va_list args; /* not initialized */ |
| 163 | char ptype; | 163 | char ptype; |
| 164 | 164 | ||
| 165 | preempt_disable(); | 165 | rcu_read_lock_sched(); |
| 166 | ptype = mdata->ptype; | 166 | ptype = mdata->ptype; |
| 167 | if (likely(!ptype)) { | 167 | if (likely(!ptype)) { |
| 168 | marker_probe_func *func; | 168 | marker_probe_func *func; |
| @@ -195,7 +195,7 @@ void marker_probe_cb_noarg(const struct marker *mdata, void *call_private, ...) | |||
| 195 | multi[i].func(multi[i].probe_private, call_private, | 195 | multi[i].func(multi[i].probe_private, call_private, |
| 196 | mdata->format, &args); | 196 | mdata->format, &args); |
| 197 | } | 197 | } |
| 198 | preempt_enable(); | 198 | rcu_read_unlock_sched(); |
| 199 | } | 199 | } |
| 200 | EXPORT_SYMBOL_GPL(marker_probe_cb_noarg); | 200 | EXPORT_SYMBOL_GPL(marker_probe_cb_noarg); |
| 201 | 201 | ||
| @@ -560,7 +560,7 @@ static int set_marker(struct marker_entry **entry, struct marker *elem, | |||
| 560 | * Disable a marker and its probe callback. | 560 | * Disable a marker and its probe callback. |
| 561 | * Note: only waiting an RCU period after setting elem->call to the empty | 561 | * Note: only waiting an RCU period after setting elem->call to the empty |
| 562 | * function insures that the original callback is not used anymore. This insured | 562 | * function insures that the original callback is not used anymore. This insured |
| 563 | * by preempt_disable around the call site. | 563 | * by rcu_read_lock_sched around the call site. |
| 564 | */ | 564 | */ |
| 565 | static void disable_marker(struct marker *elem) | 565 | static void disable_marker(struct marker *elem) |
| 566 | { | 566 | { |
| @@ -653,11 +653,17 @@ int marker_probe_register(const char *name, const char *format, | |||
| 653 | entry = get_marker(name); | 653 | entry = get_marker(name); |
| 654 | if (!entry) { | 654 | if (!entry) { |
| 655 | entry = add_marker(name, format); | 655 | entry = add_marker(name, format); |
| 656 | if (IS_ERR(entry)) { | 656 | if (IS_ERR(entry)) |
| 657 | ret = PTR_ERR(entry); | 657 | ret = PTR_ERR(entry); |
| 658 | goto end; | 658 | } else if (format) { |
| 659 | } | 659 | if (!entry->format) |
| 660 | ret = marker_set_format(&entry, format); | ||
| 661 | else if (strcmp(entry->format, format)) | ||
| 662 | ret = -EPERM; | ||
| 660 | } | 663 | } |
| 664 | if (ret) | ||
| 665 | goto end; | ||
| 666 | |||
| 661 | /* | 667 | /* |
| 662 | * If we detect that a call_rcu is pending for this marker, | 668 | * If we detect that a call_rcu is pending for this marker, |
| 663 | * make sure it's executed now. | 669 | * make sure it's executed now. |
| @@ -674,6 +680,8 @@ int marker_probe_register(const char *name, const char *format, | |||
| 674 | mutex_lock(&markers_mutex); | 680 | mutex_lock(&markers_mutex); |
| 675 | entry = get_marker(name); | 681 | entry = get_marker(name); |
| 676 | WARN_ON(!entry); | 682 | WARN_ON(!entry); |
| 683 | if (entry->rcu_pending) | ||
| 684 | rcu_barrier_sched(); | ||
| 677 | entry->oldptr = old; | 685 | entry->oldptr = old; |
| 678 | entry->rcu_pending = 1; | 686 | entry->rcu_pending = 1; |
| 679 | /* write rcu_pending before calling the RCU callback */ | 687 | /* write rcu_pending before calling the RCU callback */ |
| @@ -717,6 +725,8 @@ int marker_probe_unregister(const char *name, | |||
| 717 | entry = get_marker(name); | 725 | entry = get_marker(name); |
| 718 | if (!entry) | 726 | if (!entry) |
| 719 | goto end; | 727 | goto end; |
| 728 | if (entry->rcu_pending) | ||
| 729 | rcu_barrier_sched(); | ||
| 720 | entry->oldptr = old; | 730 | entry->oldptr = old; |
| 721 | entry->rcu_pending = 1; | 731 | entry->rcu_pending = 1; |
| 722 | /* write rcu_pending before calling the RCU callback */ | 732 | /* write rcu_pending before calling the RCU callback */ |
| @@ -795,6 +805,8 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, | |||
| 795 | mutex_lock(&markers_mutex); | 805 | mutex_lock(&markers_mutex); |
| 796 | entry = get_marker_from_private_data(probe, probe_private); | 806 | entry = get_marker_from_private_data(probe, probe_private); |
| 797 | WARN_ON(!entry); | 807 | WARN_ON(!entry); |
| 808 | if (entry->rcu_pending) | ||
| 809 | rcu_barrier_sched(); | ||
| 798 | entry->oldptr = old; | 810 | entry->oldptr = old; |
| 799 | entry->rcu_pending = 1; | 811 | entry->rcu_pending = 1; |
| 800 | /* write rcu_pending before calling the RCU callback */ | 812 | /* write rcu_pending before calling the RCU callback */ |
