* [patch 0/2] stop_machine: create kstop threads only when needed
@ 2008-12-22 11:36 Heiko Carstens
2008-12-22 11:36 ` [patch 1/2] stop_machine: introduce stop_machine_create/destroy Heiko Carstens
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Heiko Carstens @ 2008-12-22 11:36 UTC (permalink / raw)
To: Andrew Morton, Rusty Russell; +Cc: linux-kernel, Heiko Carstens
Introduce stop_machine_create/destroy. With this interface subsystems
that need a non-failing stop_machine environment can create the
stop_machine threads before actually calling stop_machine.
When the threads aren't needed anymore they can be killed with
stop_machine_destroy again.
When stop_machine gets called and the threads aren't present they
will be created and destroyed automatically.
This restores the old behaviour of stop_machine from 2.6.27 and thus
we get rid of the normally not needed kstop threads.
The second patch converts the module loader/unloder code to the new
interface, since it needs a non-failing stop_machine infrastructure.
Looks like there are more users that need a non-failing version.
I'll take care of them when I'm back from vacation.
^ permalink raw reply [flat|nested] 7+ messages in thread* [patch 1/2] stop_machine: introduce stop_machine_create/destroy. 2008-12-22 11:36 [patch 0/2] stop_machine: create kstop threads only when needed Heiko Carstens @ 2008-12-22 11:36 ` Heiko Carstens 2009-01-27 8:04 ` [Bug 12492] " Andrew Morton 2008-12-22 11:36 ` [patch 2/2] module: convert to stop_machine_create/destroy Heiko Carstens 2008-12-25 13:07 ` [patch 0/2] stop_machine: create kstop threads only when needed Rusty Russell 2 siblings, 1 reply; 7+ messages in thread From: Heiko Carstens @ 2008-12-22 11:36 UTC (permalink / raw) To: Andrew Morton, Rusty Russell; +Cc: linux-kernel, Heiko Carstens [-- Attachment #1: 001_stop.diff --] [-- Type: text/plain, Size: 5299 bytes --] From: Heiko Carstens <heiko.carstens@de.ibm.com> Introduce stop_machine_create/destroy. With this interface subsystems that need a non-failing stop_machine environment can create the stop_machine machine threads before actually calling stop_machine. When the threads aren't needed anymore they can be killed with stop_machine_destroy again. When stop_machine gets called and the threads aren't present they will be created and destroyed automatically. This restores the old behaviour of stop_machine. This patch also converts cpu hotplug to the new interface since it is special: cpu_down calls __stop_machine instead of stop_machine. However the kstop threads will only be created when stop_machine gets called. Changing the code so that the threads would be created automatically on __stop_machine is currently not possible: when __stop_machine gets called we hold cpu_add_remove_lock, which is the same lock that create_rt_workqueue would take. So the workqueue needs to be created before the cpu hotplug code locks cpu_add_remove_lock. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> --- include/linux/stop_machine.h | 22 +++++++++++++++++ kernel/cpu.c | 6 +++- kernel/stop_machine.c | 55 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 72 insertions(+), 11 deletions(-) Index: linux-2.6/kernel/stop_machine.c =================================================================== --- linux-2.6.orig/kernel/stop_machine.c +++ linux-2.6/kernel/stop_machine.c @@ -38,7 +38,10 @@ struct stop_machine_data { static unsigned int num_threads; static atomic_t thread_ack; static DEFINE_MUTEX(lock); - +/* setup_lock protects refcount, stop_machine_wq and stop_machine_work. */ +static DEFINE_MUTEX(setup_lock); +/* Users of stop_machine. */ +static int refcount; static struct workqueue_struct *stop_machine_wq; static struct stop_machine_data active, idle; static const cpumask_t *active_cpus; @@ -109,6 +112,43 @@ static int chill(void *unused) return 0; } +int stop_machine_create(void) +{ + mutex_lock(&setup_lock); + if (refcount) + goto done; + stop_machine_wq = create_rt_workqueue("kstop"); + if (!stop_machine_wq) + goto err_out; + stop_machine_work = alloc_percpu(struct work_struct); + if (!stop_machine_work) + goto err_out; +done: + refcount++; + mutex_unlock(&setup_lock); + return 0; + +err_out: + if (stop_machine_wq) + destroy_workqueue(stop_machine_wq); + mutex_unlock(&setup_lock); + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(stop_machine_create); + +void stop_machine_destroy(void) +{ + mutex_lock(&setup_lock); + refcount--; + if (refcount) + goto done; + destroy_workqueue(stop_machine_wq); + free_percpu(stop_machine_work); +done: + mutex_unlock(&setup_lock); +} +EXPORT_SYMBOL_GPL(stop_machine_destroy); + int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus) { struct work_struct *sm_work; @@ -146,19 +186,14 @@ int stop_machine(int (*fn)(void *), void { int ret; + ret = stop_machine_create(); + if (ret) + return ret; /* No CPUs can come up or down during this. */ get_online_cpus(); ret = __stop_machine(fn, data, cpus); put_online_cpus(); - + stop_machine_destroy(); return ret; } EXPORT_SYMBOL_GPL(stop_machine); - -static int __init stop_machine_init(void) -{ - stop_machine_wq = create_rt_workqueue("kstop"); - stop_machine_work = alloc_percpu(struct work_struct); - return 0; -} -core_initcall(stop_machine_init); Index: linux-2.6/kernel/cpu.c =================================================================== --- linux-2.6.orig/kernel/cpu.c +++ linux-2.6/kernel/cpu.c @@ -290,8 +290,11 @@ out_release: int __ref cpu_down(unsigned int cpu) { - int err = 0; + int err; + err = stop_machine_create(); + if (err) + return err; cpu_maps_update_begin(); if (cpu_hotplug_disabled) { @@ -318,6 +321,7 @@ int __ref cpu_down(unsigned int cpu) out: cpu_maps_update_done(); + stop_machine_destroy(); return err; } EXPORT_SYMBOL(cpu_down); Index: linux-2.6/include/linux/stop_machine.h =================================================================== --- linux-2.6.orig/include/linux/stop_machine.h +++ linux-2.6/include/linux/stop_machine.h @@ -35,6 +35,24 @@ int stop_machine(int (*fn)(void *), void * won't come or go while it's being called. Used by hotplug cpu. */ int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *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 static inline int stop_machine(int (*fn)(void *), void *data, @@ -46,5 +64,9 @@ static inline int stop_machine(int (*fn) local_irq_enable(); return ret; } + +static inline int stop_machine_create(void) { return 0; } +static inline void stop_machine_destroy(void) { } + #endif /* CONFIG_SMP */ #endif /* _LINUX_STOP_MACHINE */ -- ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug 12492] Re: [patch 1/2] stop_machine: introduce stop_machine_create/destroy. 2008-12-22 11:36 ` [patch 1/2] stop_machine: introduce stop_machine_create/destroy Heiko Carstens @ 2009-01-27 8:04 ` Andrew Morton 2009-01-27 9:52 ` Andrew Morton 0 siblings, 1 reply; 7+ messages in thread From: Andrew Morton @ 2009-01-27 8:04 UTC (permalink / raw) To: Heiko Carstens; +Cc: Rusty Russell, linux-kernel, Tomas Carnecky, bugme-daemon On Mon, 22 Dec 2008 12:36:30 +0100 Heiko Carstens <heiko.carstens@de.ibm.com> wrote: > Introduce stop_machine_create/destroy. With this interface subsystems > that need a non-failing stop_machine environment can create the > stop_machine machine threads before actually calling stop_machine. > When the threads aren't needed anymore they can be killed with > stop_machine_destroy again. > > When stop_machine gets called and the threads aren't present they > will be created and destroyed automatically. This restores the old > behaviour of stop_machine. > > This patch also converts cpu hotplug to the new interface since it > is special: cpu_down calls __stop_machine instead of stop_machine. > However the kstop threads will only be created when stop_machine > gets called. > > Changing the code so that the threads would be created automatically > on __stop_machine is currently not possible: when __stop_machine gets > called we hold cpu_add_remove_lock, which is the same lock that > create_rt_workqueue would take. So the workqueue needs to be created > before the cpu hotplug code locks cpu_add_remove_lock. In http://bugzilla.kernel.org/show_bug.cgi?id=12492, Thomas (cc'ed here) reports Commit 9ea09af3bd3090e8349ca2899ca2011bd94cda85 introduced a regression that caused the kernel to fail to suspend. The 'sleeping' LED on the laptop just keeps blinking and the laptop never shuts down. I think this was eventually fixed because with 2.6.29-rc1 and -rc2 the laptop suspends fine, but fails to resume. When I try to resume, all I see is a blinking cursor in the top left corner of the screen. I'm using acpi_sleep=s3_bios,s3_mode, suspending using a script that does: echo mem > /sys/power/state. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Bug 12492] Re: [patch 1/2] stop_machine: introduce stop_machine_create/destroy. 2009-01-27 8:04 ` [Bug 12492] " Andrew Morton @ 2009-01-27 9:52 ` Andrew Morton 2009-01-27 10:09 ` Heiko Carstens 0 siblings, 1 reply; 7+ messages in thread From: Andrew Morton @ 2009-01-27 9:52 UTC (permalink / raw) To: Heiko Carstens, Rusty Russell, linux-kernel, Tomas Carnecky, bugme-daemon On Tue, 27 Jan 2009 00:04:32 -0800 Andrew Morton <akpm@linux-foundation.org> wrote: > On Mon, 22 Dec 2008 12:36:30 +0100 Heiko Carstens <heiko.carstens@de.ibm.com> wrote: > > > Introduce stop_machine_create/destroy. With this interface subsystems > > that need a non-failing stop_machine environment can create the > > stop_machine machine threads before actually calling stop_machine. > > When the threads aren't needed anymore they can be killed with > > stop_machine_destroy again. > > > > When stop_machine gets called and the threads aren't present they > > will be created and destroyed automatically. This restores the old > > behaviour of stop_machine. > > > > This patch also converts cpu hotplug to the new interface since it > > is special: cpu_down calls __stop_machine instead of stop_machine. > > However the kstop threads will only be created when stop_machine > > gets called. > > > > Changing the code so that the threads would be created automatically > > on __stop_machine is currently not possible: when __stop_machine gets > > called we hold cpu_add_remove_lock, which is the same lock that > > create_rt_workqueue would take. So the workqueue needs to be created > > before the cpu hotplug code locks cpu_add_remove_lock. > > In http://bugzilla.kernel.org/show_bug.cgi?id=12492, Thomas (cc'ed > here) reports > > Commit 9ea09af3bd3090e8349ca2899ca2011bd94cda85 introduced a > regression that caused the kernel to fail to suspend. The 'sleeping' > LED on the laptop just keeps blinking and the laptop never shuts > down. I think this was eventually fixed because with 2.6.29-rc1 and > -rc2 the laptop suspends fine, but fails to resume. When I try to > resume, all I see is a blinking cursor in the top left corner of the > screen. > > I'm using acpi_sleep=s3_bios,s3_mode, suspending using a script > that does: echo mem > /sys/power/state. > hm. Re-reading this, it seems to be saying that 9ea09af3bd3090e8349ca2899ca2011bd94cda85 might be innocent, and that some other patch might have caused the resume regression? ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Bug 12492] Re: [patch 1/2] stop_machine: introduce stop_machine_create/destroy. 2009-01-27 9:52 ` Andrew Morton @ 2009-01-27 10:09 ` Heiko Carstens 0 siblings, 0 replies; 7+ messages in thread From: Heiko Carstens @ 2009-01-27 10:09 UTC (permalink / raw) To: Andrew Morton; +Cc: Rusty Russell, linux-kernel, Tomas Carnecky, bugme-daemon On Tue, 27 Jan 2009 01:52:02 -0800 Andrew Morton <akpm@linux-foundation.org> wrote: > On Tue, 27 Jan 2009 00:04:32 -0800 Andrew Morton <akpm@linux-foundation.org> wrote: > > Commit 9ea09af3bd3090e8349ca2899ca2011bd94cda85 introduced a > > regression that caused the kernel to fail to suspend. The 'sleeping' > > LED on the laptop just keeps blinking and the laptop never shuts > > down. I think this was eventually fixed because with 2.6.29-rc1 and > > -rc2 the laptop suspends fine, but fails to resume. When I try to > > resume, all I see is a blinking cursor in the top left corner of the > > screen. > > > > I'm using acpi_sleep=s3_bios,s3_mode, suspending using a script > > that does: echo mem > /sys/power/state. > > hm. Re-reading this, it seems to be saying that > 9ea09af3bd3090e8349ca2899ca2011bd94cda85 might be innocent, and that > some other patch might have caused the resume regression? Yes, I already updated the bugzilla entry at kernel.org: The bug introduced with the introduction of stop_machine_create/destroy was fixed with a0e280e0f33f6c859a235fb69a875ed8f3420388 "stop_machine/cpu hotplug: fix disable_nonboot_cpus". Must be something else. ^ permalink raw reply [flat|nested] 7+ messages in thread
* [patch 2/2] module: convert to stop_machine_create/destroy. 2008-12-22 11:36 [patch 0/2] stop_machine: create kstop threads only when needed Heiko Carstens 2008-12-22 11:36 ` [patch 1/2] stop_machine: introduce stop_machine_create/destroy Heiko Carstens @ 2008-12-22 11:36 ` Heiko Carstens 2008-12-25 13:07 ` [patch 0/2] stop_machine: create kstop threads only when needed Rusty Russell 2 siblings, 0 replies; 7+ messages in thread From: Heiko Carstens @ 2008-12-22 11:36 UTC (permalink / raw) To: Andrew Morton, Rusty Russell; +Cc: linux-kernel, Heiko Carstens [-- Attachment #1: 002_module.diff --] [-- Type: text/plain, Size: 1967 bytes --] From: Heiko Carstens <heiko.carstens@de.ibm.com> The module code relies on a non-failing stop_machine call. So we create the kstop threads in advance and with that make sure the call won't fail. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> --- kernel/module.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) Index: linux-2.6/kernel/module.c =================================================================== --- linux-2.6.orig/kernel/module.c +++ linux-2.6/kernel/module.c @@ -757,8 +757,16 @@ sys_delete_module(const char __user *nam return -EFAULT; name[MODULE_NAME_LEN-1] = '\0'; - if (mutex_lock_interruptible(&module_mutex) != 0) - return -EINTR; + /* Create stop_machine threads since free_module relies on + * a non-failing stop_machine call. */ + ret = stop_machine_create(); + if (ret) + return ret; + + if (mutex_lock_interruptible(&module_mutex) != 0) { + ret = -EINTR; + goto out_stop; + } mod = find_module(name); if (!mod) { @@ -817,6 +825,8 @@ sys_delete_module(const char __user *nam out: mutex_unlock(&module_mutex); +out_stop: + stop_machine_destroy(); return ret; } @@ -1865,6 +1875,13 @@ static noinline struct module *load_modu /* vmalloc barfs on "unusual" numbers. Check here */ if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL) return ERR_PTR(-ENOMEM); + + /* Create stop_machine threads since the error path relies on + * a non-failing stop_machine call. */ + err = stop_machine_create(); + if (err) + goto free_hdr; + if (copy_from_user(hdr, umod, len) != 0) { err = -EFAULT; goto free_hdr; @@ -2257,6 +2274,7 @@ static noinline struct module *load_modu /* Get rid of temporary copy */ vfree(hdr); + stop_machine_destroy(); /* Done! */ return mod; @@ -2279,6 +2297,7 @@ static noinline struct module *load_modu kfree(args); free_hdr: vfree(hdr); + stop_machine_destroy(); return ERR_PTR(err); truncated: -- ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 0/2] stop_machine: create kstop threads only when needed 2008-12-22 11:36 [patch 0/2] stop_machine: create kstop threads only when needed Heiko Carstens 2008-12-22 11:36 ` [patch 1/2] stop_machine: introduce stop_machine_create/destroy Heiko Carstens 2008-12-22 11:36 ` [patch 2/2] module: convert to stop_machine_create/destroy Heiko Carstens @ 2008-12-25 13:07 ` Rusty Russell 2 siblings, 0 replies; 7+ messages in thread From: Rusty Russell @ 2008-12-25 13:07 UTC (permalink / raw) To: Heiko Carstens; +Cc: Andrew Morton, linux-kernel On Monday 22 December 2008 22:06:29 Heiko Carstens wrote: > Introduce stop_machine_create/destroy. With this interface subsystems > that need a non-failing stop_machine environment can create the > stop_machine threads before actually calling stop_machine. > When the threads aren't needed anymore they can be killed with > stop_machine_destroy again. Thanks, this is straightforward and effective. I've applied both patches, Rusty. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-01-27 10:09 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-12-22 11:36 [patch 0/2] stop_machine: create kstop threads only when needed Heiko Carstens 2008-12-22 11:36 ` [patch 1/2] stop_machine: introduce stop_machine_create/destroy Heiko Carstens 2009-01-27 8:04 ` [Bug 12492] " Andrew Morton 2009-01-27 9:52 ` Andrew Morton 2009-01-27 10:09 ` Heiko Carstens 2008-12-22 11:36 ` [patch 2/2] module: convert to stop_machine_create/destroy Heiko Carstens 2008-12-25 13:07 ` [patch 0/2] stop_machine: create kstop threads only when needed Rusty Russell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox