While workqueue.default_affinity_scope is writable, it only affects workqueues which are created afterwards and isn't very useful. Instead, let's introduce explicit "default" scope and update the effective scope dynamically when workqueue.default_affinity_scope is changed.
Showing the changes to kernel/workqueue.c (1 of 4 files). Show all
Unified · Split
| @@ -339,9 +339,10 @@ struct wq_pod_type { · 338 unmodified lines | |||
| 339 | }; | 339 | }; |
| 340 | 340 | ||
| 341 | static struct wq_pod_type wq_pod_types[WQ_AFFN_NR_TYPES]; | 341 | static struct wq_pod_type wq_pod_types[WQ_AFFN_NR_TYPES]; |
| 342 | static enum wq_affn_scope wq_affn_dfl = WQ_AFFN_DFL; | 342 | static enum wq_affn_scope wq_affn_dfl = WQ_AFFN_CACHE; |
| 343 | 343 | ||
| 344 | static const char *wq_affn_names[WQ_AFFN_NR_TYPES] = { | 344 | static const char *wq_affn_names[WQ_AFFN_NR_TYPES] = { |
| 345 | [WQ_AFFN_DFL] = "default", | ||
| 345 | [WQ_AFFN_CPU] = "cpu", | 346 | [WQ_AFFN_CPU] = "cpu", |
| 346 | [WQ_AFFN_SMT] = "smt", | 347 | [WQ_AFFN_SMT] = "smt", |
| 347 | [WQ_AFFN_CACHE] = "cache", | 348 | [WQ_AFFN_CACHE] = "cache", |
| @@ -3734,7 +3735,7 @@ struct workqueue_attrs *alloc_workqueue_attrs(void) · 3386 unmodified lines | |||
| 3734 | goto fail; | 3735 | goto fail; |
| 3735 | 3736 | ||
| 3736 | cpumask_copy(attrs->cpumask, cpu_possible_mask); | 3737 | cpumask_copy(attrs->cpumask, cpu_possible_mask); |
| 3737 | attrs->affn_scope = wq_affn_dfl; | 3738 | attrs->affn_scope = WQ_AFFN_DFL; |
| 3738 | return attrs; | 3739 | return attrs; |
| 3739 | fail: | 3740 | fail: |
| 3740 | free_workqueue_attrs(attrs); | 3741 | free_workqueue_attrs(attrs); |
| @@ -3815,7 +3816,18 @@ static void wqattrs_actualize_cpumask(struct workqueue_attrs *attrs, · 74 unmodified lines | |||
| 3815 | static const struct wq_pod_type * | 3816 | static const struct wq_pod_type * |
| 3816 | wqattrs_pod_type(const struct workqueue_attrs *attrs) | 3817 | wqattrs_pod_type(const struct workqueue_attrs *attrs) |
| 3817 | { | 3818 | { |
| 3818 | struct wq_pod_type *pt = &wq_pod_types[attrs->affn_scope]; | 3819 | enum wq_affn_scope scope; |
| 3820 | struct wq_pod_type *pt; | ||
| 3821 | |||
| 3822 | /* to synchronize access to wq_affn_dfl */ | ||
| 3823 | lockdep_assert_held(&wq_pool_mutex); | ||
| 3824 | |||
| 3825 | if (attrs->affn_scope == WQ_AFFN_DFL) | ||
| 3826 | scope = wq_affn_dfl; | ||
| 3827 | else | ||
| 3828 | scope = attrs->affn_scope; | ||
| 3829 | |||
| 3830 | pt = &wq_pod_types[scope]; | ||
| 3819 | 3831 | ||
| 3820 | if (!WARN_ON_ONCE(attrs->affn_scope == WQ_AFFN_NR_TYPES) && | 3832 | if (!WARN_ON_ONCE(attrs->affn_scope == WQ_AFFN_NR_TYPES) && |
| 3821 | likely(pt->nr_pods)) | 3833 | likely(pt->nr_pods)) |
| @@ -5847,13 +5859,29 @@ static int parse_affn_scope(const char *val) · 2025 unmodified lines | |||
| 5847 | 5859 | ||
| 5848 | static int wq_affn_dfl_set(const char *val, const struct kernel_param *kp) | 5860 | static int wq_affn_dfl_set(const char *val, const struct kernel_param *kp) |
| 5849 | { | 5861 | { |
| 5850 | int affn; | 5862 | struct workqueue_struct *wq; |
| 5863 | int affn, cpu; | ||
| 5851 | 5864 | ||
| 5852 | affn = parse_affn_scope(val); | 5865 | affn = parse_affn_scope(val); |
| 5853 | if (affn < 0) | 5866 | if (affn < 0) |
| 5854 | return affn; | 5867 | return affn; |
| 5868 | if (affn == WQ_AFFN_DFL) | ||
| 5869 | return -EINVAL; | ||
| 5870 | |||
| 5871 | cpus_read_lock(); | ||
| 5872 | mutex_lock(&wq_pool_mutex); | ||
| 5855 | 5873 | ||
| 5856 | wq_affn_dfl = affn; | 5874 | wq_affn_dfl = affn; |
| 5875 | |||
| 5876 | list_for_each_entry(wq, &workqueues, list) { | ||
| 5877 | for_each_online_cpu(cpu) { | ||
| 5878 | wq_update_pod(wq, cpu, cpu, true); | ||
| 5879 | } | ||
| 5880 | } | ||
| 5881 | |||
| 5882 | mutex_unlock(&wq_pool_mutex); | ||
| 5883 | cpus_read_unlock(); | ||
| 5884 | |||
| 5857 | return 0; | 5885 | return 0; |
| 5858 | } | 5886 | } |
| 5859 | 5887 | ||
| @@ -6033,8 +6061,13 @@ static ssize_t wq_affn_scope_show(struct device *dev, · 173 unmodified lines | |||
| 6033 | int written; | 6061 | int written; |
| 6034 | 6062 | ||
| 6035 | mutex_lock(&wq->mutex); | 6063 | mutex_lock(&wq->mutex); |
| 6036 | written = scnprintf(buf, PAGE_SIZE, "%s\n", | 6064 | if (wq->unbound_attrs->affn_scope == WQ_AFFN_DFL) |
| 6037 | wq_affn_names[wq->unbound_attrs->affn_scope]); | 6065 | written = scnprintf(buf, PAGE_SIZE, "%s (%s)\n", |
| 6066 | wq_affn_names[WQ_AFFN_DFL], | ||
| 6067 | wq_affn_names[wq_affn_dfl]); | ||
| 6068 | else | ||
| 6069 | written = scnprintf(buf, PAGE_SIZE, "%s\n", | ||
| 6070 | wq_affn_names[wq->unbound_attrs->affn_scope]); | ||
| 6038 | mutex_unlock(&wq->mutex); | 6071 | mutex_unlock(&wq->mutex); |
| 6039 | 6072 | ||
| 6040 | return written; | 6073 | return written; |