mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
cgroup: Merge branch 'for-6.17-fixes' into for-6.18
Pull for-6.17-fixes to receive79f919a89c("cgroup: split cgroup_destroy_wq into 3 workqueues") to resolve its conflict with7fa33aa3b0("cgroup: WQ_PERCPU added to alloc_workqueue users"). The latter adds WQ_PERCPU when creating cgroup_destroy_wq and the former splits the workqueue into three. Resolve by applying WQ_PERCPU to the three split workqueues. Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
commit
4a3e62dfa7
|
|
@ -435,8 +435,8 @@ both cgroups.
|
|||
Controlling Controllers
|
||||
-----------------------
|
||||
|
||||
Availablity
|
||||
~~~~~~~~~~~
|
||||
Availability
|
||||
~~~~~~~~~~~~
|
||||
|
||||
A controller is available in a cgroup when it is supported by the kernel (i.e.,
|
||||
compiled in, not disabled and not attached to a v1 hierarchy) and listed in the
|
||||
|
|
|
|||
|
|
@ -126,8 +126,31 @@ DEFINE_PERCPU_RWSEM(cgroup_threadgroup_rwsem);
|
|||
* of concurrent destructions. Use a separate workqueue so that cgroup
|
||||
* destruction work items don't end up filling up max_active of system_percpu_wq
|
||||
* which may lead to deadlock.
|
||||
*
|
||||
* A cgroup destruction should enqueue work sequentially to:
|
||||
* cgroup_offline_wq: use for css offline work
|
||||
* cgroup_release_wq: use for css release work
|
||||
* cgroup_free_wq: use for free work
|
||||
*
|
||||
* Rationale for using separate workqueues:
|
||||
* The cgroup root free work may depend on completion of other css offline
|
||||
* operations. If all tasks were enqueued to a single workqueue, this could
|
||||
* create a deadlock scenario where:
|
||||
* - Free work waits for other css offline work to complete.
|
||||
* - But other css offline work is queued after free work in the same queue.
|
||||
*
|
||||
* Example deadlock scenario with single workqueue (cgroup_destroy_wq):
|
||||
* 1. umount net_prio
|
||||
* 2. net_prio root destruction enqueues work to cgroup_destroy_wq (CPUx)
|
||||
* 3. perf_event CSS A offline enqueues work to same cgroup_destroy_wq (CPUx)
|
||||
* 4. net_prio cgroup_destroy_root->cgroup_lock_and_drain_offline.
|
||||
* 5. net_prio root destruction blocks waiting for perf_event CSS A offline,
|
||||
* which can never complete as it's behind in the same queue and
|
||||
* workqueue's max_active is 1.
|
||||
*/
|
||||
static struct workqueue_struct *cgroup_destroy_wq;
|
||||
static struct workqueue_struct *cgroup_offline_wq;
|
||||
static struct workqueue_struct *cgroup_release_wq;
|
||||
static struct workqueue_struct *cgroup_free_wq;
|
||||
|
||||
/* generate an array of cgroup subsystem pointers */
|
||||
#define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys,
|
||||
|
|
@ -4173,6 +4196,7 @@ static void cgroup_file_release(struct kernfs_open_file *of)
|
|||
cft->release(of);
|
||||
put_cgroup_ns(ctx->ns);
|
||||
kfree(ctx);
|
||||
of->priv = NULL;
|
||||
}
|
||||
|
||||
static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
|
||||
|
|
@ -5577,7 +5601,7 @@ static void css_release_work_fn(struct work_struct *work)
|
|||
cgroup_unlock();
|
||||
|
||||
INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
|
||||
queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
|
||||
queue_rcu_work(cgroup_free_wq, &css->destroy_rwork);
|
||||
}
|
||||
|
||||
static void css_release(struct percpu_ref *ref)
|
||||
|
|
@ -5586,7 +5610,7 @@ static void css_release(struct percpu_ref *ref)
|
|||
container_of(ref, struct cgroup_subsys_state, refcnt);
|
||||
|
||||
INIT_WORK(&css->destroy_work, css_release_work_fn);
|
||||
queue_work(cgroup_destroy_wq, &css->destroy_work);
|
||||
queue_work(cgroup_release_wq, &css->destroy_work);
|
||||
}
|
||||
|
||||
static void init_and_link_css(struct cgroup_subsys_state *css,
|
||||
|
|
@ -5720,7 +5744,7 @@ static struct cgroup_subsys_state *css_create(struct cgroup *cgrp,
|
|||
list_del_rcu(&css->sibling);
|
||||
err_free_css:
|
||||
INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
|
||||
queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
|
||||
queue_rcu_work(cgroup_free_wq, &css->destroy_rwork);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
|
|
@ -5960,7 +5984,7 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
|
|||
|
||||
if (atomic_dec_and_test(&css->online_cnt)) {
|
||||
INIT_WORK(&css->destroy_work, css_killed_work_fn);
|
||||
queue_work(cgroup_destroy_wq, &css->destroy_work);
|
||||
queue_work(cgroup_offline_wq, &css->destroy_work);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6346,8 +6370,14 @@ static int __init cgroup_wq_init(void)
|
|||
* We would prefer to do this in cgroup_init() above, but that
|
||||
* is called before init_workqueues(): so leave this until after.
|
||||
*/
|
||||
cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", WQ_PERCPU, 1);
|
||||
BUG_ON(!cgroup_destroy_wq);
|
||||
cgroup_offline_wq = alloc_workqueue("cgroup_offline", WQ_PERCPU, 1);
|
||||
BUG_ON(!cgroup_offline_wq);
|
||||
|
||||
cgroup_release_wq = alloc_workqueue("cgroup_release", WQ_PERCPU, 1);
|
||||
BUG_ON(!cgroup_release_wq);
|
||||
|
||||
cgroup_free_wq = alloc_workqueue("cgroup_free", WQ_PERCPU, 1);
|
||||
BUG_ON(!cgroup_free_wq);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(cgroup_wq_init);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user