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

Commit 53e353fa authored by Paul E. McKenney's avatar Paul E. McKenney Committed by Mahesh Sivasubramanian
Browse files

cpu: Avoid puts_pending overflow



A long string of get_online_cpus() with each followed by a
put_online_cpu() that fails to acquire cpu_hotplug.lock can result in
overflow of the cpu_hotplug.puts_pending counter.  Although this is
perhaps improbably, a system with absolutely no CPU-hotplug operations
will have an arbitrarily long time in which this overflow could occur.
This commit therefore adds overflow checks to get_online_cpus() and
try_get_online_cpus().

Change-Id: Iaac6c81b4cc34946a9769f1a3b4aa39fa3eb8ef3
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: default avatarPranith Kumar <bobby.prani@gmail.com>
Git-commit: 62db99f4783ea34531fc344bd8c539d5d186f24d
Git-repo: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git


Signed-off-by: default avatarMahesh Sivasubramanian <msivasub@codeaurora.org>
parent 40b49a34
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -88,6 +88,16 @@ static struct {
#define cpuhp_lock_acquire()      lock_map_acquire(&cpu_hotplug.dep_map)
#define cpuhp_lock_release()      lock_map_release(&cpu_hotplug.dep_map)

static void apply_puts_pending(int max)
{
	int delta;

	if (atomic_read(&cpu_hotplug.puts_pending) >= max) {
		delta = atomic_xchg(&cpu_hotplug.puts_pending, 0);
		cpu_hotplug.refcount -= delta;
	}
}

void get_online_cpus(void)
{
	might_sleep();
@@ -95,6 +105,7 @@ void get_online_cpus(void)
		return;
	cpuhp_lock_acquire_read();
	mutex_lock(&cpu_hotplug.lock);
	apply_puts_pending(65536);
	cpu_hotplug.refcount++;
	mutex_unlock(&cpu_hotplug.lock);
}
@@ -107,6 +118,7 @@ bool try_get_online_cpus(void)
	if (!mutex_trylock(&cpu_hotplug.lock))
		return false;
	cpuhp_lock_acquire_tryread();
	apply_puts_pending(65536);
	cpu_hotplug.refcount++;
	mutex_unlock(&cpu_hotplug.lock);
	return true;
@@ -163,12 +175,7 @@ void cpu_hotplug_begin(void)
	cpuhp_lock_acquire();
	for (;;) {
		mutex_lock(&cpu_hotplug.lock);
		if (atomic_read(&cpu_hotplug.puts_pending)) {
			int delta;

			delta = atomic_xchg(&cpu_hotplug.puts_pending, 0);
			cpu_hotplug.refcount -= delta;
		}
		apply_puts_pending(1);
		if (likely(!cpu_hotplug.refcount))
			break;
		__set_current_state(TASK_UNINTERRUPTIBLE);