* [patch 07/13] ACPI/processor: Fix error handling in __acpi_processor_start() [not found] <20170412200726.941336635@linutronix.de> @ 2017-04-12 20:07 ` Thomas Gleixner 2017-04-12 20:07 ` [patch 08/13] ACPI/processor: Replace racy task affinity logic Thomas Gleixner 1 sibling, 0 replies; 5+ messages in thread From: Thomas Gleixner @ 2017-04-12 20:07 UTC (permalink / raw) To: LKML Cc: Peter Zijlstra, Ingo Molnar, Sebastian Siewior, Benjamin Herrenschmidt, David S. Miller, Fenghua Yu, Herbert Xu, Lai Jiangshan, Len Brown, Michael Ellerman, Rafael J. Wysocki, Tejun Heo, Tony Luck, Viresh Kumar, linux-acpi [-- Attachment #1: ACPI-processor--Fix-error-handling-in-__acpi_processor_start--.patch --] [-- Type: text/plain, Size: 781 bytes --] When acpi_install_notify_handler() fails the cooling device stays registered and the sysfs files created via acpi_pss_perf_init() are leaked and the function returns success. Undo acpi_pss_perf_init() and return a proper error code. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net> Cc: Len Brown <lenb@kernel.org> Cc: linux-acpi@vger.kernel.org --- drivers/acpi/processor_driver.c | 3 +++ 1 file changed, 3 insertions(+) --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -251,6 +251,9 @@ static int __acpi_processor_start(struct if (ACPI_SUCCESS(status)) return 0; + result = -ENODEV; + acpi_pss_perf_exit(pr, device); + err_power_exit: acpi_processor_power_exit(pr); return result; ^ permalink raw reply [flat|nested] 5+ messages in thread
* [patch 08/13] ACPI/processor: Replace racy task affinity logic. [not found] <20170412200726.941336635@linutronix.de> 2017-04-12 20:07 ` [patch 07/13] ACPI/processor: Fix error handling in __acpi_processor_start() Thomas Gleixner @ 2017-04-12 20:07 ` Thomas Gleixner 2017-04-13 11:39 ` Peter Zijlstra 1 sibling, 1 reply; 5+ messages in thread From: Thomas Gleixner @ 2017-04-12 20:07 UTC (permalink / raw) To: LKML Cc: Peter Zijlstra, Ingo Molnar, Sebastian Siewior, Benjamin Herrenschmidt, David S. Miller, Fenghua Yu, Herbert Xu, Lai Jiangshan, Len Brown, Michael Ellerman, Rafael J. Wysocki, Tejun Heo, Tony Luck, Viresh Kumar, linux-acpi [-- Attachment #1: ACPI-processor--Use-work_on_cpu--.patch --] [-- Type: text/plain, Size: 3257 bytes --] acpi_processor_get_throttling() requires to invoke the getter function on the target CPU. This is achieved by temporarily setting the affinity of the calling user space thread to the requested CPU and reset it to the original affinity afterwards. That's racy vs. CPU hotplug and concurrent affinity settings for that thread resulting in code executing on the wrong CPU and overwriting the new affinity setting. acpi_processor_get_throttling() is invoked in two ways: 1) The CPU online callback, which is already running on the target CPU and obviously protected against hotplug and not affected by affinity settings. 2) The ACPI driver probe function, which is not protected against hotplug during modprobe. Switch it over to work_on_cpu() and protect the probe function against CPU hotplug. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net> Cc: Len Brown <lenb@kernel.org> Cc: linux-acpi@vger.kernel.org --- drivers/acpi/processor_driver.c | 7 ++++++- drivers/acpi/processor_throttling.c | 31 +++++++++++++------------------ 2 files changed, 19 insertions(+), 19 deletions(-) --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -262,11 +262,16 @@ static int __acpi_processor_start(struct static int acpi_processor_start(struct device *dev) { struct acpi_device *device = ACPI_COMPANION(dev); + int ret; if (!device) return -ENODEV; - return __acpi_processor_start(device); + /* Protect against concurrent CPU hotplug operations */ + get_online_cpus(); + ret = __acpi_processor_start(device); + put_online_cpus(); + return ret; } static int acpi_processor_stop(struct device *dev) --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -901,36 +901,31 @@ static int acpi_processor_get_throttling return 0; } -static int acpi_processor_get_throttling(struct acpi_processor *pr) +static long __acpi_processor_get_throttling(void *data) { - cpumask_var_t saved_mask; - int ret; + struct acpi_processor *pr = data; + + return pr->throttling.acpi_processor_get_throttling(pr); +} +static int acpi_processor_get_throttling(struct acpi_processor *pr) +{ if (!pr) return -EINVAL; if (!pr->flags.throttling) return -ENODEV; - if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL)) - return -ENOMEM; - /* - * Migrate task to the cpu pointed by pr. + * This is either called from the CPU hotplug callback of + * processor_driver or via the ACPI probe function. In the latter + * case the CPU is not guaranteed to be online. Both call sites are + * protected against CPU hotplug. */ - cpumask_copy(saved_mask, ¤t->cpus_allowed); - /* FIXME: use work_on_cpu() */ - if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { - /* Can't migrate to the target pr->id CPU. Exit */ - free_cpumask_var(saved_mask); + if (!cpu_online(pr->id)) return -ENODEV; - } - ret = pr->throttling.acpi_processor_get_throttling(pr); - /* restore the previous state */ - set_cpus_allowed_ptr(current, saved_mask); - free_cpumask_var(saved_mask); - return ret; + return work_on_cpu(pr->id, __acpi_processor_get_throttling, pr); } static int acpi_processor_get_fadt_info(struct acpi_processor *pr) ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [patch 08/13] ACPI/processor: Replace racy task affinity logic. 2017-04-12 20:07 ` [patch 08/13] ACPI/processor: Replace racy task affinity logic Thomas Gleixner @ 2017-04-13 11:39 ` Peter Zijlstra 2017-04-13 12:01 ` Thomas Gleixner 0 siblings, 1 reply; 5+ messages in thread From: Peter Zijlstra @ 2017-04-13 11:39 UTC (permalink / raw) To: Thomas Gleixner Cc: LKML, Ingo Molnar, Sebastian Siewior, Benjamin Herrenschmidt, David S. Miller, Fenghua Yu, Herbert Xu, Lai Jiangshan, Len Brown, Michael Ellerman, Rafael J. Wysocki, Tejun Heo, Tony Luck, Viresh Kumar, linux-acpi On Wed, Apr 12, 2017 at 10:07:34PM +0200, Thomas Gleixner wrote: > acpi_processor_get_throttling() requires to invoke the getter function on > the target CPU. This is achieved by temporarily setting the affinity of the > calling user space thread to the requested CPU and reset it to the original > affinity afterwards. > > That's racy vs. CPU hotplug and concurrent affinity settings for that > thread resulting in code executing on the wrong CPU and overwriting the > new affinity setting. > > acpi_processor_get_throttling() is invoked in two ways: > > 1) The CPU online callback, which is already running on the target CPU and > obviously protected against hotplug and not affected by affinity > settings. > > 2) The ACPI driver probe function, which is not protected against hotplug > during modprobe. > > Switch it over to work_on_cpu() and protect the probe function against CPU > hotplug. > > +static int acpi_processor_get_throttling(struct acpi_processor *pr) > +{ > if (!pr) > return -EINVAL; > > if (!pr->flags.throttling) > return -ENODEV; > > + * This is either called from the CPU hotplug callback of > + * processor_driver or via the ACPI probe function. In the latter > + * case the CPU is not guaranteed to be online. Both call sites are > + * protected against CPU hotplug. > */ > + if (!cpu_online(pr->id)) > return -ENODEV; > > + return work_on_cpu(pr->id, __acpi_processor_get_throttling, pr); > } That makes my machine sad... [ 9.583030] ============================================= [ 9.589053] [ INFO: possible recursive locking detected ] [ 9.595079] 4.11.0-rc6-00385-g5aee78a-dirty #678 Not tainted [ 9.601393] --------------------------------------------- [ 9.607418] kworker/0:0/3 is trying to acquire lock: [ 9.612954] ((&wfc.work)){+.+.+.}, at: [<ffffffff8110c172>] flush_work+0x12/0x2a0 [ 9.621406] [ 9.621406] but task is already holding lock: [ 9.627915] ((&wfc.work)){+.+.+.}, at: [<ffffffff8110df17>] process_one_work+0x1e7/0x670 [ 9.637044] [ 9.637044] other info that might help us debug this: [ 9.644330] Possible unsafe locking scenario: [ 9.644330] [ 9.650934] CPU0 [ 9.653660] ---- [ 9.656386] lock((&wfc.work)); [ 9.659987] lock((&wfc.work)); [ 9.663586] [ 9.663586] *** DEADLOCK *** [ 9.663586] [ 9.670189] May be due to missing lock nesting notation [ 9.670189] [ 9.677765] 2 locks held by kworker/0:0/3: [ 9.682332] #0: ("events"){.+.+.+}, at: [<ffffffff8110df17>] process_one_work+0x1e7/0x670 [ 9.691654] #1: ((&wfc.work)){+.+.+.}, at: [<ffffffff8110df17>] process_one_work+0x1e7/0x670 [ 9.701267] [ 9.701267] stack backtrace: [ 9.706127] CPU: 0 PID: 3 Comm: kworker/0:0 Not tainted 4.11.0-rc6-00385-g5aee78a-dirty #678 [ 9.715545] Hardware name: Intel Corporation S2600GZ/S2600GZ, BIOS SE5C600.86B.02.02.0002.122320131210 12/23/2013 [ 9.726999] Workqueue: events work_for_cpu_fn [ 9.731860] Call Trace: [ 9.734591] dump_stack+0x86/0xcf [ 9.738290] __lock_acquire+0x790/0x1620 [ 9.742667] ? __lock_acquire+0x4a5/0x1620 [ 9.747237] lock_acquire+0x100/0x210 [ 9.751319] ? lock_acquire+0x100/0x210 [ 9.755596] ? flush_work+0x12/0x2a0 [ 9.759583] flush_work+0x47/0x2a0 [ 9.763375] ? flush_work+0x12/0x2a0 [ 9.767362] ? queue_work_on+0x47/0xa0 [ 9.771545] ? __this_cpu_preempt_check+0x13/0x20 [ 9.776792] ? trace_hardirqs_on_caller+0xfb/0x1d0 [ 9.782139] ? trace_hardirqs_on+0xd/0x10 [ 9.786610] work_on_cpu+0x82/0x90 [ 9.790404] ? __usermodehelper_disable+0x110/0x110 [ 9.795846] ? __acpi_processor_get_throttling+0x20/0x20 [ 9.801773] acpi_processor_set_throttling+0x199/0x220 [ 9.807506] ? trace_hardirqs_on_caller+0xfb/0x1d0 [ 9.812851] acpi_processor_get_throttling_ptc+0xec/0x180 [ 9.818876] __acpi_processor_get_throttling+0xf/0x20 [ 9.824511] work_for_cpu_fn+0x14/0x20 [ 9.828692] process_one_work+0x261/0x670 [ 9.833165] worker_thread+0x21b/0x3f0 [ 9.837348] kthread+0x108/0x140 [ 9.840947] ? process_one_work+0x670/0x670 [ 9.845611] ? kthread_create_on_node+0x40/0x40 [ 9.850667] ret_from_fork+0x31/0x40 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [patch 08/13] ACPI/processor: Replace racy task affinity logic. 2017-04-13 11:39 ` Peter Zijlstra @ 2017-04-13 12:01 ` Thomas Gleixner 2017-04-13 12:52 ` Peter Zijlstra 0 siblings, 1 reply; 5+ messages in thread From: Thomas Gleixner @ 2017-04-13 12:01 UTC (permalink / raw) To: Peter Zijlstra Cc: LKML, Ingo Molnar, Sebastian Siewior, Benjamin Herrenschmidt, David S. Miller, Fenghua Yu, Herbert Xu, Lai Jiangshan, Len Brown, Michael Ellerman, Rafael J. Wysocki, Tejun Heo, Tony Luck, Viresh Kumar, linux-acpi On Thu, 13 Apr 2017, Peter Zijlstra wrote: > > That makes my machine sad... > [ 9.786610] work_on_cpu+0x82/0x90 > [ 9.790404] ? __usermodehelper_disable+0x110/0x110 > [ 9.795846] ? __acpi_processor_get_throttling+0x20/0x20 > [ 9.801773] acpi_processor_set_throttling+0x199/0x220 > [ 9.807506] ? trace_hardirqs_on_caller+0xfb/0x1d0 > [ 9.812851] acpi_processor_get_throttling_ptc+0xec/0x180 > [ 9.818876] __acpi_processor_get_throttling+0xf/0x20 > [ 9.824511] work_for_cpu_fn+0x14/0x20 > [ 9.828692] process_one_work+0x261/0x670 > [ 9.833165] worker_thread+0x21b/0x3f0 > [ 9.837348] kthread+0x108/0x140 > [ 9.840947] ? process_one_work+0x670/0x670 > [ 9.845611] ? kthread_create_on_node+0x40/0x40 > [ 9.850667] ret_from_fork+0x31/0x40 Yuck. So the call chain is: acpi_processor_get_throttling() work_on_cpu(acpi_processor_get_throttling) That work does: __acpi_processor_get_throttling() acpi_processor_get_throttling_ptc() acpi_processor_set_throttling() work_on_cpu(__acpi_processor_set_throttling) Why the heck calls a get_throttling() function set_throttling()? I'm mildly surprised. Does the delta patch below cure the problem? Thanks, tglx 8<-------------- --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -62,8 +62,8 @@ struct acpi_processor_throttling_arg { #define THROTTLING_POSTCHANGE (2) static int acpi_processor_get_throttling(struct acpi_processor *pr); -int acpi_processor_set_throttling(struct acpi_processor *pr, - int state, bool force); +static int __acpi_processor_set_throttling(struct acpi_processor *pr, + int state, bool force, bool direct); static int acpi_processor_update_tsd_coord(void) { @@ -891,7 +891,8 @@ static int acpi_processor_get_throttling ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid throttling state, reset\n")); state = 0; - ret = acpi_processor_set_throttling(pr, state, true); + ret = __acpi_processor_set_throttling(pr, state, true, + true); if (ret) return ret; } @@ -1075,8 +1076,15 @@ static long acpi_processor_throttling_fn arg->target_state, arg->force); } -int acpi_processor_set_throttling(struct acpi_processor *pr, - int state, bool force) +static int call_on_cpu(int cpu, long (*fn)(void *), void *arg, bool direct) +{ + if (direct) + return fn(arg); + return work_on_cpu(cpu, fn, arg); +} + +static int __acpi_processor_set_throttling(struct acpi_processor *pr, + int state, bool force, bool direct) { int ret = 0; unsigned int i; @@ -1125,7 +1133,8 @@ int acpi_processor_set_throttling(struct arg.pr = pr; arg.target_state = state; arg.force = force; - ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, &arg); + ret = call_on_cpu(pr->id, acpi_processor_throttling_fn, &arg, + direct); } else { /* * When the T-state coordination is SW_ALL or HW_ALL, @@ -1158,8 +1167,8 @@ int acpi_processor_set_throttling(struct arg.pr = match_pr; arg.target_state = state; arg.force = force; - ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, - &arg); + ret = call_on_cpu(pr->id, acpi_processor_throttling_fn, + &arg, direct); } } /* @@ -1177,6 +1186,12 @@ int acpi_processor_set_throttling(struct return ret; } +int acpi_processor_set_throttling(struct acpi_processor *pr, int state, + bool force) +{ + return __acpi_processor_set_throttling(pr, state, force, false); +} + int acpi_processor_get_throttling_info(struct acpi_processor *pr) { int result = 0; ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [patch 08/13] ACPI/processor: Replace racy task affinity logic. 2017-04-13 12:01 ` Thomas Gleixner @ 2017-04-13 12:52 ` Peter Zijlstra 0 siblings, 0 replies; 5+ messages in thread From: Peter Zijlstra @ 2017-04-13 12:52 UTC (permalink / raw) To: Thomas Gleixner Cc: LKML, Ingo Molnar, Sebastian Siewior, Benjamin Herrenschmidt, David S. Miller, Fenghua Yu, Herbert Xu, Lai Jiangshan, Len Brown, Michael Ellerman, Rafael J. Wysocki, Tejun Heo, Tony Luck, Viresh Kumar, linux-acpi On Thu, Apr 13, 2017 at 02:01:42PM +0200, Thomas Gleixner wrote: > On Thu, 13 Apr 2017, Peter Zijlstra wrote: > > > > That makes my machine sad... > > [ 9.786610] work_on_cpu+0x82/0x90 > > [ 9.790404] ? __usermodehelper_disable+0x110/0x110 > > [ 9.795846] ? __acpi_processor_get_throttling+0x20/0x20 > > [ 9.801773] acpi_processor_set_throttling+0x199/0x220 > > [ 9.807506] ? trace_hardirqs_on_caller+0xfb/0x1d0 > > [ 9.812851] acpi_processor_get_throttling_ptc+0xec/0x180 > > [ 9.818876] __acpi_processor_get_throttling+0xf/0x20 > > [ 9.824511] work_for_cpu_fn+0x14/0x20 > > [ 9.828692] process_one_work+0x261/0x670 > > [ 9.833165] worker_thread+0x21b/0x3f0 > > [ 9.837348] kthread+0x108/0x140 > > [ 9.840947] ? process_one_work+0x670/0x670 > > [ 9.845611] ? kthread_create_on_node+0x40/0x40 > > [ 9.850667] ret_from_fork+0x31/0x40 > > Yuck. So the call chain is: > > acpi_processor_get_throttling() > work_on_cpu(acpi_processor_get_throttling) > > That work does: > > __acpi_processor_get_throttling() > acpi_processor_get_throttling_ptc() > acpi_processor_set_throttling() > work_on_cpu(__acpi_processor_set_throttling) > > Why the heck calls a get_throttling() function set_throttling()? I'm mildly > surprised. > > Does the delta patch below cure the problem? Yes, aside from a compile warn. But that's disgusting... then again, you merely reintroduced this hack. ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-04-13 12:52 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20170412200726.941336635@linutronix.de>
2017-04-12 20:07 ` [patch 07/13] ACPI/processor: Fix error handling in __acpi_processor_start() Thomas Gleixner
2017-04-12 20:07 ` [patch 08/13] ACPI/processor: Replace racy task affinity logic Thomas Gleixner
2017-04-13 11:39 ` Peter Zijlstra
2017-04-13 12:01 ` Thomas Gleixner
2017-04-13 12:52 ` Peter Zijlstra
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox