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

Commit 3fc1f1e2 authored by Tejun Heo's avatar Tejun Heo
Browse files

stop_machine: reimplement using cpu_stop



Reimplement stop_machine using cpu_stop.  As cpu stoppers are
guaranteed to be available for all online cpus,
stop_machine_create/destroy() are no longer necessary and removed.

With resource management and synchronization handled by cpu_stop, the
new implementation is much simpler.  Asking the cpu_stop to execute
the stop_cpu() state machine on all online cpus with cpu hotplug
disabled is enough.

stop_machine itself doesn't need to manage any global resources
anymore, so all per-instance information is rolled into struct
stop_machine_data and the mutex and all static data variables are
removed.

The previous implementation created and destroyed RT workqueues as
necessary which made stop_machine() calls highly expensive on very
large machines.  According to Dimitri Sivanich, preventing the dynamic
creation/destruction makes booting faster more than twice on very
large machines.  cpu_stop resources are preallocated for all online
cpus and should have the same effect.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarRusty Russell <rusty@rustcorp.com.au>
Acked-by: default avatarPeter Zijlstra <peterz@infradead.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Dimitri Sivanich <sivanich@sgi.com>
parent 1142d810
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -390,7 +390,6 @@ static void __init time_init_wq(void)
	if (time_sync_wq)
	if (time_sync_wq)
		return;
		return;
	time_sync_wq = create_singlethread_workqueue("timesync");
	time_sync_wq = create_singlethread_workqueue("timesync");
	stop_machine_create();
}
}


/*
/*
+2 −12
Original line number Original line Diff line number Diff line
@@ -80,12 +80,6 @@ static void do_suspend(void)


	shutting_down = SHUTDOWN_SUSPEND;
	shutting_down = SHUTDOWN_SUSPEND;


	err = stop_machine_create();
	if (err) {
		printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err);
		goto out;
	}

#ifdef CONFIG_PREEMPT
#ifdef CONFIG_PREEMPT
	/* If the kernel is preemptible, we need to freeze all the processes
	/* If the kernel is preemptible, we need to freeze all the processes
	   to prevent them from being in the middle of a pagetable update
	   to prevent them from being in the middle of a pagetable update
@@ -93,7 +87,7 @@ static void do_suspend(void)
	err = freeze_processes();
	err = freeze_processes();
	if (err) {
	if (err) {
		printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
		printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
		goto out_destroy_sm;
		goto out;
	}
	}
#endif
#endif


@@ -136,12 +130,8 @@ static void do_suspend(void)
out_thaw:
out_thaw:
#ifdef CONFIG_PREEMPT
#ifdef CONFIG_PREEMPT
	thaw_processes();
	thaw_processes();

out_destroy_sm:
#endif
	stop_machine_destroy();

out:
out:
#endif
	shutting_down = SHUTDOWN_INVALID;
	shutting_down = SHUTDOWN_INVALID;
}
}
#endif	/* CONFIG_PM_SLEEP */
#endif	/* CONFIG_PM_SLEEP */
+0 −20
Original line number Original line Diff line number Diff line
@@ -67,23 +67,6 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
 */
 */
int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);


/**
 * stop_machine_create: create all stop_machine threads
 *
 * Description: This causes all stop_machine threads to be created before
 * stop_machine actually gets called. This can be used by subsystems that
 * need a non failing stop_machine infrastructure.
 */
int stop_machine_create(void);

/**
 * stop_machine_destroy: destroy all stop_machine threads
 *
 * Description: This causes all stop_machine threads which were created with
 * stop_machine_create to be destroyed again.
 */
void stop_machine_destroy(void);

#else
#else


static inline int stop_machine(int (*fn)(void *), void *data,
static inline int stop_machine(int (*fn)(void *), void *data,
@@ -96,8 +79,5 @@ static inline int stop_machine(int (*fn)(void *), void *data,
	return ret;
	return ret;
}
}


static inline int stop_machine_create(void) { return 0; }
static inline void stop_machine_destroy(void) { }

#endif /* CONFIG_SMP */
#endif /* CONFIG_SMP */
#endif /* _LINUX_STOP_MACHINE */
#endif /* _LINUX_STOP_MACHINE */
+0 −8
Original line number Original line Diff line number Diff line
@@ -266,9 +266,6 @@ int __ref cpu_down(unsigned int cpu)
{
{
	int err;
	int err;


	err = stop_machine_create();
	if (err)
		return err;
	cpu_maps_update_begin();
	cpu_maps_update_begin();


	if (cpu_hotplug_disabled) {
	if (cpu_hotplug_disabled) {
@@ -280,7 +277,6 @@ int __ref cpu_down(unsigned int cpu)


out:
out:
	cpu_maps_update_done();
	cpu_maps_update_done();
	stop_machine_destroy();
	return err;
	return err;
}
}
EXPORT_SYMBOL(cpu_down);
EXPORT_SYMBOL(cpu_down);
@@ -361,9 +357,6 @@ int disable_nonboot_cpus(void)
{
{
	int cpu, first_cpu, error;
	int cpu, first_cpu, error;


	error = stop_machine_create();
	if (error)
		return error;
	cpu_maps_update_begin();
	cpu_maps_update_begin();
	first_cpu = cpumask_first(cpu_online_mask);
	first_cpu = cpumask_first(cpu_online_mask);
	/*
	/*
@@ -394,7 +387,6 @@ int disable_nonboot_cpus(void)
		printk(KERN_ERR "Non-boot CPUs are not disabled\n");
		printk(KERN_ERR "Non-boot CPUs are not disabled\n");
	}
	}
	cpu_maps_update_done();
	cpu_maps_update_done();
	stop_machine_destroy();
	return error;
	return error;
}
}


+2 −12
Original line number Original line Diff line number Diff line
@@ -723,16 +723,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
		return -EFAULT;
		return -EFAULT;
	name[MODULE_NAME_LEN-1] = '\0';
	name[MODULE_NAME_LEN-1] = '\0';


	/* Create stop_machine threads since free_module relies on
	if (mutex_lock_interruptible(&module_mutex) != 0)
	 * a non-failing stop_machine call. */
		return -EINTR;
	ret = stop_machine_create();
	if (ret)
		return ret;

	if (mutex_lock_interruptible(&module_mutex) != 0) {
		ret = -EINTR;
		goto out_stop;
	}


	mod = find_module(name);
	mod = find_module(name);
	if (!mod) {
	if (!mod) {
@@ -792,8 +784,6 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,


 out:
 out:
	mutex_unlock(&module_mutex);
	mutex_unlock(&module_mutex);
out_stop:
	stop_machine_destroy();
	return ret;
	return ret;
}
}


Loading