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

Commit 65a64464 authored by Andi Kleen's avatar Andi Kleen
Browse files

HWPOISON: Allow schedule_on_each_cpu() from keventd



Right now when calling schedule_on_each_cpu() from keventd there
is a deadlock because it tries to schedule a work item on the current CPU
too. This happens via lru_add_drain_all() in hwpoison.

Just call the function for the current CPU in this case. This is actually
faster too.

Debugging with Fengguang Wu & Max Asbock

Signed-off-by: default avatarAndi Kleen <ak@linux.intel.com>
parent 5d5429af
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -667,21 +667,38 @@ EXPORT_SYMBOL(schedule_delayed_work_on);
int schedule_on_each_cpu(work_func_t func)
{
	int cpu;
	int orig = -1;
	struct work_struct *works;

	works = alloc_percpu(struct work_struct);
	if (!works)
		return -ENOMEM;

	/*
	 * when running in keventd don't schedule a work item on itself.
	 * Can just call directly because the work queue is already bound.
	 * This also is faster.
	 * Make this a generic parameter for other workqueues?
	 */
	if (current_is_keventd()) {
		orig = raw_smp_processor_id();
		INIT_WORK(per_cpu_ptr(works, orig), func);
		func(per_cpu_ptr(works, orig));
	}

	get_online_cpus();
	for_each_online_cpu(cpu) {
		struct work_struct *work = per_cpu_ptr(works, cpu);

		if (cpu == orig)
			continue;
		INIT_WORK(work, func);
		schedule_work_on(cpu, work);
	}
	for_each_online_cpu(cpu)
	for_each_online_cpu(cpu) {
		if (cpu != orig)
			flush_work(per_cpu_ptr(works, cpu));
	}
	put_online_cpus();
	free_percpu(works);
	return 0;