Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

kthread: Honour kthreads preferred affinity after cpuset changes

When cpuset isolated partitions get updated, unbound kthreads get
indifferently affine to all non isolated CPUs, regardless of their
individual affinity preferences.

For example kswapd is a per-node kthread that prefers to be affine to
the node it refers to. Whenever an isolated partition is created,
updated or deleted, kswapd's node affinity is going to be broken if any
CPU in the related node is not isolated because kswapd will be affine
globally.

Fix this with letting the consolidated kthread managed affinity code do
the affinity update on behalf of cpuset.

Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Reviewed-by: Waiman Long <longman@redhat.com>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Marco Crivellari <marco.crivellari@suse.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Tejun Heo <tj@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Waiman Long <longman@redhat.com>
Cc: cgroups@vger.kernel.org

+37 -13
+1
include/linux/kthread.h
··· 100 100 void kthread_parkme(void); 101 101 void kthread_exit(long result) __noreturn; 102 102 void kthread_complete_and_exit(struct completion *, long) __noreturn; 103 + int kthreads_update_housekeeping(void); 103 104 104 105 int kthreadd(void *unused); 105 106 extern struct task_struct *kthreadd_task;
+2 -3
kernel/cgroup/cpuset.c
··· 1208 1208 1209 1209 if (top_cs) { 1210 1210 /* 1211 + * PF_KTHREAD tasks are handled by housekeeping. 1211 1212 * PF_NO_SETAFFINITY tasks are ignored. 1212 - * All per cpu kthreads should have PF_NO_SETAFFINITY 1213 - * flag set, see kthread_set_per_cpu(). 1214 1213 */ 1215 - if (task->flags & PF_NO_SETAFFINITY) 1214 + if (task->flags & (PF_KTHREAD | PF_NO_SETAFFINITY)) 1216 1215 continue; 1217 1216 cpumask_andnot(new_cpus, possible_mask, subpartitions_cpus); 1218 1217 } else {
+31 -10
kernel/kthread.c
··· 891 891 } 892 892 EXPORT_SYMBOL_GPL(kthread_affine_preferred); 893 893 894 - /* 895 - * Re-affine kthreads according to their preferences 896 - * and the newly online CPU. The CPU down part is handled 897 - * by select_fallback_rq() which default re-affines to 898 - * housekeepers from other nodes in case the preferred 899 - * affinity doesn't apply anymore. 900 - */ 901 - static int kthreads_online_cpu(unsigned int cpu) 894 + static int kthreads_update_affinity(bool force) 902 895 { 903 896 cpumask_var_t affinity; 904 897 struct kthread *k; ··· 917 924 /* 918 925 * Unbound kthreads without preferred affinity are already affine 919 926 * to housekeeping, whether those CPUs are online or not. So no need 920 - * to handle newly online CPUs for them. 927 + * to handle newly online CPUs for them. However housekeeping changes 928 + * have to be applied. 921 929 * 922 930 * But kthreads with a preferred affinity or node are different: 923 931 * if none of their preferred CPUs are online and part of ··· 926 932 * But as soon as one of their preferred CPU becomes online, they must 927 933 * be affine to them. 928 934 */ 929 - if (k->preferred_affinity || k->node != NUMA_NO_NODE) { 935 + if (force || k->preferred_affinity || k->node != NUMA_NO_NODE) { 930 936 kthread_fetch_affinity(k, affinity); 931 937 set_cpus_allowed_ptr(k->task, affinity); 932 938 } ··· 935 941 free_cpumask_var(affinity); 936 942 937 943 return ret; 944 + } 945 + 946 + /** 947 + * kthreads_update_housekeeping - Update kthreads affinity on cpuset change 948 + * 949 + * When cpuset changes a partition type to/from "isolated" or updates related 950 + * cpumasks, propagate the housekeeping cpumask change to preferred kthreads 951 + * affinity. 952 + * 953 + * Returns 0 if successful, -ENOMEM if temporary mask couldn't 954 + * be allocated or -EINVAL in case of internal error. 955 + */ 956 + int kthreads_update_housekeeping(void) 957 + { 958 + return kthreads_update_affinity(true); 959 + } 960 + 961 + /* 962 + * Re-affine kthreads according to their preferences 963 + * and the newly online CPU. The CPU down part is handled 964 + * by select_fallback_rq() which default re-affines to 965 + * housekeepers from other nodes in case the preferred 966 + * affinity doesn't apply anymore. 967 + */ 968 + static int kthreads_online_cpu(unsigned int cpu) 969 + { 970 + return kthreads_update_affinity(false); 938 971 } 939 972 940 973 static int kthreads_init(void)
+3
kernel/sched/isolation.c
··· 156 156 err = tmigr_isolated_exclude_cpumask(isol_mask); 157 157 WARN_ON_ONCE(err < 0); 158 158 159 + err = kthreads_update_housekeeping(); 160 + WARN_ON_ONCE(err < 0); 161 + 159 162 kfree(old); 160 163 161 164 return 0;