mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-16 09:56:46 +00:00
cgroup/cpuset: Enforce at most one rebuild_sched_domains_locked() call per operation
Since commit ff0ce721ec21 ("cgroup/cpuset: Eliminate unncessary sched domains rebuilds in hotplug"), there is only one rebuild_sched_domains_locked() call per hotplug operation. However, writing to the various cpuset control files may still casue more than one rebuild_sched_domains_locked() call to happen in some cases. Juri had found that two rebuild_sched_domains_locked() calls in update_prstate(), one from update_cpumasks_hier() and another one from update_partition_sd_lb() could cause cpuset partition to be created with null total_bw for DL tasks. IOW, DL tasks may not be scheduled correctly in such a partition. A sample command sequence that can reproduce null total_bw is as follows. # echo Y >/sys/kernel/debug/sched/verbose # echo +cpuset >/sys/fs/cgroup/cgroup.subtree_control # mkdir /sys/fs/cgroup/test # echo 0-7 > /sys/fs/cgroup/test/cpuset.cpus # echo 6-7 > /sys/fs/cgroup/test/cpuset.cpus.exclusive # echo root >/sys/fs/cgroup/test/cpuset.cpus.partition Fix this double rebuild_sched_domains_locked() calls problem by replacing existing calls with cpuset_force_rebuild() except the rebuild_sched_domains_cpuslocked() call at the end of cpuset_handle_hotplug(). Checking of the force_sd_rebuild flag is now done at the end of cpuset_write_resmask() and update_prstate() to determine if rebuild_sched_domains_locked() should be called or not. The cpuset v1 code can still call rebuild_sched_domains_locked() directly as double rebuild_sched_domains_locked() calls is not possible. Reported-by: Juri Lelli <juri.lelli@redhat.com> Closes: https://lore.kernel.org/lkml/ZyuUcJDPBln1BK1Y@jlelli-thinkpadt14gen4.remote.csb/ Signed-off-by: Waiman Long <longman@redhat.com> Tested-by: Juri Lelli <juri.lelli@redhat.com> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
bcd7012afd
commit
a040c35128
@ -84,9 +84,19 @@ static bool have_boot_isolcpus;
|
|||||||
static struct list_head remote_children;
|
static struct list_head remote_children;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A flag to force sched domain rebuild at the end of an operation while
|
* A flag to force sched domain rebuild at the end of an operation.
|
||||||
* inhibiting it in the intermediate stages when set. Currently it is only
|
* It can be set in
|
||||||
* set in hotplug code.
|
* - update_partition_sd_lb()
|
||||||
|
* - remote_partition_check()
|
||||||
|
* - update_cpumasks_hier()
|
||||||
|
* - cpuset_update_flag()
|
||||||
|
* - cpuset_hotplug_update_tasks()
|
||||||
|
* - cpuset_handle_hotplug()
|
||||||
|
*
|
||||||
|
* Protected by cpuset_mutex (with cpus_read_lock held) or cpus_write_lock.
|
||||||
|
*
|
||||||
|
* Note that update_relax_domain_level() in cpuset-v1.c can still call
|
||||||
|
* rebuild_sched_domains_locked() directly without using this flag.
|
||||||
*/
|
*/
|
||||||
static bool force_sd_rebuild;
|
static bool force_sd_rebuild;
|
||||||
|
|
||||||
@ -990,6 +1000,7 @@ void rebuild_sched_domains_locked(void)
|
|||||||
|
|
||||||
lockdep_assert_cpus_held();
|
lockdep_assert_cpus_held();
|
||||||
lockdep_assert_held(&cpuset_mutex);
|
lockdep_assert_held(&cpuset_mutex);
|
||||||
|
force_sd_rebuild = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have raced with CPU hotplug, return early to avoid
|
* If we have raced with CPU hotplug, return early to avoid
|
||||||
@ -1164,8 +1175,8 @@ static void update_partition_sd_lb(struct cpuset *cs, int old_prs)
|
|||||||
clear_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
|
clear_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebuild_domains && !force_sd_rebuild)
|
if (rebuild_domains)
|
||||||
rebuild_sched_domains_locked();
|
cpuset_force_rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1512,8 +1523,8 @@ static void remote_partition_check(struct cpuset *cs, struct cpumask *newmask,
|
|||||||
remote_partition_disable(child, tmp);
|
remote_partition_disable(child, tmp);
|
||||||
disable_cnt++;
|
disable_cnt++;
|
||||||
}
|
}
|
||||||
if (disable_cnt && !force_sd_rebuild)
|
if (disable_cnt)
|
||||||
rebuild_sched_domains_locked();
|
cpuset_force_rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2106,8 +2117,8 @@ get_css:
|
|||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (need_rebuild_sched_domains && !force_sd_rebuild)
|
if (need_rebuild_sched_domains)
|
||||||
rebuild_sched_domains_locked();
|
cpuset_force_rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2726,9 +2737,13 @@ int cpuset_update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
|
|||||||
cs->flags = trialcs->flags;
|
cs->flags = trialcs->flags;
|
||||||
spin_unlock_irq(&callback_lock);
|
spin_unlock_irq(&callback_lock);
|
||||||
|
|
||||||
if (!cpumask_empty(trialcs->cpus_allowed) && balance_flag_changed &&
|
if (!cpumask_empty(trialcs->cpus_allowed) && balance_flag_changed) {
|
||||||
!force_sd_rebuild)
|
if (!IS_ENABLED(CONFIG_CPUSETS_V1) ||
|
||||||
rebuild_sched_domains_locked();
|
cgroup_subsys_on_dfl(cpuset_cgrp_subsys))
|
||||||
|
cpuset_force_rebuild();
|
||||||
|
else
|
||||||
|
rebuild_sched_domains_locked();
|
||||||
|
}
|
||||||
|
|
||||||
if (spread_flag_changed)
|
if (spread_flag_changed)
|
||||||
cpuset1_update_tasks_flags(cs);
|
cpuset1_update_tasks_flags(cs);
|
||||||
@ -2848,6 +2863,8 @@ out:
|
|||||||
update_partition_sd_lb(cs, old_prs);
|
update_partition_sd_lb(cs, old_prs);
|
||||||
|
|
||||||
notify_partition_change(cs, old_prs);
|
notify_partition_change(cs, old_prs);
|
||||||
|
if (force_sd_rebuild)
|
||||||
|
rebuild_sched_domains_locked();
|
||||||
free_cpumasks(NULL, &tmpmask);
|
free_cpumasks(NULL, &tmpmask);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3141,6 +3158,8 @@ ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
|
|||||||
}
|
}
|
||||||
|
|
||||||
free_cpuset(trialcs);
|
free_cpuset(trialcs);
|
||||||
|
if (force_sd_rebuild)
|
||||||
|
rebuild_sched_domains_locked();
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&cpuset_mutex);
|
mutex_unlock(&cpuset_mutex);
|
||||||
cpus_read_unlock();
|
cpus_read_unlock();
|
||||||
@ -3885,11 +3904,9 @@ static void cpuset_handle_hotplug(void)
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rebuild sched domains if cpus_allowed has changed */
|
/* rebuild sched domains if necessary */
|
||||||
if (force_sd_rebuild) {
|
if (force_sd_rebuild)
|
||||||
force_sd_rebuild = false;
|
|
||||||
rebuild_sched_domains_cpuslocked();
|
rebuild_sched_domains_cpuslocked();
|
||||||
}
|
|
||||||
|
|
||||||
free_cpumasks(NULL, ptmp);
|
free_cpumasks(NULL, ptmp);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user