diff options
Diffstat (limited to 'kernel/trace/trace_uprobe.c')
-rw-r--r-- | kernel/trace/trace_uprobe.c | 46 |
1 files changed, 27 insertions, 19 deletions
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 04fdb5de823c..3c9b97e6b1f4 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c | |||
@@ -893,6 +893,9 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, | |||
893 | int ret; | 893 | int ret; |
894 | 894 | ||
895 | if (file) { | 895 | if (file) { |
896 | if (tu->tp.flags & TP_FLAG_PROFILE) | ||
897 | return -EINTR; | ||
898 | |||
896 | link = kmalloc(sizeof(*link), GFP_KERNEL); | 899 | link = kmalloc(sizeof(*link), GFP_KERNEL); |
897 | if (!link) | 900 | if (!link) |
898 | return -ENOMEM; | 901 | return -ENOMEM; |
@@ -901,29 +904,40 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, | |||
901 | list_add_tail_rcu(&link->list, &tu->tp.files); | 904 | list_add_tail_rcu(&link->list, &tu->tp.files); |
902 | 905 | ||
903 | tu->tp.flags |= TP_FLAG_TRACE; | 906 | tu->tp.flags |= TP_FLAG_TRACE; |
904 | } else | 907 | } else { |
905 | tu->tp.flags |= TP_FLAG_PROFILE; | 908 | if (tu->tp.flags & TP_FLAG_TRACE) |
909 | return -EINTR; | ||
906 | 910 | ||
907 | ret = uprobe_buffer_enable(); | 911 | tu->tp.flags |= TP_FLAG_PROFILE; |
908 | if (ret < 0) | 912 | } |
909 | return ret; | ||
910 | 913 | ||
911 | WARN_ON(!uprobe_filter_is_empty(&tu->filter)); | 914 | WARN_ON(!uprobe_filter_is_empty(&tu->filter)); |
912 | 915 | ||
913 | if (enabled) | 916 | if (enabled) |
914 | return 0; | 917 | return 0; |
915 | 918 | ||
919 | ret = uprobe_buffer_enable(); | ||
920 | if (ret) | ||
921 | goto err_flags; | ||
922 | |||
916 | tu->consumer.filter = filter; | 923 | tu->consumer.filter = filter; |
917 | ret = uprobe_register(tu->inode, tu->offset, &tu->consumer); | 924 | ret = uprobe_register(tu->inode, tu->offset, &tu->consumer); |
918 | if (ret) { | 925 | if (ret) |
919 | if (file) { | 926 | goto err_buffer; |
920 | list_del(&link->list); | ||
921 | kfree(link); | ||
922 | tu->tp.flags &= ~TP_FLAG_TRACE; | ||
923 | } else | ||
924 | tu->tp.flags &= ~TP_FLAG_PROFILE; | ||
925 | } | ||
926 | 927 | ||
928 | return 0; | ||
929 | |||
930 | err_buffer: | ||
931 | uprobe_buffer_disable(); | ||
932 | |||
933 | err_flags: | ||
934 | if (file) { | ||
935 | list_del(&link->list); | ||
936 | kfree(link); | ||
937 | tu->tp.flags &= ~TP_FLAG_TRACE; | ||
938 | } else { | ||
939 | tu->tp.flags &= ~TP_FLAG_PROFILE; | ||
940 | } | ||
927 | return ret; | 941 | return ret; |
928 | } | 942 | } |
929 | 943 | ||
@@ -1201,12 +1215,6 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs) | |||
1201 | 1215 | ||
1202 | current->utask->vaddr = (unsigned long) &udd; | 1216 | current->utask->vaddr = (unsigned long) &udd; |
1203 | 1217 | ||
1204 | #ifdef CONFIG_PERF_EVENTS | ||
1205 | if ((tu->tp.flags & TP_FLAG_TRACE) == 0 && | ||
1206 | !uprobe_perf_filter(&tu->consumer, 0, current->mm)) | ||
1207 | return UPROBE_HANDLER_REMOVE; | ||
1208 | #endif | ||
1209 | |||
1210 | if (WARN_ON_ONCE(!uprobe_cpu_buffer)) | 1218 | if (WARN_ON_ONCE(!uprobe_cpu_buffer)) |
1211 | return 0; | 1219 | return 0; |
1212 | 1220 | ||