Skip to content

Commit 5950a00

Browse files
committed
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}()
2 parents dad9774 + 6f363f5 commit 5950a00

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

kernel/cgroup/cgroup.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,7 +1798,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
17981798
{
17991799
struct cgroup *dcgrp = &dst_root->cgrp;
18001800
struct cgroup_subsys *ss;
1801-
int ssid, i, ret;
1801+
int ssid, ret;
18021802
u16 dfl_disable_ss_mask = 0;
18031803

18041804
lockdep_assert_held(&cgroup_mutex);
@@ -1842,7 +1842,8 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
18421842
struct cgroup_root *src_root = ss->root;
18431843
struct cgroup *scgrp = &src_root->cgrp;
18441844
struct cgroup_subsys_state *css = cgroup_css(scgrp, ss);
1845-
struct css_set *cset;
1845+
struct css_set *cset, *cset_pos;
1846+
struct css_task_iter *it;
18461847

18471848
WARN_ON(!css || cgroup_css(dcgrp, ss));
18481849

@@ -1860,9 +1861,22 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
18601861
css->cgroup = dcgrp;
18611862

18621863
spin_lock_irq(&css_set_lock);
1863-
hash_for_each(css_set_table, i, cset, hlist)
1864+
WARN_ON(!list_empty(&dcgrp->e_csets[ss->id]));
1865+
list_for_each_entry_safe(cset, cset_pos, &scgrp->e_csets[ss->id],
1866+
e_cset_node[ss->id]) {
18641867
list_move_tail(&cset->e_cset_node[ss->id],
18651868
&dcgrp->e_csets[ss->id]);
1869+
/*
1870+
* all css_sets of scgrp together in same order to dcgrp,
1871+
* patch in-flight iterators to preserve correct iteration.
1872+
* since the iterator is always advanced right away and
1873+
* finished when it->cset_pos meets it->cset_head, so only
1874+
* update it->cset_head is enough here.
1875+
*/
1876+
list_for_each_entry(it, &cset->task_iters, iters_node)
1877+
if (it->cset_head == &scgrp->e_csets[ss->id])
1878+
it->cset_head = &dcgrp->e_csets[ss->id];
1879+
}
18661880
spin_unlock_irq(&css_set_lock);
18671881

18681882
if (ss->css_rstat_flush) {

kernel/cgroup/legacy_freezer.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,18 @@ static int freezer_css_online(struct cgroup_subsys_state *css)
108108
struct freezer *freezer = css_freezer(css);
109109
struct freezer *parent = parent_freezer(freezer);
110110

111+
cpus_read_lock();
111112
mutex_lock(&freezer_mutex);
112113

113114
freezer->state |= CGROUP_FREEZER_ONLINE;
114115

115116
if (parent && (parent->state & CGROUP_FREEZING)) {
116117
freezer->state |= CGROUP_FREEZING_PARENT | CGROUP_FROZEN;
117-
static_branch_inc(&freezer_active);
118+
static_branch_inc_cpuslocked(&freezer_active);
118119
}
119120

120121
mutex_unlock(&freezer_mutex);
122+
cpus_read_unlock();
121123
return 0;
122124
}
123125

@@ -132,14 +134,16 @@ static void freezer_css_offline(struct cgroup_subsys_state *css)
132134
{
133135
struct freezer *freezer = css_freezer(css);
134136

137+
cpus_read_lock();
135138
mutex_lock(&freezer_mutex);
136139

137140
if (freezer->state & CGROUP_FREEZING)
138-
static_branch_dec(&freezer_active);
141+
static_branch_dec_cpuslocked(&freezer_active);
139142

140143
freezer->state = 0;
141144

142145
mutex_unlock(&freezer_mutex);
146+
cpus_read_unlock();
143147
}
144148

145149
static void freezer_css_free(struct cgroup_subsys_state *css)

0 commit comments

Comments
 (0)