Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33b2fb30 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

perf_counter: fix counter freeing logic



Fix counter lifetime bugs which explain the crashes reported by
Marcelo Tosatti and Arnaldo Carvalho de Melo.

The new rule is: flushing + freeing is only done for a task's
own counters, never for other tasks.

[ Impact: fix crashes/lockups with inherited counters ]

Reported-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Reported-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Acked-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent b68f1d2e
Loading
Loading
Loading
Loading
+7 −12
Original line number Diff line number Diff line
@@ -178,12 +178,6 @@ void release_task(struct task_struct * p)

	proc_flush_task(p);

	/*
	 * Flush inherited counters to the parent - before the parent
	 * gets woken up by child-exit notifications.
	 */
	perf_counter_exit_task(p);

	write_lock_irq(&tasklist_lock);
	tracehook_finish_release_task(p);
	__exit_signal(p);
@@ -985,6 +979,13 @@ NORET_TYPE void do_exit(long code)
		module_put(tsk->binfmt->module);

	proc_exit_connector(tsk);

	/*
	 * Flush inherited counters to the parent - before the parent
	 * gets woken up by child-exit notifications.
	 */
	perf_counter_exit_task(tsk);

	exit_notify(tsk, group_dead);
#ifdef CONFIG_NUMA
	mpol_put(tsk->mempolicy);
@@ -1257,12 +1258,6 @@ static int wait_task_zombie(struct task_struct *p, int options,
	 */
	read_unlock(&tasklist_lock);

	/*
	 * Flush inherited counters to the parent - before the parent
	 * gets woken up by child-exit notifications.
	 */
	perf_counter_exit_task(p);

	retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
	status = (p->signal->flags & SIGNAL_GROUP_EXIT)
		? p->signal->group_exit_code : p->exit_code;
+2 −0
Original line number Diff line number Diff line
@@ -3299,6 +3299,8 @@ void perf_counter_exit_task(struct task_struct *child)
	struct perf_counter *child_counter, *tmp;
	struct perf_counter_context *child_ctx;

	WARN_ON_ONCE(child != current);

	child_ctx = &child->perf_counter_ctx;

	if (likely(!child_ctx->nr_counters))