diff options
author | Keir Fraser <keir@xen.org> | 2011-01-14 14:19:55 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2011-01-14 14:19:55 +0000 |
commit | 00e9c7bcb6397e85a8596cda619997982b6411e7 (patch) | |
tree | 883da4d5780df6f5278cf3b88b97f05a1798aba5 /xen/arch/x86/sysctl.c | |
parent | 9d9af7dca878fb6f85ddf3cf3cb43df273f6b5a0 (diff) | |
download | xen-00e9c7bcb6397e85a8596cda619997982b6411e7.tar.gz xen-00e9c7bcb6397e85a8596cda619997982b6411e7.tar.bz2 xen-00e9c7bcb6397e85a8596cda619997982b6411e7.zip |
x86: On CPU online/offline from dom0, try flushing RCU work on EBUSY.
Although the caller should react appropriately to EBUSY, if the error
is due to pending RCU work then we can help things along by executing
rcu_barrier() and then retrying. To this end, this changeset is an
optimisation only.
Signed-off-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/sysctl.c')
-rw-r--r-- | xen/arch/x86/sysctl.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c index 7bd20b9d0d..042bde4c46 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -30,10 +30,30 @@ #define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0) -static long cpu_down_helper(void *data) +long cpu_up_helper(void *data) { int cpu = (unsigned long)data; - return cpu_down(cpu); + int ret = cpu_up(cpu); + if ( ret == -EBUSY ) + { + /* On EBUSY, flush RCU work and have one more go. */ + rcu_barrier(); + ret = cpu_up(cpu); + } + return ret; +} + +long cpu_down_helper(void *data) +{ + int cpu = (unsigned long)data; + int ret = cpu_down(cpu); + if ( ret == -EBUSY ) + { + /* On EBUSY, flush RCU work and have one more go. */ + rcu_barrier(); + ret = cpu_down(cpu); + } + return ret; } extern int __node_distance(int a, int b); @@ -170,7 +190,8 @@ long arch_do_sysctl( switch ( sysctl->u.cpu_hotplug.op ) { case XEN_SYSCTL_CPU_HOTPLUG_ONLINE: - ret = cpu_up(cpu); + ret = continue_hypercall_on_cpu( + 0, cpu_up_helper, (void *)(unsigned long)cpu); break; case XEN_SYSCTL_CPU_HOTPLUG_OFFLINE: ret = continue_hypercall_on_cpu( |