cgroup: Fixes for v6.4-rc7
It's late but here are two bug fixes. Both fix problems which can be severe but are very confined in scope. The risk to most use cases should be minimal. * Fix for an old bug which triggers if a cgroup subsystem is remounted to a different hierarchy while someone is reading its cgroup.procs/tasks file. The risk is pretty low given how seldom cgroup subsystems are moved across hierarchies. * We moved cpus_read_lock() outside of cgroup internal locks a while ago but forgot to update the legacy_freezer leading to lockdep triggers. Fixed. -----BEGIN PGP SIGNATURE----- iIQEABYIACwWIQTfIjM1kS57o3GsC/uxYfJx3gVYGQUCZJNz6g4cdGpAa2VybmVs Lm9yZwAKCRCxYfJx3gVYGS9zAP9lGszI1Zgvjz+qlU0dmE96yUEuqEg7Tfwcqxr3 Y+hHyAEArgNGnCoPfu4NAWQDZ31AgPUdL8EFqx6pY9Vq9R0oFg0= =uaB+ -----END PGP SIGNATURE----- Merge tag 'cgroup-for-6.4-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup Pull cgroup fixes from Tejun Heo: "It's late but here are two bug fixes. Both fix problems which can be severe but are very confined in scope. The risk to most use cases should be minimal. - Fix for an old bug which triggers if a cgroup subsystem is remounted to a different hierarchy while someone is reading its cgroup.procs/tasks file. The risk is pretty low given how seldom cgroup subsystems are moved across hierarchies. - We moved cpus_read_lock() outside of cgroup internal locks a while ago but forgot to update the legacy_freezer leading to lockdep triggers. Fixed" * tag 'cgroup-for-6.4-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup: Do not corrupt task iteration when rebinding subsystem cgroup,freezer: hold cpu_hotplug_lock before freezer_mutex in freezer_css_{online,offline}()
This commit is contained in:
commit
5950a0066f
|
@ -1798,7 +1798,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
|
|||
{
|
||||
struct cgroup *dcgrp = &dst_root->cgrp;
|
||||
struct cgroup_subsys *ss;
|
||||
int ssid, i, ret;
|
||||
int ssid, ret;
|
||||
u16 dfl_disable_ss_mask = 0;
|
||||
|
||||
lockdep_assert_held(&cgroup_mutex);
|
||||
|
@ -1842,7 +1842,8 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
|
|||
struct cgroup_root *src_root = ss->root;
|
||||
struct cgroup *scgrp = &src_root->cgrp;
|
||||
struct cgroup_subsys_state *css = cgroup_css(scgrp, ss);
|
||||
struct css_set *cset;
|
||||
struct css_set *cset, *cset_pos;
|
||||
struct css_task_iter *it;
|
||||
|
||||
WARN_ON(!css || cgroup_css(dcgrp, ss));
|
||||
|
||||
|
@ -1860,9 +1861,22 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
|
|||
css->cgroup = dcgrp;
|
||||
|
||||
spin_lock_irq(&css_set_lock);
|
||||
hash_for_each(css_set_table, i, cset, hlist)
|
||||
WARN_ON(!list_empty(&dcgrp->e_csets[ss->id]));
|
||||
list_for_each_entry_safe(cset, cset_pos, &scgrp->e_csets[ss->id],
|
||||
e_cset_node[ss->id]) {
|
||||
list_move_tail(&cset->e_cset_node[ss->id],
|
||||
&dcgrp->e_csets[ss->id]);
|
||||
/*
|
||||
* all css_sets of scgrp together in same order to dcgrp,
|
||||
* patch in-flight iterators to preserve correct iteration.
|
||||
* since the iterator is always advanced right away and
|
||||
* finished when it->cset_pos meets it->cset_head, so only
|
||||
* update it->cset_head is enough here.
|
||||
*/
|
||||
list_for_each_entry(it, &cset->task_iters, iters_node)
|
||||
if (it->cset_head == &scgrp->e_csets[ss->id])
|
||||
it->cset_head = &dcgrp->e_csets[ss->id];
|
||||
}
|
||||
spin_unlock_irq(&css_set_lock);
|
||||
|
||||
if (ss->css_rstat_flush) {
|
||||
|
|
|
@ -108,16 +108,18 @@ static int freezer_css_online(struct cgroup_subsys_state *css)
|
|||
struct freezer *freezer = css_freezer(css);
|
||||
struct freezer *parent = parent_freezer(freezer);
|
||||
|
||||
cpus_read_lock();
|
||||
mutex_lock(&freezer_mutex);
|
||||
|
||||
freezer->state |= CGROUP_FREEZER_ONLINE;
|
||||
|
||||
if (parent && (parent->state & CGROUP_FREEZING)) {
|
||||
freezer->state |= CGROUP_FREEZING_PARENT | CGROUP_FROZEN;
|
||||
static_branch_inc(&freezer_active);
|
||||
static_branch_inc_cpuslocked(&freezer_active);
|
||||
}
|
||||
|
||||
mutex_unlock(&freezer_mutex);
|
||||
cpus_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -132,14 +134,16 @@ static void freezer_css_offline(struct cgroup_subsys_state *css)
|
|||
{
|
||||
struct freezer *freezer = css_freezer(css);
|
||||
|
||||
cpus_read_lock();
|
||||
mutex_lock(&freezer_mutex);
|
||||
|
||||
if (freezer->state & CGROUP_FREEZING)
|
||||
static_branch_dec(&freezer_active);
|
||||
static_branch_dec_cpuslocked(&freezer_active);
|
||||
|
||||
freezer->state = 0;
|
||||
|
||||
mutex_unlock(&freezer_mutex);
|
||||
cpus_read_unlock();
|
||||
}
|
||||
|
||||
static void freezer_css_free(struct cgroup_subsys_state *css)
|
||||
|
|
Loading…
Reference in New Issue