* [PATCH cgroup/for-3.19 1/3] cgroup: separate out cgroup_calc_child_subsys_mask() from cgroup_refresh_child_subsys_mask()
@ 2014-11-13 21:58 Tejun Heo
2014-11-13 21:58 ` [PATCH cgroup/for-3.19 2/3] cgroup: restructure child_subsys_mask handling in cgroup_subtree_control_write() Tejun Heo
0 siblings, 1 reply; 5+ messages in thread
From: Tejun Heo @ 2014-11-13 21:58 UTC (permalink / raw)
To: Li Zefan; +Cc: cgroups, linux-kernel
cgroup_refresh_child_subsys_mask() calculates and updates the
effective @cgrp->child_subsys_maks according to the current
@cgrp->subtree_control. Separate out the calculation part into
cgroup_calc_child_subsys_mask(). This will be used to fix a bug in
the async css offline wait logic.
Signed-off-by: Tejun Heo <tj@kernel.org>
---
kernel/cgroup.c | 36 ++++++++++++++++++++++++------------
1 file changed, 24 insertions(+), 12 deletions(-)
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1019,31 +1019,30 @@ static void cgroup_put(struct cgroup *cg
}
/**
- * cgroup_refresh_child_subsys_mask - update child_subsys_mask
+ * cgroup_calc_child_subsys_mask - calculate child_subsys_mask
* @cgrp: the target cgroup
+ * @subtree_control: the new subtree_control mask to consider
*
* On the default hierarchy, a subsystem may request other subsystems to be
* enabled together through its ->depends_on mask. In such cases, more
* subsystems than specified in "cgroup.subtree_control" may be enabled.
*
- * This function determines which subsystems need to be enabled given the
- * current @cgrp->subtree_control and records it in
- * @cgrp->child_subsys_mask. The resulting mask is always a superset of
- * @cgrp->subtree_control and follows the usual hierarchy rules.
+ * This function calculates which subsystems need to be enabled if
+ * @subtree_control is to be applied to @cgrp. The returned mask is always
+ * a superset of @subtree_control and follows the usual hierarchy rules.
*/
-static void cgroup_refresh_child_subsys_mask(struct cgroup *cgrp)
+static unsigned int cgroup_calc_child_subsys_mask(struct cgroup *cgrp,
+ unsigned int subtree_control)
{
struct cgroup *parent = cgroup_parent(cgrp);
- unsigned int cur_ss_mask = cgrp->subtree_control;
+ unsigned int cur_ss_mask = subtree_control;
struct cgroup_subsys *ss;
int ssid;
lockdep_assert_held(&cgroup_mutex);
- if (!cgroup_on_dfl(cgrp)) {
- cgrp->child_subsys_mask = cur_ss_mask;
- return;
- }
+ if (!cgroup_on_dfl(cgrp))
+ return cur_ss_mask;
while (true) {
unsigned int new_ss_mask = cur_ss_mask;
@@ -1067,7 +1066,20 @@ static void cgroup_refresh_child_subsys_
cur_ss_mask = new_ss_mask;
}
- cgrp->child_subsys_mask = cur_ss_mask;
+ return cur_ss_mask;
+}
+
+/**
+ * cgroup_refresh_child_subsys_mask - update child_subsys_mask
+ * @cgrp: the target cgroup
+ *
+ * Update @cgrp->child_subsys_mask according to the current
+ * @cgrp->subtree_control using cgroup_calc_child_subsys_mask().
+ */
+static void cgroup_refresh_child_subsys_mask(struct cgroup *cgrp)
+{
+ cgrp->child_subsys_mask =
+ cgroup_calc_child_subsys_mask(cgrp, cgrp->subtree_control);
}
/**
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH cgroup/for-3.19 2/3] cgroup: restructure child_subsys_mask handling in cgroup_subtree_control_write()
2014-11-13 21:58 [PATCH cgroup/for-3.19 1/3] cgroup: separate out cgroup_calc_child_subsys_mask() from cgroup_refresh_child_subsys_mask() Tejun Heo
@ 2014-11-13 21:58 ` Tejun Heo
[not found] ` <20141113215848.GB2598-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Tejun Heo @ 2014-11-13 21:58 UTC (permalink / raw)
To: Li Zefan; +Cc: cgroups, linux-kernel
Make cgroup_subtree_control_write() first calculate new
subtree_control (new_sc), child_subsys_mask (new_ss) and
css_enable/disable masks before applying them to the cgroup. Also,
store the original subtree_control (old_sc) and child_subsys_mask
(old_ss) and use them to restore the orignal state after failure.
This patch shouldn't cause any behavior changes. This prepares for a
fix for a bug in the async css offline wait logic.
Signed-off-by: Tejun Heo <tj@kernel.org>
---
kernel/cgroup.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2653,7 +2653,7 @@ static ssize_t cgroup_subtree_control_wr
loff_t off)
{
unsigned int enable = 0, disable = 0;
- unsigned int css_enable, css_disable, old_ctrl, new_ctrl;
+ unsigned int css_enable, css_disable, old_sc, new_sc, old_ss, new_ss;
struct cgroup *cgrp, *child;
struct cgroup_subsys *ss;
char *tok;
@@ -2770,18 +2770,19 @@ static ssize_t cgroup_subtree_control_wr
* subsystems than specified may need to be enabled or disabled
* depending on subsystem dependencies.
*/
- cgrp->subtree_control |= enable;
- cgrp->subtree_control &= ~disable;
+ old_sc = cgrp->subtree_control;
+ old_ss = cgrp->child_subsys_mask;
+ new_sc = (old_sc | enable) & ~disable;
+ new_ss = cgroup_calc_child_subsys_mask(cgrp, new_sc);
- old_ctrl = cgrp->child_subsys_mask;
- cgroup_refresh_child_subsys_mask(cgrp);
- new_ctrl = cgrp->child_subsys_mask;
-
- css_enable = ~old_ctrl & new_ctrl;
- css_disable = old_ctrl & ~new_ctrl;
+ css_enable = ~old_ss & new_ss;
+ css_disable = old_ss & ~new_ss;
enable |= css_enable;
disable |= css_disable;
+ cgrp->subtree_control = new_sc;
+ cgrp->child_subsys_mask = new_ss;
+
/*
* Create new csses or make the existing ones visible. A css is
* created invisible if it's being implicitly enabled through
@@ -2844,9 +2845,8 @@ out_unlock:
return ret ?: nbytes;
err_undo_css:
- cgrp->subtree_control &= ~enable;
- cgrp->subtree_control |= disable;
- cgroup_refresh_child_subsys_mask(cgrp);
+ cgrp->subtree_control = old_sc;
+ cgrp->child_subsys_mask = old_ss;
for_each_subsys(ss, ssid) {
if (!(enable & (1 << ssid)))
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH cgroup/for-3.19 3/3] cgroup: fix the async css offline wait logic in cgroup_subtree_control_write()
[not found] ` <20141113215848.GB2598-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
@ 2014-11-13 21:59 ` Tejun Heo
[not found] ` <20141113215921.GC2598-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Tejun Heo @ 2014-11-13 21:59 UTC (permalink / raw)
To: Li Zefan
Cc: cgroups-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
When a subsystem is offlined, its entry on @cgrp->subsys[] is cleared
asynchronously. If cgroup_subtree_control_write() is requested to
enable the subsystem again before the entry is cleared, it has to wait
for the previous offlining to finish and clear the @cgrp->subsys[]
entry before trying to enable the subsystem again.
This is currently done while verifying the input enable / disable
parameters. This used to be correct but f63070d350e3 ("cgroup: make
interface files visible iff enabled on cgroup->subtree_control")
breaks it. The commit is one of the commits implementing subsystem
dependency.
Through subsystem dependency, some subsystems may be enabled and
disabled implicitly in addition to the explicitly requested ones. The
actual subsystems to be enabled and disabled are determined during
@css_enable/disable calculation. The current offline wait logic skips
the ones which are already implicitly enabled and then waits for
subsystems in @enable; however, this misses the subsystems which may
be implicitly enabled through dependency from @enable. If such
implicitly subsystem hasn't yet finished offlining yet, the function
ends up trying to create a css when its @cgrp->subsys[] slot is
already occupied triggering BUG_ON() in init_and_link_css().
Fix it by moving the wait logic after @css_enable is calculated and
waiting for all the subsystems in @css_enable. This fixes the above
bug as the mask contains all subsystems which are to be enabled
including the ones enabled through dependencies.
Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Fixes: f63070d350e3 ("cgroup: make interface files visible iff enabled on cgroup->subtree_control")
---
kernel/cgroup.c | 58 +++++++++++++++++++++++++++-----------------------------
1 file changed, 28 insertions(+), 30 deletions(-)
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2705,36 +2705,6 @@ static ssize_t cgroup_subtree_control_wr
ret = -ENOENT;
goto out_unlock;
}
-
- /*
- * @ss is already enabled through dependency and
- * we'll just make it visible. Skip draining.
- */
- if (cgrp->child_subsys_mask & (1 << ssid))
- continue;
-
- /*
- * Because css offlining is asynchronous, userland
- * might try to re-enable the same controller while
- * the previous instance is still around. In such
- * cases, wait till it's gone using offline_waitq.
- */
- cgroup_for_each_live_child(child, cgrp) {
- DEFINE_WAIT(wait);
-
- if (!cgroup_css(child, ss))
- continue;
-
- cgroup_get(child);
- prepare_to_wait(&child->offline_waitq, &wait,
- TASK_UNINTERRUPTIBLE);
- cgroup_kn_unlock(of->kn);
- schedule();
- finish_wait(&child->offline_waitq, &wait);
- cgroup_put(child);
-
- return restart_syscall();
- }
} else if (disable & (1 << ssid)) {
if (!(cgrp->subtree_control & (1 << ssid))) {
disable &= ~(1 << ssid);
@@ -2780,6 +2750,34 @@ static ssize_t cgroup_subtree_control_wr
enable |= css_enable;
disable |= css_disable;
+ /*
+ * Because css offlining is asynchronous, userland might try to
+ * re-enable the same controller while the previous instance is
+ * still around. In such cases, wait till it's gone using
+ * offline_waitq.
+ */
+ for_each_subsys(ss, ssid) {
+ if (!(css_enable & (1 << ssid)))
+ continue;
+
+ cgroup_for_each_live_child(child, cgrp) {
+ DEFINE_WAIT(wait);
+
+ if (!cgroup_css(child, ss))
+ continue;
+
+ cgroup_get(child);
+ prepare_to_wait(&child->offline_waitq, &wait,
+ TASK_UNINTERRUPTIBLE);
+ cgroup_kn_unlock(of->kn);
+ schedule();
+ finish_wait(&child->offline_waitq, &wait);
+ cgroup_put(child);
+
+ return restart_syscall();
+ }
+ }
+
cgrp->subtree_control = new_sc;
cgrp->child_subsys_mask = new_ss;
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH cgroup/for-3.19 3/3] cgroup: fix the async css offline wait logic in cgroup_subtree_control_write()
[not found] ` <20141113215921.GC2598-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
@ 2014-11-18 6:30 ` Zefan Li
[not found] ` <546AE794.5070902-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Zefan Li @ 2014-11-18 6:30 UTC (permalink / raw)
To: Tejun Heo
Cc: cgroups-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On 2014/11/14 5:59, Tejun Heo wrote:
> When a subsystem is offlined, its entry on @cgrp->subsys[] is cleared
> asynchronously. If cgroup_subtree_control_write() is requested to
> enable the subsystem again before the entry is cleared, it has to wait
> for the previous offlining to finish and clear the @cgrp->subsys[]
> entry before trying to enable the subsystem again.
>
> This is currently done while verifying the input enable / disable
> parameters. This used to be correct but f63070d350e3 ("cgroup: make
> interface files visible iff enabled on cgroup->subtree_control")
> breaks it. The commit is one of the commits implementing subsystem
> dependency.
>
> Through subsystem dependency, some subsystems may be enabled and
> disabled implicitly in addition to the explicitly requested ones. The
> actual subsystems to be enabled and disabled are determined during
> @css_enable/disable calculation. The current offline wait logic skips
> the ones which are already implicitly enabled and then waits for
> subsystems in @enable; however, this misses the subsystems which may
> be implicitly enabled through dependency from @enable. If such
> implicitly subsystem hasn't yet finished offlining yet, the function
> ends up trying to create a css when its @cgrp->subsys[] slot is
> already occupied triggering BUG_ON() in init_and_link_css().
>
> Fix it by moving the wait logic after @css_enable is calculated and
> waiting for all the subsystems in @css_enable. This fixes the above
> bug as the mask contains all subsystems which are to be enabled
> including the ones enabled through dependencies.
>
> Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Fixes: f63070d350e3 ("cgroup: make interface files visible iff enabled on cgroup->subtree_control")
For all 3 patches:
Acked-by: Zefan Li <lizefan-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH cgroup/for-3.19 3/3] cgroup: fix the async css offline wait logic in cgroup_subtree_control_write()
[not found] ` <546AE794.5070902-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
@ 2014-11-18 7:50 ` Tejun Heo
0 siblings, 0 replies; 5+ messages in thread
From: Tejun Heo @ 2014-11-18 7:50 UTC (permalink / raw)
To: Zefan Li
Cc: cgroups-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Tue, Nov 18, 2014 at 02:30:44PM +0800, Zefan Li wrote:
> For all 3 patches:
>
> Acked-by: Zefan Li <lizefan-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Applied 1-3 to cgroup/for-3.19.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2014-11-18 7:50 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-13 21:58 [PATCH cgroup/for-3.19 1/3] cgroup: separate out cgroup_calc_child_subsys_mask() from cgroup_refresh_child_subsys_mask() Tejun Heo
2014-11-13 21:58 ` [PATCH cgroup/for-3.19 2/3] cgroup: restructure child_subsys_mask handling in cgroup_subtree_control_write() Tejun Heo
[not found] ` <20141113215848.GB2598-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
2014-11-13 21:59 ` [PATCH cgroup/for-3.19 3/3] cgroup: fix the async css offline wait logic " Tejun Heo
[not found] ` <20141113215921.GC2598-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
2014-11-18 6:30 ` Zefan Li
[not found] ` <546AE794.5070902-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
2014-11-18 7:50 ` Tejun Heo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).