mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:207589dbac("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:44a7d4f0a5master date: 2024-07-31 14:50:18 +0200
This commit is contained in:
1 parent
211c73c8e9
commit
bfae66cc4c
1 file changed
+33
-30
+33
-30
@@ -2760,6 +2760,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;
|
||||
@@ -2799,7 +2829,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;
|
||||
|
||||
@@ -2817,36 +2850,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;
|
||||
|
||||