summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '0006-xen-sched-fix-error-handling-in-cpu_schedule_up.patch')
-rw-r--r--0006-xen-sched-fix-error-handling-in-cpu_schedule_up.patch113
1 files changed, 113 insertions, 0 deletions
diff --git a/0006-xen-sched-fix-error-handling-in-cpu_schedule_up.patch b/0006-xen-sched-fix-error-handling-in-cpu_schedule_up.patch
new file mode 100644
index 0000000..86189a6
--- /dev/null
+++ b/0006-xen-sched-fix-error-handling-in-cpu_schedule_up.patch
@@ -0,0 +1,113 @@
+From b37580d5e984770266783b639552a97c36ecb58a Mon Sep 17 00:00:00 2001
+From: Juergen Gross <jgross@suse.com>
+Date: Thu, 8 Aug 2024 13:46:21 +0200
+Subject: [PATCH 06/35] xen/sched: fix error handling in cpu_schedule_up()
+
+In case cpu_schedule_up() is failing, it needs to undo all externally
+visible changes it has done before.
+
+Reason is that cpu_schedule_callback() won't be called with the
+CPU_UP_CANCELED notifier in case cpu_schedule_up() did fail.
+
+Fixes: 207589dbacd4 ("xen/sched: move per cpu scheduler private data into struct sched_resource")
+Reported-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+master commit: 44a7d4f0a5e9eae41a44a162e54ff6d2ebe5b7d6
+master date: 2024-07-31 14:50:18 +0200
+---
+ xen/common/sched/core.c | 63 +++++++++++++++++++++--------------------
+ 1 file changed, 33 insertions(+), 30 deletions(-)
+
+diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c
+index d84b65f197..c466711e9e 100644
+--- a/xen/common/sched/core.c
++++ b/xen/common/sched/core.c
+@@ -2755,6 +2755,36 @@ static struct sched_resource *sched_alloc_res(void)
+ return sr;
+ }
+
++static void cf_check sched_res_free(struct rcu_head *head)
++{
++ struct sched_resource *sr = container_of(head, struct sched_resource, rcu);
++
++ free_cpumask_var(sr->cpus);
++ if ( sr->sched_unit_idle )
++ sched_free_unit_mem(sr->sched_unit_idle);
++ xfree(sr);
++}
++
++static void cpu_schedule_down(unsigned int cpu)
++{
++ struct sched_resource *sr;
++
++ rcu_read_lock(&sched_res_rculock);
++
++ sr = get_sched_res(cpu);
++
++ kill_timer(&sr->s_timer);
++
++ cpumask_clear_cpu(cpu, &sched_res_mask);
++ set_sched_res(cpu, NULL);
++
++ /* Keep idle unit. */
++ sr->sched_unit_idle = NULL;
++ call_rcu(&sr->rcu, sched_res_free);
++
++ rcu_read_unlock(&sched_res_rculock);
++}
++
+ static int cpu_schedule_up(unsigned int cpu)
+ {
+ struct sched_resource *sr;
+@@ -2794,7 +2824,10 @@ static int cpu_schedule_up(unsigned int cpu)
+ idle_vcpu[cpu]->sched_unit->res = sr;
+
+ if ( idle_vcpu[cpu] == NULL )
++ {
++ cpu_schedule_down(cpu);
+ return -ENOMEM;
++ }
+
+ idle_vcpu[cpu]->sched_unit->rendezvous_in_cnt = 0;
+
+@@ -2812,36 +2845,6 @@ static int cpu_schedule_up(unsigned int cpu)
+ return 0;
+ }
+
+-static void cf_check sched_res_free(struct rcu_head *head)
+-{
+- struct sched_resource *sr = container_of(head, struct sched_resource, rcu);
+-
+- free_cpumask_var(sr->cpus);
+- if ( sr->sched_unit_idle )
+- sched_free_unit_mem(sr->sched_unit_idle);
+- xfree(sr);
+-}
+-
+-static void cpu_schedule_down(unsigned int cpu)
+-{
+- struct sched_resource *sr;
+-
+- rcu_read_lock(&sched_res_rculock);
+-
+- sr = get_sched_res(cpu);
+-
+- kill_timer(&sr->s_timer);
+-
+- cpumask_clear_cpu(cpu, &sched_res_mask);
+- set_sched_res(cpu, NULL);
+-
+- /* Keep idle unit. */
+- sr->sched_unit_idle = NULL;
+- call_rcu(&sr->rcu, sched_res_free);
+-
+- rcu_read_unlock(&sched_res_rculock);
+-}
+-
+ void sched_rm_cpu(unsigned int cpu)
+ {
+ int rc;
+--
+2.46.1
+