From: Cyrill Gorcunov <gorcunov@gmail.com>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Li Zefan <lizf@cn.fujitsu.com>,
Matt Helsley <matthltc@us.ibm.com>,
Andrey Vagin <avagin@openvz.org>,
Pavel Emelyanov <xemul@parallels.com>, Tejun Heo <tj@kernel.org>
Subject: [RFC] cgroups: freezer -- Allow to attach a task to a frozen cgroup
Date: Mon, 28 Nov 2011 16:08:13 +0400 [thread overview]
Message-ID: <20111128120813.GK1775@moon> (raw)
In checkpoint/restore we need an ability to attach pids to
a frozen cgroup. Thus once pid reaches a frozen cgroup it is
not rejected, but the task get frozen immediately.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
I would really appreciate complains and comments.
include/linux/cgroup.h | 2
kernel/cgroup.c | 6 +-
kernel/cgroup_freezer.c | 119 +++++++++++++++++++++++++++++++++---------------
mm/memcontrol.c | 2
4 files changed, 90 insertions(+), 39 deletions(-)
Index: linux-2.6.git/include/linux/cgroup.h
===================================================================
--- linux-2.6.git.orig/include/linux/cgroup.h
+++ linux-2.6.git/include/linux/cgroup.h
@@ -470,7 +470,7 @@ struct cgroup_subsys {
struct task_struct *tsk);
int (*can_attach_task)(struct cgroup *cgrp, struct task_struct *tsk);
void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
- struct task_struct *tsk);
+ struct cgroup *old_cgrp, struct task_struct *tsk);
void (*pre_attach)(struct cgroup *cgrp);
void (*attach_task)(struct cgroup *cgrp, struct task_struct *tsk);
void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
Index: linux-2.6.git/kernel/cgroup.c
===================================================================
--- linux-2.6.git.orig/kernel/cgroup.c
+++ linux-2.6.git/kernel/cgroup.c
@@ -1884,7 +1884,7 @@ out:
*/
break;
if (ss->cancel_attach)
- ss->cancel_attach(ss, cgrp, tsk);
+ ss->cancel_attach(ss, cgrp, oldcgrp, tsk);
}
}
return retval;
@@ -2178,11 +2178,11 @@ out_cancel_attach:
for_each_subsys(root, ss) {
if (ss == failed_ss) {
if (cancel_failed_ss && ss->cancel_attach)
- ss->cancel_attach(ss, cgrp, leader);
+ ss->cancel_attach(ss, cgrp, oldcgrp, leader);
break;
}
if (ss->cancel_attach)
- ss->cancel_attach(ss, cgrp, leader);
+ ss->cancel_attach(ss, cgrp, oldcgrp, leader);
}
}
/* clean up the array of referenced threads in the group. */
Index: linux-2.6.git/kernel/cgroup_freezer.c
===================================================================
--- linux-2.6.git.orig/kernel/cgroup_freezer.c
+++ linux-2.6.git/kernel/cgroup_freezer.c
@@ -153,39 +153,6 @@ static void freezer_destroy(struct cgrou
kfree(cgroup_freezer(cgroup));
}
-/*
- * The call to cgroup_lock() in the freezer.state write method prevents
- * a write to that file racing against an attach, and hence the
- * can_attach() result will remain valid until the attach completes.
- */
-static int freezer_can_attach(struct cgroup_subsys *ss,
- struct cgroup *new_cgroup,
- struct task_struct *task)
-{
- struct freezer *freezer;
-
- /*
- * Anything frozen can't move or be moved to/from.
- */
-
- freezer = cgroup_freezer(new_cgroup);
- if (freezer->state != CGROUP_THAWED)
- return -EBUSY;
-
- return 0;
-}
-
-static int freezer_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
-{
- rcu_read_lock();
- if (__cgroup_freezing_or_frozen(tsk)) {
- rcu_read_unlock();
- return -EBUSY;
- }
- rcu_read_unlock();
- return 0;
-}
-
static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task)
{
struct freezer *freezer;
@@ -374,14 +341,96 @@ static int freezer_populate(struct cgrou
return cgroup_add_files(cgroup, ss, files, ARRAY_SIZE(files));
}
+static int freezer_task_transition(struct task_struct *task, int state_to)
+{
+ int retval = 0;
+
+ switch (state_to) {
+ case CGROUP_THAWED:
+ thaw_process(task);
+ break;
+ case CGROUP_FROZEN:
+ case CGROUP_FREEZING:
+ if (freeze_task(task, true)) {
+ if (!frozen(task)) {
+ if (!freezing(task) &&
+ !freezer_should_skip(task))
+ retval = -EBUSY;
+ }
+ }
+ break;
+ }
+
+ return retval;
+}
+
+static int freezer_can_attach_task(struct cgroup *cgroup, struct task_struct *task)
+{
+ struct freezer *old_freezer;
+ struct freezer *freezer;
+
+ int goal_state, orig_state;
+ int retval = 0;
+
+ old_freezer = task_freezer(task);
+ freezer = cgroup_freezer(cgroup);
+
+ spin_lock_irq(&freezer->lock);
+
+ if (!spin_trylock_irq(&old_freezer->lock)) {
+ retval = -EBUSY;
+ goto out_unlock_freezer;
+ }
+
+ goal_state = orig_state = CGROUP_THAWED;
+
+ if (freezer->state == CGROUP_FREEZING ||
+ freezer->state == CGROUP_FROZEN)
+ goal_state = CGROUP_FREEZING;
+
+ if (old_freezer->state == CGROUP_FREEZING ||
+ old_freezer->state == CGROUP_FROZEN)
+ orig_state = CGROUP_FREEZING;
+
+ /* Nothing to change */
+ if (orig_state == goal_state)
+ goto done;
+
+ retval = freezer_task_transition(task, goal_state);
+done:
+ spin_unlock_irq(&old_freezer->lock);
+out_unlock_freezer:
+ spin_unlock_irq(&freezer->lock);
+
+ return retval;
+}
+
+static void freezer_cancel_attach(struct cgroup_subsys *ss,
+ struct cgroup *cgroup,
+ struct cgroup *old_cgroup,
+ struct task_struct *task)
+{
+ struct freezer *freezer = cgroup_freezer(old_cgroup);
+ int retval = 0;
+
+ spin_lock_irq(&freezer->lock);
+ retval = freezer_task_transition(task, freezer->state);
+ if (retval)
+ pr_warning("freezer: Can't move task (pid %d) to %s state\n",
+ task_pid_nr(task),
+ freezer_state_strs[freezer->state]);
+ spin_unlock_irq(&freezer->lock);
+}
+
struct cgroup_subsys freezer_subsys = {
.name = "freezer",
.create = freezer_create,
.destroy = freezer_destroy,
.populate = freezer_populate,
.subsys_id = freezer_subsys_id,
- .can_attach = freezer_can_attach,
- .can_attach_task = freezer_can_attach_task,
+ .can_attach = NULL,
+ .can_attach_task= freezer_can_attach_task,
+ .cancel_attach = freezer_cancel_attach,
.pre_attach = NULL,
.attach_task = NULL,
.attach = NULL,
Index: linux-2.6.git/mm/memcontrol.c
===================================================================
--- linux-2.6.git.orig/mm/memcontrol.c
+++ linux-2.6.git/mm/memcontrol.c
@@ -5337,6 +5337,7 @@ static int mem_cgroup_can_attach(struct
static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
struct cgroup *cgroup,
+ struct cgroup *old_cgroup,
struct task_struct *p)
{
mem_cgroup_clear_mc();
@@ -5477,6 +5478,7 @@ static int mem_cgroup_can_attach(struct
}
static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
struct cgroup *cgroup,
+ struct cgroup *old_cgroup,
struct task_struct *p)
{
}
next reply other threads:[~2011-11-28 12:08 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-11-28 12:08 Cyrill Gorcunov [this message]
2011-11-28 13:10 ` [RFC] cgroups: freezer -- Allow to attach a task to a frozen cgroup Andrey Vagin
2011-11-28 13:38 ` Cyrill Gorcunov
2011-11-28 14:03 ` Andrew Vagin
2011-11-28 15:00 ` Cyrill Gorcunov
2011-11-28 15:43 ` Andrew Wagin
2011-11-28 16:08 ` Tejun Heo
2011-11-28 16:31 ` Cyrill Gorcunov
2011-11-29 22:58 ` Matt Helsley
2011-11-29 23:19 ` Tejun Heo
2011-11-30 6:48 ` Cyrill Gorcunov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20111128120813.GK1775@moon \
--to=gorcunov@gmail.com \
--cc=avagin@openvz.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lizf@cn.fujitsu.com \
--cc=matthltc@us.ibm.com \
--cc=tj@kernel.org \
--cc=xemul@parallels.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.