History

workqueue: Make default affinity_scope dynamically updatable

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.

Tejun Heo committed 3 years ago

Commit 523a3011 parent 7dbf15c4 files · +52 −13Browse files

Showing the changes to kernel/workqueue.c (1 of 4 files). Show all

Unified · Split

kernel/workqueue.c+39−6
@@ -339,9 +339,10 @@ struct wq_pod_type { · 338 unmodified lines
339339 };
340340
341341 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;
343343
344344 static const char *wq_affn_names[WQ_AFFN_NR_TYPES] = {
345+ [WQ_AFFN_DFL] = "default",
345346 [WQ_AFFN_CPU] = "cpu",
346347 [WQ_AFFN_SMT] = "smt",
347348 [WQ_AFFN_CACHE] = "cache",
@@ -3734,7 +3735,7 @@ struct workqueue_attrs *alloc_workqueue_attrs(void) · 3386 unmodified lines
37343735 goto fail;
37353736
37363737 cpumask_copy(attrs->cpumask, cpu_possible_mask);
3737− attrs->affn_scope = wq_affn_dfl;
3738+ attrs->affn_scope = WQ_AFFN_DFL;
37383739 return attrs;
37393740 fail:
37403741 free_workqueue_attrs(attrs);
@@ -3815,7 +3816,18 @@ static void wqattrs_actualize_cpumask(struct workqueue_attrs *attrs, · 74 unmodified lines
38153816 static const struct wq_pod_type *
38163817 wqattrs_pod_type(const struct workqueue_attrs *attrs)
38173818 {
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];
38193831
38203832 if (!WARN_ON_ONCE(attrs->affn_scope == WQ_AFFN_NR_TYPES) &&
38213833 likely(pt->nr_pods))
@@ -5847,13 +5859,29 @@ static int parse_affn_scope(const char *val) · 2025 unmodified lines
58475859
58485860 static int wq_affn_dfl_set(const char *val, const struct kernel_param *kp)
58495861 {
5850− int affn;
5862+ struct workqueue_struct *wq;
5863+ int affn, cpu;
58515864
58525865 affn = parse_affn_scope(val);
58535866 if (affn < 0)
58545867 return affn;
5868+ if (affn == WQ_AFFN_DFL)
5869+ return -EINVAL;
5870+
5871+ cpus_read_lock();
5872+ mutex_lock(&wq_pool_mutex);
58555873
58565874 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+
58575885 return 0;
58585886 }
58595887
@@ -6033,8 +6061,13 @@ static ssize_t wq_affn_scope_show(struct device *dev, · 173 unmodified lines
60336061 int written;
60346062
60356063 mutex_lock(&wq->mutex);
6036− written = scnprintf(buf, PAGE_SIZE, "%s\n",
6037− wq_affn_names[wq->unbound_attrs->affn_scope]);
6064+ if (wq->unbound_attrs->affn_scope == WQ_AFFN_DFL)
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]);
60386071 mutex_unlock(&wq->mutex);
60396072
60406073 return written;