diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-15 07:46:29 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-15 07:46:29 -0400 |
commit | b2aaf8f74cdc84a9182f6cabf198b7763bcb9d40 (patch) | |
tree | 53ccb1c2c14751fe69cf93102e76e97021f6df07 /kernel/marker.c | |
parent | 4f962d4d65923d7b722192e729840cfb79af0a5a (diff) | |
parent | 278429cff8809958d25415ba0ed32b59866ab1a8 (diff) |
Merge branch 'linus' into stackprotector
Conflicts:
arch/x86/kernel/Makefile
include/asm-x86/pda.h
Diffstat (limited to 'kernel/marker.c')
-rw-r--r-- | kernel/marker.c | 67 |
1 files changed, 32 insertions, 35 deletions
diff --git a/kernel/marker.c b/kernel/marker.c index b5a9fe1d50d5..7d1faecd7a51 100644 --- a/kernel/marker.c +++ b/kernel/marker.c | |||
@@ -55,8 +55,8 @@ static DEFINE_MUTEX(markers_mutex); | |||
55 | struct marker_entry { | 55 | struct marker_entry { |
56 | struct hlist_node hlist; | 56 | struct hlist_node hlist; |
57 | char *format; | 57 | char *format; |
58 | void (*call)(const struct marker *mdata, /* Probe wrapper */ | 58 | /* Probe wrapper */ |
59 | void *call_private, const char *fmt, ...); | 59 | void (*call)(const struct marker *mdata, void *call_private, ...); |
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. */ |
@@ -91,15 +91,13 @@ EXPORT_SYMBOL_GPL(__mark_empty_function); | |||
91 | * marker_probe_cb Callback that prepares the variable argument list for probes. | 91 | * marker_probe_cb Callback that prepares the variable argument list for probes. |
92 | * @mdata: pointer of type struct marker | 92 | * @mdata: pointer of type struct marker |
93 | * @call_private: caller site private data | 93 | * @call_private: caller site private data |
94 | * @fmt: format string | ||
95 | * @...: Variable argument list. | 94 | * @...: Variable argument list. |
96 | * | 95 | * |
97 | * Since we do not use "typical" pointer based RCU in the 1 argument case, we | 96 | * Since we do not use "typical" pointer based RCU in the 1 argument case, we |
98 | * need to put a full smp_rmb() in this branch. This is why we do not use | 97 | * need to put a full smp_rmb() in this branch. This is why we do not use |
99 | * rcu_dereference() for the pointer read. | 98 | * rcu_dereference() for the pointer read. |
100 | */ | 99 | */ |
101 | void marker_probe_cb(const struct marker *mdata, void *call_private, | 100 | void marker_probe_cb(const struct marker *mdata, void *call_private, ...) |
102 | const char *fmt, ...) | ||
103 | { | 101 | { |
104 | va_list args; | 102 | va_list args; |
105 | char ptype; | 103 | char ptype; |
@@ -120,13 +118,19 @@ void marker_probe_cb(const struct marker *mdata, void *call_private, | |||
120 | /* Must read the ptr before private data. They are not data | 118 | /* Must read the ptr before private data. They are not data |
121 | * dependant, so we put an explicit smp_rmb() here. */ | 119 | * dependant, so we put an explicit smp_rmb() here. */ |
122 | smp_rmb(); | 120 | smp_rmb(); |
123 | va_start(args, fmt); | 121 | va_start(args, call_private); |
124 | func(mdata->single.probe_private, call_private, fmt, &args); | 122 | func(mdata->single.probe_private, call_private, mdata->format, |
123 | &args); | ||
125 | va_end(args); | 124 | va_end(args); |
126 | } else { | 125 | } else { |
127 | struct marker_probe_closure *multi; | 126 | struct marker_probe_closure *multi; |
128 | int i; | 127 | int i; |
129 | /* | 128 | /* |
129 | * Read mdata->ptype before mdata->multi. | ||
130 | */ | ||
131 | smp_rmb(); | ||
132 | multi = mdata->multi; | ||
133 | /* | ||
130 | * multi points to an array, therefore accessing the array | 134 | * multi points to an array, therefore accessing the array |
131 | * depends on reading multi. However, even in this case, | 135 | * depends on reading multi. However, even in this case, |
132 | * we must insure that the pointer is read _before_ the array | 136 | * we must insure that the pointer is read _before_ the array |
@@ -134,11 +138,10 @@ void marker_probe_cb(const struct marker *mdata, void *call_private, | |||
134 | * in the fast path, so put the explicit barrier here. | 138 | * in the fast path, so put the explicit barrier here. |
135 | */ | 139 | */ |
136 | smp_read_barrier_depends(); | 140 | smp_read_barrier_depends(); |
137 | multi = mdata->multi; | ||
138 | for (i = 0; multi[i].func; i++) { | 141 | for (i = 0; multi[i].func; i++) { |
139 | va_start(args, fmt); | 142 | va_start(args, call_private); |
140 | multi[i].func(multi[i].probe_private, call_private, fmt, | 143 | multi[i].func(multi[i].probe_private, call_private, |
141 | &args); | 144 | mdata->format, &args); |
142 | va_end(args); | 145 | va_end(args); |
143 | } | 146 | } |
144 | } | 147 | } |
@@ -150,13 +153,11 @@ EXPORT_SYMBOL_GPL(marker_probe_cb); | |||
150 | * marker_probe_cb Callback that does not prepare the variable argument list. | 153 | * marker_probe_cb Callback that does not prepare the variable argument list. |
151 | * @mdata: pointer of type struct marker | 154 | * @mdata: pointer of type struct marker |
152 | * @call_private: caller site private data | 155 | * @call_private: caller site private data |
153 | * @fmt: format string | ||
154 | * @...: Variable argument list. | 156 | * @...: Variable argument list. |
155 | * | 157 | * |
156 | * Should be connected to markers "MARK_NOARGS". | 158 | * Should be connected to markers "MARK_NOARGS". |
157 | */ | 159 | */ |
158 | void marker_probe_cb_noarg(const struct marker *mdata, | 160 | void marker_probe_cb_noarg(const struct marker *mdata, void *call_private, ...) |
159 | void *call_private, const char *fmt, ...) | ||
160 | { | 161 | { |
161 | va_list args; /* not initialized */ | 162 | va_list args; /* not initialized */ |
162 | char ptype; | 163 | char ptype; |
@@ -172,11 +173,17 @@ void marker_probe_cb_noarg(const struct marker *mdata, | |||
172 | /* Must read the ptr before private data. They are not data | 173 | /* Must read the ptr before private data. They are not data |
173 | * dependant, so we put an explicit smp_rmb() here. */ | 174 | * dependant, so we put an explicit smp_rmb() here. */ |
174 | smp_rmb(); | 175 | smp_rmb(); |
175 | func(mdata->single.probe_private, call_private, fmt, &args); | 176 | func(mdata->single.probe_private, call_private, mdata->format, |
177 | &args); | ||
176 | } else { | 178 | } else { |
177 | struct marker_probe_closure *multi; | 179 | struct marker_probe_closure *multi; |
178 | int i; | 180 | int i; |
179 | /* | 181 | /* |
182 | * Read mdata->ptype before mdata->multi. | ||
183 | */ | ||
184 | smp_rmb(); | ||
185 | multi = mdata->multi; | ||
186 | /* | ||
180 | * multi points to an array, therefore accessing the array | 187 | * multi points to an array, therefore accessing the array |
181 | * depends on reading multi. However, even in this case, | 188 | * depends on reading multi. However, even in this case, |
182 | * we must insure that the pointer is read _before_ the array | 189 | * we must insure that the pointer is read _before_ the array |
@@ -184,10 +191,9 @@ void marker_probe_cb_noarg(const struct marker *mdata, | |||
184 | * in the fast path, so put the explicit barrier here. | 191 | * in the fast path, so put the explicit barrier here. |
185 | */ | 192 | */ |
186 | smp_read_barrier_depends(); | 193 | smp_read_barrier_depends(); |
187 | multi = mdata->multi; | ||
188 | for (i = 0; multi[i].func; i++) | 194 | for (i = 0; multi[i].func; i++) |
189 | multi[i].func(multi[i].probe_private, call_private, fmt, | 195 | multi[i].func(multi[i].probe_private, call_private, |
190 | &args); | 196 | mdata->format, &args); |
191 | } | 197 | } |
192 | preempt_enable(); | 198 | preempt_enable(); |
193 | } | 199 | } |
@@ -443,7 +449,7 @@ static int remove_marker(const char *name) | |||
443 | hlist_del(&e->hlist); | 449 | hlist_del(&e->hlist); |
444 | /* Make sure the call_rcu has been executed */ | 450 | /* Make sure the call_rcu has been executed */ |
445 | if (e->rcu_pending) | 451 | if (e->rcu_pending) |
446 | rcu_barrier(); | 452 | rcu_barrier_sched(); |
447 | kfree(e); | 453 | kfree(e); |
448 | return 0; | 454 | return 0; |
449 | } | 455 | } |
@@ -478,7 +484,7 @@ static int marker_set_format(struct marker_entry **entry, const char *format) | |||
478 | hlist_del(&(*entry)->hlist); | 484 | hlist_del(&(*entry)->hlist); |
479 | /* Make sure the call_rcu has been executed */ | 485 | /* Make sure the call_rcu has been executed */ |
480 | if ((*entry)->rcu_pending) | 486 | if ((*entry)->rcu_pending) |
481 | rcu_barrier(); | 487 | rcu_barrier_sched(); |
482 | kfree(*entry); | 488 | kfree(*entry); |
483 | *entry = e; | 489 | *entry = e; |
484 | trace_mark(core_marker_format, "name %s format %s", | 490 | trace_mark(core_marker_format, "name %s format %s", |
@@ -657,7 +663,7 @@ int marker_probe_register(const char *name, const char *format, | |||
657 | * make sure it's executed now. | 663 | * make sure it's executed now. |
658 | */ | 664 | */ |
659 | if (entry->rcu_pending) | 665 | if (entry->rcu_pending) |
660 | rcu_barrier(); | 666 | rcu_barrier_sched(); |
661 | old = marker_entry_add_probe(entry, probe, probe_private); | 667 | old = marker_entry_add_probe(entry, probe, probe_private); |
662 | if (IS_ERR(old)) { | 668 | if (IS_ERR(old)) { |
663 | ret = PTR_ERR(old); | 669 | ret = PTR_ERR(old); |
@@ -672,10 +678,7 @@ int marker_probe_register(const char *name, const char *format, | |||
672 | entry->rcu_pending = 1; | 678 | entry->rcu_pending = 1; |
673 | /* write rcu_pending before calling the RCU callback */ | 679 | /* write rcu_pending before calling the RCU callback */ |
674 | smp_wmb(); | 680 | smp_wmb(); |
675 | #ifdef CONFIG_PREEMPT_RCU | 681 | call_rcu_sched(&entry->rcu, free_old_closure); |
676 | synchronize_sched(); /* Until we have the call_rcu_sched() */ | ||
677 | #endif | ||
678 | call_rcu(&entry->rcu, free_old_closure); | ||
679 | end: | 682 | end: |
680 | mutex_unlock(&markers_mutex); | 683 | mutex_unlock(&markers_mutex); |
681 | return ret; | 684 | return ret; |
@@ -706,7 +709,7 @@ int marker_probe_unregister(const char *name, | |||
706 | if (!entry) | 709 | if (!entry) |
707 | goto end; | 710 | goto end; |
708 | if (entry->rcu_pending) | 711 | if (entry->rcu_pending) |
709 | rcu_barrier(); | 712 | rcu_barrier_sched(); |
710 | old = marker_entry_remove_probe(entry, probe, probe_private); | 713 | old = marker_entry_remove_probe(entry, probe, probe_private); |
711 | mutex_unlock(&markers_mutex); | 714 | mutex_unlock(&markers_mutex); |
712 | marker_update_probes(); /* may update entry */ | 715 | marker_update_probes(); /* may update entry */ |
@@ -718,10 +721,7 @@ int marker_probe_unregister(const char *name, | |||
718 | entry->rcu_pending = 1; | 721 | entry->rcu_pending = 1; |
719 | /* write rcu_pending before calling the RCU callback */ | 722 | /* write rcu_pending before calling the RCU callback */ |
720 | smp_wmb(); | 723 | smp_wmb(); |
721 | #ifdef CONFIG_PREEMPT_RCU | 724 | call_rcu_sched(&entry->rcu, free_old_closure); |
722 | synchronize_sched(); /* Until we have the call_rcu_sched() */ | ||
723 | #endif | ||
724 | call_rcu(&entry->rcu, free_old_closure); | ||
725 | remove_marker(name); /* Ignore busy error message */ | 725 | remove_marker(name); /* Ignore busy error message */ |
726 | ret = 0; | 726 | ret = 0; |
727 | end: | 727 | end: |
@@ -788,7 +788,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, | |||
788 | goto end; | 788 | goto end; |
789 | } | 789 | } |
790 | if (entry->rcu_pending) | 790 | if (entry->rcu_pending) |
791 | rcu_barrier(); | 791 | rcu_barrier_sched(); |
792 | old = marker_entry_remove_probe(entry, NULL, probe_private); | 792 | old = marker_entry_remove_probe(entry, NULL, probe_private); |
793 | mutex_unlock(&markers_mutex); | 793 | mutex_unlock(&markers_mutex); |
794 | marker_update_probes(); /* may update entry */ | 794 | marker_update_probes(); /* may update entry */ |
@@ -799,10 +799,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, | |||
799 | entry->rcu_pending = 1; | 799 | entry->rcu_pending = 1; |
800 | /* write rcu_pending before calling the RCU callback */ | 800 | /* write rcu_pending before calling the RCU callback */ |
801 | smp_wmb(); | 801 | smp_wmb(); |
802 | #ifdef CONFIG_PREEMPT_RCU | 802 | call_rcu_sched(&entry->rcu, free_old_closure); |
803 | synchronize_sched(); /* Until we have the call_rcu_sched() */ | ||
804 | #endif | ||
805 | call_rcu(&entry->rcu, free_old_closure); | ||
806 | remove_marker(entry->name); /* Ignore busy error message */ | 803 | remove_marker(entry->name); /* Ignore busy error message */ |
807 | end: | 804 | end: |
808 | mutex_unlock(&markers_mutex); | 805 | mutex_unlock(&markers_mutex); |