diff options
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.patch | 113 |
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 + |