mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
smp: convert cpu_hotplug_begin into a blocking lock acquisition
Don't allow cpu_hotplug_begin to fail by converting the trylock into a
blocking lock acquisition. Write users of the cpu_add_remove_lock are
limited to CPU plug/unplug operations, and cannot deadlock between
themselves or other users taking the lock in read mode as
cpu_add_remove_lock is always locked with interrupts enabled. There
are also no other locks taken during the plug/unplug operations.
The exclusive lock usage in register_cpu_notifier is also converted
into a blocking lock acquisition, as it was previously not allowed to
fail anyway.
This is meaningful when running Xen in shim mode, since VCPU_{up/down}
hypercalls use cpu hotplug/unplug operations in the background, and
hence failing to take the lock results in VPCU_{up/down} failing with
-EBUSY, which most users are not prepared to handle.
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
868a01021c
commit
5b74f5e428
3 files changed
+7
-11
No files matched your search
@@ -1255,8 +1255,7 @@ int cpu_add(uint32_t apic_id, uint32_t acpi_id, uint32_t pxm)
|
||||
(pxm >= 256) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( !cpu_hotplug_begin() )
|
||||
return -EBUSY;
|
||||
cpu_hotplug_begin();
|
||||
|
||||
/* Detect if the cpu has been added before */
|
||||
if ( x86_acpiid_to_apicid[acpi_id] != BAD_APICID )
|
||||
|
||||
+5
-8
@@ -51,9 +51,9 @@ void put_cpu_maps(void)
|
||||
read_unlock(&cpu_add_remove_lock);
|
||||
}
|
||||
|
||||
bool cpu_hotplug_begin(void)
|
||||
void cpu_hotplug_begin(void)
|
||||
{
|
||||
return write_trylock(&cpu_add_remove_lock);
|
||||
write_lock(&cpu_add_remove_lock);
|
||||
}
|
||||
|
||||
void cpu_hotplug_done(void)
|
||||
@@ -65,8 +65,7 @@ static NOTIFIER_HEAD(cpu_chain);
|
||||
|
||||
void __init register_cpu_notifier(struct notifier_block *nb)
|
||||
{
|
||||
if ( !write_trylock(&cpu_add_remove_lock) )
|
||||
BUG(); /* Should never fail as we are called only during boot. */
|
||||
write_lock(&cpu_add_remove_lock);
|
||||
notifier_chain_register(&cpu_chain, nb);
|
||||
write_unlock(&cpu_add_remove_lock);
|
||||
}
|
||||
@@ -100,8 +99,7 @@ int cpu_down(unsigned int cpu)
|
||||
int err;
|
||||
struct notifier_block *nb = NULL;
|
||||
|
||||
if ( !cpu_hotplug_begin() )
|
||||
return -EBUSY;
|
||||
cpu_hotplug_begin();
|
||||
|
||||
err = -EINVAL;
|
||||
if ( (cpu >= nr_cpu_ids) || (cpu == 0) )
|
||||
@@ -142,8 +140,7 @@ int cpu_up(unsigned int cpu)
|
||||
int err;
|
||||
struct notifier_block *nb = NULL;
|
||||
|
||||
if ( !cpu_hotplug_begin() )
|
||||
return -EBUSY;
|
||||
cpu_hotplug_begin();
|
||||
|
||||
err = -EINVAL;
|
||||
if ( (cpu >= nr_cpu_ids) || !cpu_present(cpu) )
|
||||
|
||||
@@ -10,7 +10,7 @@ bool get_cpu_maps(void);
|
||||
void put_cpu_maps(void);
|
||||
|
||||
/* Safely perform CPU hotplug and update cpu_online_map, etc. */
|
||||
bool cpu_hotplug_begin(void);
|
||||
void cpu_hotplug_begin(void);
|
||||
void cpu_hotplug_done(void);
|
||||
|
||||
/* Receive notification of CPU hotplug events. */
|
||||
|
||||