Workqueues use housekeeping masks (HK_TYPE_WQ and HK_TYPE_DOMAIN) to determine the default affinity for unbound workqueues. Currently, these masks are only applied during early boot.
Register a housekeeping notifier to dynamically update the workqueue unbound cpumask when these housekeeping masks are changed at runtime. This ensures that unbound workqueues are re-affined to the new housekeeping CPUs. Also update wq_isolated_cpumask to reflect the changes in HK_TYPE_DOMAIN. Signed-off-by: Qiliang Yuan <[email protected]> Signed-off-by: Qiliang Yuan <[email protected]> --- kernel/workqueue.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 253311af47c6..b8913935d5e8 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -7913,6 +7913,44 @@ static void __init wq_cpu_intensive_thresh_init(void) * executing the work items yet. Populate the worker pools with the initial * workers and enable future kworker creations. */ +static int wq_housekeeping_reconfigure(struct notifier_block *nb, + unsigned long action, void *data) +{ + if (action == HK_UPDATE_MASK) { + unsigned int type = (unsigned long)data; + + if (type == HK_TYPE_WQ || type == HK_TYPE_DOMAIN) { + cpumask_var_t cpumask; + + if (!alloc_cpumask_var(&cpumask, GFP_KERNEL)) + return NOTIFY_BAD; + + cpumask_copy(cpumask, cpu_possible_mask); + if (!cpumask_empty(housekeeping_cpumask(HK_TYPE_WQ))) + cpumask_and(cpumask, cpumask, housekeeping_cpumask(HK_TYPE_WQ)); + if (!cpumask_empty(housekeeping_cpumask(HK_TYPE_DOMAIN))) + cpumask_and(cpumask, cpumask, housekeeping_cpumask(HK_TYPE_DOMAIN)); + + workqueue_set_unbound_cpumask(cpumask); + + if (type == HK_TYPE_DOMAIN) { + apply_wqattrs_lock(); + cpumask_andnot(wq_isolated_cpumask, cpu_possible_mask, + housekeeping_cpumask(HK_TYPE_DOMAIN)); + apply_wqattrs_unlock(); + } + + free_cpumask_var(cpumask); + } + } + + return NOTIFY_OK; +} + +static struct notifier_block wq_housekeeping_nb = { + .notifier_call = wq_housekeeping_reconfigure, +}; + void __init workqueue_init(void) { struct workqueue_struct *wq; @@ -7964,6 +8002,7 @@ void __init workqueue_init(void) wq_online = true; wq_watchdog_init(); + housekeeping_register_notifier(&wq_housekeeping_nb); } /* -- 2.51.0

