aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_counter.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-12-11 05:26:29 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-11 09:45:50 -0500
commitccff286d85098ba5438e22aa2ea807fc1e18cf2f (patch)
tree0e8ab0180e38ddc530cc3f3d55152a34160605cc /kernel/perf_counter.c
parent04289bb9891882202d7e961c4c04d2376930e9f9 (diff)
perf counters: group counter, fixes
Impact: bugfix Check that a group does not span outside the context of a CPU or a task. Also, do not allow deep recursive hierarchies. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_counter.c')
-rw-r--r--kernel/perf_counter.c39
1 files changed, 20 insertions, 19 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index fa59fe8c02d5..278209c547a8 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -107,9 +107,6 @@ list_del_counter(struct perf_counter *counter, struct perf_counter_context *ctx)
107 107
108 list_del_init(&counter->list_entry); 108 list_del_init(&counter->list_entry);
109 109
110 if (list_empty(&counter->sibling_list))
111 return;
112
113 /* 110 /*
114 * If this was a group counter with sibling counters then 111 * If this was a group counter with sibling counters then
115 * upgrade the siblings to singleton counters by adding them 112 * upgrade the siblings to singleton counters by adding them
@@ -395,9 +392,6 @@ counter_sched_in(struct perf_counter *counter,
395 struct perf_counter_context *ctx, 392 struct perf_counter_context *ctx,
396 int cpu) 393 int cpu)
397{ 394{
398 if (!counter->active)
399 return;
400
401 hw_perf_counter_enable(counter); 395 hw_perf_counter_enable(counter);
402 counter->active = 1; 396 counter->active = 1;
403 counter->oncpu = cpu; /* TODO: put 'cpu' into cpuctx->cpu */ 397 counter->oncpu = cpu; /* TODO: put 'cpu' into cpuctx->cpu */
@@ -876,32 +870,39 @@ asmlinkage int sys_perf_counter_open(
876 return -EFAULT; 870 return -EFAULT;
877 871
878 /* 872 /*
879 * Look up the group leader: 873 * Get the target context (task or percpu):
874 */
875 ctx = find_get_context(pid, cpu);
876 if (IS_ERR(ctx))
877 return PTR_ERR(ctx);
878
879 /*
880 * Look up the group leader (we will attach this counter to it):
880 */ 881 */
881 group_leader = NULL; 882 group_leader = NULL;
882 if (group_fd != -1) { 883 if (group_fd != -1) {
883 ret = -EINVAL; 884 ret = -EINVAL;
884 group_file = fget_light(group_fd, &fput_needed); 885 group_file = fget_light(group_fd, &fput_needed);
885 if (!group_file) 886 if (!group_file)
886 goto out_fput; 887 goto err_put_context;
887 if (group_file->f_op != &perf_fops) 888 if (group_file->f_op != &perf_fops)
888 goto out_fput; 889 goto err_put_context;
889 890
890 group_leader = group_file->private_data; 891 group_leader = group_file->private_data;
891 /* 892 /*
892 * Do not allow a recursive hierarchy: 893 * Do not allow a recursive hierarchy (this new sibling
894 * becoming part of another group-sibling):
895 */
896 if (group_leader->group_leader != group_leader)
897 goto err_put_context;
898 /*
899 * Do not allow to attach to a group in a different
900 * task or CPU context:
893 */ 901 */
894 if (group_leader->group_leader) 902 if (group_leader->ctx != ctx)
895 goto out_fput; 903 goto err_put_context;
896 } 904 }
897 905
898 /*
899 * Get the target context (task or percpu):
900 */
901 ctx = find_get_context(pid, cpu);
902 if (IS_ERR(ctx))
903 return PTR_ERR(ctx);
904
905 ret = -ENOMEM; 906 ret = -ENOMEM;
906 counter = perf_counter_alloc(&hw_event, cpu, group_leader); 907 counter = perf_counter_alloc(&hw_event, cpu, group_leader);
907 if (!counter) 908 if (!counter)