diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2011-11-13 14:55:35 -0500 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2011-11-13 14:55:53 -0500 |
| commit | 2290c0d06d82faee87b1ab2d9d4f7bf81ef64379 (patch) | |
| tree | e075e4d5534193f28e6059904f61e5ca03958d3c /kernel/trace/trace_kprobe.c | |
| parent | 4da669a2e3e5bc70b30a0465f3641528681b5f77 (diff) | |
| parent | 52e4c2a05256cb83cda12f3c2137ab1533344edb (diff) | |
Merge branch 'master' into for-next
Sync with Linus tree to have 157550ff ("mtd: add GPMI-NAND driver
in the config and Makefile") as I have patch depending on that one.
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 58 |
1 files changed, 49 insertions, 9 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 5fb3697bf0e5..00d527c945a4 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -836,11 +836,17 @@ static void __unregister_trace_probe(struct trace_probe *tp) | |||
| 836 | } | 836 | } |
| 837 | 837 | ||
| 838 | /* Unregister a trace_probe and probe_event: call with locking probe_lock */ | 838 | /* Unregister a trace_probe and probe_event: call with locking probe_lock */ |
| 839 | static void unregister_trace_probe(struct trace_probe *tp) | 839 | static int unregister_trace_probe(struct trace_probe *tp) |
| 840 | { | 840 | { |
| 841 | /* Enabled event can not be unregistered */ | ||
| 842 | if (trace_probe_is_enabled(tp)) | ||
| 843 | return -EBUSY; | ||
| 844 | |||
| 841 | __unregister_trace_probe(tp); | 845 | __unregister_trace_probe(tp); |
| 842 | list_del(&tp->list); | 846 | list_del(&tp->list); |
| 843 | unregister_probe_event(tp); | 847 | unregister_probe_event(tp); |
| 848 | |||
| 849 | return 0; | ||
| 844 | } | 850 | } |
| 845 | 851 | ||
| 846 | /* Register a trace_probe and probe_event */ | 852 | /* Register a trace_probe and probe_event */ |
| @@ -854,7 +860,9 @@ static int register_trace_probe(struct trace_probe *tp) | |||
| 854 | /* Delete old (same name) event if exist */ | 860 | /* Delete old (same name) event if exist */ |
| 855 | old_tp = find_trace_probe(tp->call.name, tp->call.class->system); | 861 | old_tp = find_trace_probe(tp->call.name, tp->call.class->system); |
| 856 | if (old_tp) { | 862 | if (old_tp) { |
| 857 | unregister_trace_probe(old_tp); | 863 | ret = unregister_trace_probe(old_tp); |
| 864 | if (ret < 0) | ||
| 865 | goto end; | ||
| 858 | free_trace_probe(old_tp); | 866 | free_trace_probe(old_tp); |
| 859 | } | 867 | } |
| 860 | 868 | ||
| @@ -892,6 +900,7 @@ static int trace_probe_module_callback(struct notifier_block *nb, | |||
| 892 | mutex_lock(&probe_lock); | 900 | mutex_lock(&probe_lock); |
| 893 | list_for_each_entry(tp, &probe_list, list) { | 901 | list_for_each_entry(tp, &probe_list, list) { |
| 894 | if (trace_probe_within_module(tp, mod)) { | 902 | if (trace_probe_within_module(tp, mod)) { |
| 903 | /* Don't need to check busy - this should have gone. */ | ||
| 895 | __unregister_trace_probe(tp); | 904 | __unregister_trace_probe(tp); |
| 896 | ret = __register_trace_probe(tp); | 905 | ret = __register_trace_probe(tp); |
| 897 | if (ret) | 906 | if (ret) |
| @@ -1205,10 +1214,11 @@ static int create_trace_probe(int argc, char **argv) | |||
| 1205 | return -ENOENT; | 1214 | return -ENOENT; |
| 1206 | } | 1215 | } |
| 1207 | /* delete an event */ | 1216 | /* delete an event */ |
| 1208 | unregister_trace_probe(tp); | 1217 | ret = unregister_trace_probe(tp); |
| 1209 | free_trace_probe(tp); | 1218 | if (ret == 0) |
| 1219 | free_trace_probe(tp); | ||
| 1210 | mutex_unlock(&probe_lock); | 1220 | mutex_unlock(&probe_lock); |
| 1211 | return 0; | 1221 | return ret; |
| 1212 | } | 1222 | } |
| 1213 | 1223 | ||
| 1214 | if (argc < 2) { | 1224 | if (argc < 2) { |
| @@ -1317,18 +1327,29 @@ error: | |||
| 1317 | return ret; | 1327 | return ret; |
| 1318 | } | 1328 | } |
| 1319 | 1329 | ||
| 1320 | static void release_all_trace_probes(void) | 1330 | static int release_all_trace_probes(void) |
| 1321 | { | 1331 | { |
| 1322 | struct trace_probe *tp; | 1332 | struct trace_probe *tp; |
| 1333 | int ret = 0; | ||
| 1323 | 1334 | ||
| 1324 | mutex_lock(&probe_lock); | 1335 | mutex_lock(&probe_lock); |
| 1336 | /* Ensure no probe is in use. */ | ||
| 1337 | list_for_each_entry(tp, &probe_list, list) | ||
| 1338 | if (trace_probe_is_enabled(tp)) { | ||
| 1339 | ret = -EBUSY; | ||
| 1340 | goto end; | ||
| 1341 | } | ||
| 1325 | /* TODO: Use batch unregistration */ | 1342 | /* TODO: Use batch unregistration */ |
| 1326 | while (!list_empty(&probe_list)) { | 1343 | while (!list_empty(&probe_list)) { |
| 1327 | tp = list_entry(probe_list.next, struct trace_probe, list); | 1344 | tp = list_entry(probe_list.next, struct trace_probe, list); |
| 1328 | unregister_trace_probe(tp); | 1345 | unregister_trace_probe(tp); |
| 1329 | free_trace_probe(tp); | 1346 | free_trace_probe(tp); |
| 1330 | } | 1347 | } |
| 1348 | |||
| 1349 | end: | ||
| 1331 | mutex_unlock(&probe_lock); | 1350 | mutex_unlock(&probe_lock); |
| 1351 | |||
| 1352 | return ret; | ||
| 1332 | } | 1353 | } |
| 1333 | 1354 | ||
| 1334 | /* Probes listing interfaces */ | 1355 | /* Probes listing interfaces */ |
| @@ -1380,9 +1401,13 @@ static const struct seq_operations probes_seq_op = { | |||
| 1380 | 1401 | ||
| 1381 | static int probes_open(struct inode *inode, struct file *file) | 1402 | static int probes_open(struct inode *inode, struct file *file) |
| 1382 | { | 1403 | { |
| 1383 | if ((file->f_mode & FMODE_WRITE) && | 1404 | int ret; |
| 1384 | (file->f_flags & O_TRUNC)) | 1405 | |
| 1385 | release_all_trace_probes(); | 1406 | if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { |
| 1407 | ret = release_all_trace_probes(); | ||
| 1408 | if (ret < 0) | ||
| 1409 | return ret; | ||
| 1410 | } | ||
| 1386 | 1411 | ||
| 1387 | return seq_open(file, &probes_seq_op); | 1412 | return seq_open(file, &probes_seq_op); |
| 1388 | } | 1413 | } |
| @@ -2055,6 +2080,21 @@ static __init int kprobe_trace_self_tests_init(void) | |||
| 2055 | 2080 | ||
| 2056 | ret = target(1, 2, 3, 4, 5, 6); | 2081 | ret = target(1, 2, 3, 4, 5, 6); |
| 2057 | 2082 | ||
| 2083 | /* Disable trace points before removing it */ | ||
| 2084 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); | ||
| 2085 | if (WARN_ON_ONCE(tp == NULL)) { | ||
| 2086 | pr_warning("error on getting test probe.\n"); | ||
| 2087 | warn++; | ||
| 2088 | } else | ||
| 2089 | disable_trace_probe(tp, TP_FLAG_TRACE); | ||
| 2090 | |||
| 2091 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); | ||
| 2092 | if (WARN_ON_ONCE(tp == NULL)) { | ||
| 2093 | pr_warning("error on getting 2nd test probe.\n"); | ||
| 2094 | warn++; | ||
| 2095 | } else | ||
| 2096 | disable_trace_probe(tp, TP_FLAG_TRACE); | ||
| 2097 | |||
| 2058 | ret = command_trace_probe("-:testprobe"); | 2098 | ret = command_trace_probe("-:testprobe"); |
| 2059 | if (WARN_ON_ONCE(ret)) { | 2099 | if (WARN_ON_ONCE(ret)) { |
| 2060 | pr_warning("error on deleting a probe.\n"); | 2100 | pr_warning("error on deleting a probe.\n"); |
