This patch doesn't apply to the .36 stable tree If someone wants it applied there, please email the backport to [email protected]
thanks, greg k-h > commit: dddd3379a619a4cb8247bfd3c94ca9ae3797aa2e > From: Thomas Gleixner <[email protected]> > Date: Wed, 24 Nov 2010 10:05:55 +0100 > Subject: [PATCH] perf: Fix inherit vs. context rotation bug > > It was found that sometimes children of tasks with inherited events had > one extra event. Eventually it turned out to be due to the list rotation > no being exclusive with the list iteration in the inheritance code. > > Cure this by temporarily disabling the rotation while we inherit the events. > > Signed-off-by: Thomas Gleixner <[email protected]> > Signed-off-by: Peter Zijlstra <[email protected]> > LKML-Reference: <new-submission> > Cc: <[email protected]> > Signed-off-by: Ingo Molnar <[email protected]> > --- > include/linux/perf_event.h | 1 + > kernel/perf_event.c | 22 ++++++++++++++++++++-- > 2 files changed, 21 insertions(+), 2 deletions(-) > > diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h > index 40150f3..142e3d6 100644 > --- a/include/linux/perf_event.h > +++ b/include/linux/perf_event.h > @@ -850,6 +850,7 @@ struct perf_event_context { > int nr_active; > int is_active; > int nr_stat; > + int rotate_disable; > atomic_t refcount; > struct task_struct *task; > > diff --git a/kernel/perf_event.c b/kernel/perf_event.c > index 671f6c8..f365dd8 100644 > --- a/kernel/perf_event.c > +++ b/kernel/perf_event.c > @@ -1622,8 +1622,12 @@ static void rotate_ctx(struct perf_event_context *ctx) > { > raw_spin_lock(&ctx->lock); > > - /* Rotate the first entry last of non-pinned groups */ > - list_rotate_left(&ctx->flexible_groups); > + /* > + * Rotate the first entry last of non-pinned groups. Rotation might be > + * disabled by the inheritance code. > + */ > + if (!ctx->rotate_disable) > + list_rotate_left(&ctx->flexible_groups); > > raw_spin_unlock(&ctx->lock); > } > @@ -6162,6 +6166,7 @@ int perf_event_init_context(struct task_struct *child, > int ctxn) > struct perf_event *event; > struct task_struct *parent = current; > int inherited_all = 1; > + unsigned long flags; > int ret = 0; > > child->perf_event_ctxp[ctxn] = NULL; > @@ -6202,6 +6207,15 @@ int perf_event_init_context(struct task_struct *child, > int ctxn) > break; > } > > + /* > + * We can't hold ctx->lock when iterating the ->flexible_group list due > + * to allocations, but we need to prevent rotation because > + * rotate_ctx() will change the list from interrupt context. > + */ > + raw_spin_lock_irqsave(&parent_ctx->lock, flags); > + parent_ctx->rotate_disable = 1; > + raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); > + > list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) { > ret = inherit_task_group(event, parent, parent_ctx, > child, ctxn, &inherited_all); > @@ -6209,6 +6223,10 @@ int perf_event_init_context(struct task_struct *child, > int ctxn) > break; > } > > + raw_spin_lock_irqsave(&parent_ctx->lock, flags); > + parent_ctx->rotate_disable = 0; > + raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); > + > child_ctx = child->perf_event_ctxp[ctxn]; > > if (child_ctx && inherited_all) { > > _______________________________________________ > stable mailing list > [email protected] > http://linux.kernel.org/mailman/listinfo/stable _______________________________________________ stable mailing list [email protected] http://linux.kernel.org/mailman/listinfo/stable
