diff options
author | Li Zefan <lizefan@huawei.com> | 2014-07-09 04:47:29 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-07-09 15:56:16 -0400 |
commit | 734d45130cb4f668fb33d182f6943523628582ef (patch) | |
tree | d13a09fb59491e64e7cf147823d54373192dcab9 /kernel/cpuset.c | |
parent | 1344ab9c2991b45bacfd2e26a8800a62663ae427 (diff) |
cpuset: update cs->effective_{cpus, mems} when config changes
We're going to have separate user-configured masks and effective ones.
Eventually configured masks can only be changed by writing cpuset.cpus
and cpuset.mems, and they won't be restricted by parent cpuset. While
effective masks reflect cpu/memory hotplug and hierachical restriction,
and these are the real masks that apply to the tasks in the cpuset.
We calculate effective mask this way:
- top cpuset's effective_mask == online_mask, otherwise
- cpuset's effective_mask == configured_mask & parent effective_mask,
if the result is empty, it inherits parent effective mask.
Those behavior changes are for default hierarchy only. For legacy
hierarchy, effective_mask and configured_mask are the same, so we won't
break old interfaces.
To make cs->effective_{cpus,mems} to be effective masks, we need to
- update the effective masks at hotplug
- update the effective masks at config change
- take on ancestor's mask when the effective mask is empty
The second item is done here. We don't need to treat root_cs specially
in update_cpumasks_hier().
This won't introduce behavior change.
v3:
- add a WARN_ON() to check if effective masks are the same with configured
masks on legacy hierarchy.
- pass trialcs->cpus_allowed to update_cpumasks_hier() and add a comment for
it. Similar change for update_nodemasks_hier(). Suggested by Tejun.
v2:
- revise the comment in update_{cpu,node}masks_hier(), suggested by Tejun.
- fix to use @cp instead of @cs in these two functions.
Signed-off-by: Li Zefan <lizefan@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cpuset.c')
-rw-r--r-- | kernel/cpuset.c | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 94f651d2eee5..da766c3736c4 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -855,36 +855,45 @@ static void update_tasks_cpumask(struct cpuset *cs) | |||
855 | } | 855 | } |
856 | 856 | ||
857 | /* | 857 | /* |
858 | * update_tasks_cpumask_hier - Update the cpumasks of tasks in the hierarchy. | 858 | * update_cpumasks_hier - Update effective cpumasks and tasks in the subtree |
859 | * @root_cs: the root cpuset of the hierarchy | 859 | * @cs: the cpuset to consider |
860 | * @update_root: update root cpuset or not? | 860 | * @new_cpus: temp variable for calculating new effective_cpus |
861 | * | ||
862 | * When congifured cpumask is changed, the effective cpumasks of this cpuset | ||
863 | * and all its descendants need to be updated. | ||
861 | * | 864 | * |
862 | * This will update cpumasks of tasks in @root_cs and all other empty cpusets | 865 | * On legacy hierachy, effective_cpus will be the same with cpu_allowed. |
863 | * which take on cpumask of @root_cs. | ||
864 | * | 866 | * |
865 | * Called with cpuset_mutex held | 867 | * Called with cpuset_mutex held |
866 | */ | 868 | */ |
867 | static void update_tasks_cpumask_hier(struct cpuset *root_cs, bool update_root) | 869 | static void update_cpumasks_hier(struct cpuset *cs, struct cpumask *new_cpus) |
868 | { | 870 | { |
869 | struct cpuset *cp; | 871 | struct cpuset *cp; |
870 | struct cgroup_subsys_state *pos_css; | 872 | struct cgroup_subsys_state *pos_css; |
871 | 873 | ||
872 | rcu_read_lock(); | 874 | rcu_read_lock(); |
873 | cpuset_for_each_descendant_pre(cp, pos_css, root_cs) { | 875 | cpuset_for_each_descendant_pre(cp, pos_css, cs) { |
874 | if (cp == root_cs) { | 876 | struct cpuset *parent = parent_cs(cp); |
875 | if (!update_root) | 877 | |
876 | continue; | 878 | cpumask_and(new_cpus, cp->cpus_allowed, parent->effective_cpus); |
877 | } else { | 879 | |
878 | /* skip the whole subtree if @cp have some CPU */ | 880 | /* Skip the whole subtree if the cpumask remains the same. */ |
879 | if (!cpumask_empty(cp->cpus_allowed)) { | 881 | if (cpumask_equal(new_cpus, cp->effective_cpus)) { |
880 | pos_css = css_rightmost_descendant(pos_css); | 882 | pos_css = css_rightmost_descendant(pos_css); |
881 | continue; | 883 | continue; |
882 | } | ||
883 | } | 884 | } |
885 | |||
884 | if (!css_tryget_online(&cp->css)) | 886 | if (!css_tryget_online(&cp->css)) |
885 | continue; | 887 | continue; |
886 | rcu_read_unlock(); | 888 | rcu_read_unlock(); |
887 | 889 | ||
890 | mutex_lock(&callback_mutex); | ||
891 | cpumask_copy(cp->effective_cpus, new_cpus); | ||
892 | mutex_unlock(&callback_mutex); | ||
893 | |||
894 | WARN_ON(!cgroup_on_dfl(cp->css.cgroup) && | ||
895 | !cpumask_equal(cp->cpus_allowed, cp->effective_cpus)); | ||
896 | |||
888 | update_tasks_cpumask(cp); | 897 | update_tasks_cpumask(cp); |
889 | 898 | ||
890 | rcu_read_lock(); | 899 | rcu_read_lock(); |
@@ -940,7 +949,8 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, | |||
940 | cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed); | 949 | cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed); |
941 | mutex_unlock(&callback_mutex); | 950 | mutex_unlock(&callback_mutex); |
942 | 951 | ||
943 | update_tasks_cpumask_hier(cs, true); | 952 | /* use trialcs->cpus_allowed as a temp variable */ |
953 | update_cpumasks_hier(cs, trialcs->cpus_allowed); | ||
944 | 954 | ||
945 | if (is_load_balanced) | 955 | if (is_load_balanced) |
946 | rebuild_sched_domains_locked(); | 956 | rebuild_sched_domains_locked(); |
@@ -1091,36 +1101,45 @@ static void update_tasks_nodemask(struct cpuset *cs) | |||
1091 | } | 1101 | } |
1092 | 1102 | ||
1093 | /* | 1103 | /* |
1094 | * update_tasks_nodemask_hier - Update the nodemasks of tasks in the hierarchy. | 1104 | * update_nodemasks_hier - Update effective nodemasks and tasks in the subtree |
1095 | * @cs: the root cpuset of the hierarchy | 1105 | * @cs: the cpuset to consider |
1096 | * @update_root: update the root cpuset or not? | 1106 | * @new_mems: a temp variable for calculating new effective_mems |
1107 | * | ||
1108 | * When configured nodemask is changed, the effective nodemasks of this cpuset | ||
1109 | * and all its descendants need to be updated. | ||
1097 | * | 1110 | * |
1098 | * This will update nodemasks of tasks in @root_cs and all other empty cpusets | 1111 | * On legacy hiearchy, effective_mems will be the same with mems_allowed. |
1099 | * which take on nodemask of @root_cs. | ||
1100 | * | 1112 | * |
1101 | * Called with cpuset_mutex held | 1113 | * Called with cpuset_mutex held |
1102 | */ | 1114 | */ |
1103 | static void update_tasks_nodemask_hier(struct cpuset *root_cs, bool update_root) | 1115 | static void update_nodemasks_hier(struct cpuset *cs, nodemask_t *new_mems) |
1104 | { | 1116 | { |
1105 | struct cpuset *cp; | 1117 | struct cpuset *cp; |
1106 | struct cgroup_subsys_state *pos_css; | 1118 | struct cgroup_subsys_state *pos_css; |
1107 | 1119 | ||
1108 | rcu_read_lock(); | 1120 | rcu_read_lock(); |
1109 | cpuset_for_each_descendant_pre(cp, pos_css, root_cs) { | 1121 | cpuset_for_each_descendant_pre(cp, pos_css, cs) { |
1110 | if (cp == root_cs) { | 1122 | struct cpuset *parent = parent_cs(cp); |
1111 | if (!update_root) | 1123 | |
1112 | continue; | 1124 | nodes_and(*new_mems, cp->mems_allowed, parent->effective_mems); |
1113 | } else { | 1125 | |
1114 | /* skip the whole subtree if @cp have some CPU */ | 1126 | /* Skip the whole subtree if the nodemask remains the same. */ |
1115 | if (!nodes_empty(cp->mems_allowed)) { | 1127 | if (nodes_equal(*new_mems, cp->effective_mems)) { |
1116 | pos_css = css_rightmost_descendant(pos_css); | 1128 | pos_css = css_rightmost_descendant(pos_css); |
1117 | continue; | 1129 | continue; |
1118 | } | ||
1119 | } | 1130 | } |
1131 | |||
1120 | if (!css_tryget_online(&cp->css)) | 1132 | if (!css_tryget_online(&cp->css)) |
1121 | continue; | 1133 | continue; |
1122 | rcu_read_unlock(); | 1134 | rcu_read_unlock(); |
1123 | 1135 | ||
1136 | mutex_lock(&callback_mutex); | ||
1137 | cp->effective_mems = *new_mems; | ||
1138 | mutex_unlock(&callback_mutex); | ||
1139 | |||
1140 | WARN_ON(!cgroup_on_dfl(cp->css.cgroup) && | ||
1141 | nodes_equal(cp->mems_allowed, cp->effective_mems)); | ||
1142 | |||
1124 | update_tasks_nodemask(cp); | 1143 | update_tasks_nodemask(cp); |
1125 | 1144 | ||
1126 | rcu_read_lock(); | 1145 | rcu_read_lock(); |
@@ -1188,7 +1207,8 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs, | |||
1188 | cs->mems_allowed = trialcs->mems_allowed; | 1207 | cs->mems_allowed = trialcs->mems_allowed; |
1189 | mutex_unlock(&callback_mutex); | 1208 | mutex_unlock(&callback_mutex); |
1190 | 1209 | ||
1191 | update_tasks_nodemask_hier(cs, true); | 1210 | /* use trialcs->mems_allowed as a temp variable */ |
1211 | update_nodemasks_hier(cs, &cs->mems_allowed); | ||
1192 | done: | 1212 | done: |
1193 | return retval; | 1213 | return retval; |
1194 | } | 1214 | } |