From: Matt Helsley <matthltc@us.ibm.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: rjw@sisk.pl, menage@google.com, lizf@cn.fujitsu.com,
linux-kernel@vger.kernel.org,
containers@lists.linux-foundation.org,
linux-pm@lists.linux-foundation.org, clg@fr.ibm.com,
serue@us.ibm.com
Subject: Re: [PATCH 3/5] Container Freezer: Implement freezer cgroup subsystem
Date: Tue, 12 Aug 2008 19:38:08 -0700 [thread overview]
Message-ID: <1218595088.19008.176.camel@localhost.localdomain> (raw)
In-Reply-To: <20080812155610.f4d40bb1.akpm@linux-foundation.org>
On Tue, 2008-08-12 at 15:56 -0700, Andrew Morton wrote:
> On Mon, 11 Aug 2008 16:53:26 -0700
> Matt Helsley <matthltc@us.ibm.com> wrote:
>
> > This patch implements a new freezer subsystem in the control groups framework.
> > It provides a way to stop and resume execution of all tasks in a cgroup by
> > writing in the cgroup filesystem.
> >
> > The freezer subsystem in the container filesystem defines a file named
> > freezer.state. Writing "FROZEN" to the state file will freeze all tasks in the
> > cgroup. Subsequently writing "RUNNING" will unfreeze the tasks in the cgroup.
> > Reading will return the current state.
> >
> > * Examples of usage :
> >
> > # mkdir /containers/freezer
> > # mount -t cgroup -ofreezer freezer /containers
> > # mkdir /containers/0
> > # echo $some_pid > /containers/0/tasks
> >
> > to get status of the freezer subsystem :
> >
> > # cat /containers/0/freezer.state
> > RUNNING
> >
> > to freeze all tasks in the container :
> >
> > # echo FROZEN > /containers/0/freezer.state
> > # cat /containers/0/freezer.state
> > FREEZING
> > # cat /containers/0/freezer.state
> > FROZEN
> >
> > to unfreeze all tasks in the container :
> >
> > # echo RUNNING > /containers/0/freezer.state
> > # cat /containers/0/freezer.state
> > RUNNING
> >
> > This is the basic mechanism which should do the right thing for user space task
> > in a simple scenario.
> >
> > It's important to note that freezing can be incomplete. In that case we return
> > EBUSY. This means that some tasks in the cgroup are busy doing something that
> > prevents us from completely freezing the cgroup at this time. After EBUSY,
> > the cgroup will remain partially frozen -- reflected by freezer.state reporting
> > "FREEZING" when read. The state will remain "FREEZING" until one of these
> > things happens:
> >
> > 1) Userspace cancels the freezing operation by writing "RUNNING" to
> > the freezer.state file
> > 2) Userspace retries the freezing operation by writing "FROZEN" to
> > the freezer.state file (writing "FREEZING" is not legal
> > and returns EIO)
> > 3) The tasks that blocked the cgroup from entering the "FROZEN"
> > state disappear from the cgroup's set of tasks.
> >
> > ...
>
> Is a Documentation/ update planned? Documentation/cgroups.txt might be
> the place, or not.
I'll post a patch for that.
> > +
> > +#ifdef CONFIG_CGROUP_FREEZER
> > +SUBSYS(freezer)
> > +#endif
> > +
> > +/* */
> > Index: linux-2.6.27-rc1-mm1/include/linux/freezer.h
> > ===================================================================
> > --- linux-2.6.27-rc1-mm1.orig/include/linux/freezer.h
> > +++ linux-2.6.27-rc1-mm1/include/linux/freezer.h
> > @@ -47,22 +47,30 @@ static inline bool should_send_signal(st
> > /*
> > * Wake up a frozen process
> > *
> > - * task_lock() is taken to prevent the race with refrigerator() which may
> > + * task_lock() is needed to prevent the race with refrigerator() which may
> > * occur if the freezing of tasks fails. Namely, without the lock, if the
> > * freezing of tasks failed, thaw_tasks() might have run before a task in
> > * refrigerator() could call frozen_process(), in which case the task would be
> > * frozen and no one would thaw it.
> > */
> > -static inline int thaw_process(struct task_struct *p)
> > +static inline int __thaw_process(struct task_struct *p)
> > {
> > - task_lock(p);
> > if (frozen(p)) {
> > p->flags &= ~PF_FROZEN;
> > + return 1;
> > + }
> > + clear_freeze_flag(p);
> > + return 0;
> > +}
> > +
> > +static inline int thaw_process(struct task_struct *p)
> > +{
> > + task_lock(p);
> > + if (__thaw_process(p) == 1) {
> > task_unlock(p);
> > wake_up_process(p);
> > return 1;
> > }
> > - clear_freeze_flag(p);
> > task_unlock(p);
> > return 0;
> > }
>
> I wonder why these are inlined.
I wanted the changes to be obvious. I think uninlining this would be a
separate improvement. I'll post a patch uninlining these.
> > @@ -83,6 +91,12 @@ static inline int try_to_freeze(void)
> > extern bool freeze_task(struct task_struct *p, bool sig_only);
> > extern void cancel_freezing(struct task_struct *p);
> >
> > +#ifdef CONFIG_CGROUP_FREEZER
> > +extern int cgroup_frozen(struct task_struct *task);
> > +#else /* !CONFIG_CGROUP_FREEZER */
> > +static inline int cgroup_frozen(struct task_struct *task) { return 0; }
> > +#endif /* !CONFIG_CGROUP_FREEZER */
> > +
> > /*
> > * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
> > * calls wait_for_completion(&vfork) and reset right after it returns from this
> > Index: linux-2.6.27-rc1-mm1/init/Kconfig
> > ===================================================================
> > --- linux-2.6.27-rc1-mm1.orig/init/Kconfig
> > +++ linux-2.6.27-rc1-mm1/init/Kconfig
> > @@ -299,6 +299,13 @@ config CGROUP_NS
> > for instance virtual servers and checkpoint/restart
> > jobs.
> >
> > +config CGROUP_FREEZER
> > + bool "control group freezer subsystem"
> > + depends on CGROUPS
>
> Should it depend on FREEZER also?
>
> oh,
>
> > --- linux-2.6.27-rc1-mm1.orig/kernel/power/Kconfig
> > +++ linux-2.6.27-rc1-mm1/kernel/power/Kconfig
> > @@ -86,7 +86,7 @@ config PM_SLEEP
> > default y
> >
> > config FREEZER
> > - def_bool PM_SLEEP
> > + def_bool PM_SLEEP || CGROUP_FREEZER
> >
>
> we did it that way. Spose that makes sense.
I did consider a few alternatives for this. Makefile and cpp didn't
seem as nice as this. "select" didn't fit. Using "depends on" does
directly translate the build dependency. However I didn't think it would
be clear to everyone configuring a kernel that they had to enable
"FREEZER" before they could get PM_SLEEP or CGROUP_FREEZER.
Also, Rafael has asked to see this in a kernel/Kconfig file instead
(see his reply to patch 2).
> > + help
> > + Provides a way to freeze and unfreeze all tasks in a
> > + cgroup.
> > +
> > config CGROUP_DEVICE
> > bool "Device controller for cgroups"
> > depends on CGROUPS && EXPERIMENTAL
> > Index: linux-2.6.27-rc1-mm1/kernel/Makefile
> > ===================================================================
> > --- linux-2.6.27-rc1-mm1.orig/kernel/Makefile
> > +++ linux-2.6.27-rc1-mm1/kernel/Makefile
> > @@ -54,6 +54,7 @@ obj-$(CONFIG_KEXEC) += kexec.o
> > obj-$(CONFIG_COMPAT) += compat.o
> > obj-$(CONFIG_CGROUPS) += cgroup.o
> > obj-$(CONFIG_CGROUP_DEBUG) += cgroup_debug.o
> > +obj-$(CONFIG_CGROUP_FREEZER) += cgroup_freezer.o
> > obj-$(CONFIG_CPUSETS) += cpuset.o
> > obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o
> > obj-$(CONFIG_UTS_NS) += utsname.o
> > Index: linux-2.6.27-rc1-mm1/kernel/cgroup_freezer.c
> > ===================================================================
> > --- /dev/null
> > +++ linux-2.6.27-rc1-mm1/kernel/cgroup_freezer.c
> > @@ -0,0 +1,366 @@
> > +/*
> > + * cgroup_freezer.c - control group freezer subsystem
> > + *
> > + * Copyright IBM Corporation, 2007
> > + *
> > + * Author : Cedric Le Goater <clg@fr.ibm.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of version 2.1 of the GNU Lesser General Public License
> > + * as published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it would be useful, but
> > + * WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/cgroup.h>
> > +#include <linux/fs.h>
> > +#include <linux/uaccess.h>
> > +#include <linux/freezer.h>
> > +#include <linux/seq_file.h>
> > +
> > +enum freezer_state {
> > + STATE_RUNNING = 0,
>
> That's a pretty vanilla-sounding identifier. Let's hope this file
> never ends up including drivers/net/sfc/net_driver.h by some means.
> That's rather unlikely, but someone could easily choose to implement a
> new STATE_RUNNING somewhere else.
Good point. Do CGROUP_THAWED, CGROUP_FREEZING, CGROUP_FROZEN make
sensible substitutions?
> > + STATE_FREEZING,
> > + STATE_FROZEN,
> > +};
> > +
> > +struct freezer {
> > + struct cgroup_subsys_state css;
> > + enum freezer_state state;
> > + spinlock_t lock; /* protects _writes_ to state */
> > +};
> > +
> > +static inline struct freezer *cgroup_freezer(
> > + struct cgroup *cgroup)
> > +{
> > + return container_of(
> > + cgroup_subsys_state(cgroup, freezer_subsys_id),
> > + struct freezer, css);
> > +}
> > +
> > +static inline struct freezer *task_freezer(struct task_struct *task)
> > +{
> > + return container_of(task_subsys_state(task, freezer_subsys_id),
> > + struct freezer, css);
> > +}
> > +
> > +int cgroup_frozen(struct task_struct *task)
> > +{
> > + struct freezer *freezer;
> > + enum freezer_state state;
> > +
> > + task_lock(task);
> > + freezer = task_freezer(task);
> > + state = freezer->state;
> > + task_unlock(task);
> > +
> > + return state == STATE_FROZEN;
> > +}
> > +
> > +/*
> > + * Buffer size for freezer state is limited by cgroups write_string()
> > + * interface. See cgroups code for the current size.
> > + */
>
> Is this comment in the correct place?
I think so. Perhaps I should have more clearly connected it with
freezer_state_strs. How about:
/*
* cgroups_write_string() limits the size of these strings to
* CGROUP_LOCAL_BUFFER_SIZE
*/
> > +static const char *freezer_state_strs[] = {
> > + "RUNNING",
> > + "FREEZING",
> > + "FROZEN",
> > +};
> > +
> >
> > ...
> >
> > +
> > +/*
> > + * caller must hold freezer->lock
> > + */
> > +static void check_if_frozen(struct cgroup *cgroup,
> > + struct freezer *freezer)
>
> check_if_frozen() is an unfortunate name, I suspect. Normally one
> would expect a check_foo() to return a bool and have no side-effects.
>
> Perhaps some comments explaining what it does would help.
OK. I'll try to think up a better name and if that's not sufficiently
explanatory I'll add a comment explaining what it should do.
> > +{
> > + struct cgroup_iter it;
> > + struct task_struct *task;
> > + unsigned int nfrozen = 0, ntotal = 0;
> > +
> > + cgroup_iter_start(cgroup, &it);
> > + while ((task = cgroup_iter_next(cgroup, &it))) {
> > + ntotal++;
> > + /*
> > + * Task is frozen or will freeze immediately when next it gets
> > + * woken
> > + */
> > + if (frozen(task) ||
> > + (task_is_stopped_or_traced(task) && freezing(task)))
> > + nfrozen++;
> > + }
> > +
> > + /*
> > + * Transition to FROZEN when no new tasks can be added ensures
> > + * that we never exist in the FROZEN state while there are unfrozen
> > + * tasks.
> > + */
> > + if (nfrozen == ntotal)
> > + freezer->state = STATE_FROZEN;
> > + cgroup_iter_end(cgroup, &it);
> > +}
> > +
> >
> > ...
> >
> > +static int freezer_write(struct cgroup *cgroup,
> > + struct cftype *cft,
> > + const char *buffer)
> > +{
> > + int retval;
> > + enum freezer_state goal_state;
> > +
> > + if (strcmp(buffer, freezer_state_strs[STATE_RUNNING]) == 0)
>
> Did some higher-level code take care of removing the trailing \n?
Yes. cgroup_write_string() in kernel/cgroup.c does strstrip(buffer)
Thanks for the review!
Cheers,
-Matt Helsley
next prev parent reply other threads:[~2008-08-13 2:38 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-11 23:53 [PATCH 0/5] Container Freezer v6: Reuse Suspend Freezer Matt Helsley
2008-08-11 23:53 ` [PATCH 1/5] Container Freezer: Add TIF_FREEZE flag to all architectures Matt Helsley
2008-08-11 23:53 ` Matt Helsley
2008-08-11 23:53 ` Matt Helsley
2008-08-11 23:53 ` [PATCH 2/5] Container Freezer: Make refrigerator always available Matt Helsley
2008-08-11 23:53 ` Matt Helsley
2008-08-11 23:53 ` Matt Helsley
2008-08-12 20:49 ` Rafael J. Wysocki
2008-08-12 20:49 ` Rafael J. Wysocki
[not found] ` <200808122249.27553.rjw-KKrjLPT3xs0@public.gmane.org>
2008-08-13 1:01 ` [ProbableSpam]Re: " Matt Helsley
2008-08-13 1:01 ` Matt Helsley
2008-08-13 14:31 ` Rafael J. Wysocki
2008-08-13 14:31 ` Rafael J. Wysocki
[not found] ` <1218589300.19008.135.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2008-08-13 14:31 ` Rafael J. Wysocki
2008-08-13 1:01 ` Matt Helsley
[not found] ` <20080811235324.661871296-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-12 20:49 ` Rafael J. Wysocki
2008-08-11 23:53 ` [PATCH 3/5] Container Freezer: Implement freezer cgroup subsystem Matt Helsley
2008-08-11 23:53 ` Matt Helsley
2008-08-12 22:56 ` Andrew Morton
[not found] ` <20080811235325.121356317-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-12 22:56 ` Andrew Morton
2008-08-12 22:56 ` Andrew Morton
[not found] ` <20080812155610.f4d40bb1.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2008-08-13 2:38 ` Matt Helsley
2008-08-13 2:38 ` Matt Helsley
2008-08-13 2:38 ` Matt Helsley [this message]
2008-08-13 14:51 ` Rafael J. Wysocki
[not found] ` <1218595088.19008.176.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2008-08-13 14:51 ` Rafael J. Wysocki
2008-08-13 14:51 ` Rafael J. Wysocki
2008-11-04 5:43 ` Paul Menage
2008-11-04 6:12 ` Li Zefan
2008-11-04 6:40 ` Paul Menage
2008-11-04 7:25 ` Li Zefan
2008-11-04 7:35 ` [RFC][PATCH] freezer_cg: disable writing freezer.state of root cgroup Li Zefan
2008-11-04 7:56 ` Paul Menage
2008-11-04 8:01 ` Li Zefan
2008-11-05 10:18 ` Cedric Le Goater
[not found] ` <4910014F.4000808-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org>
2008-11-05 10:18 ` Cedric Le Goater
2008-11-06 0:48 ` Paul Menage
2008-11-05 10:18 ` Cedric Le Goater
2008-11-06 0:48 ` Paul Menage
2008-11-06 0:48 ` Paul Menage
2008-11-04 6:48 ` [PATCH] freezer_cg: remove task_lock from freezer_fork() Li Zefan
2008-08-11 23:53 ` [PATCH 3/5] Container Freezer: Implement freezer cgroup subsystem Matt Helsley
2008-08-11 23:53 ` [PATCH 4/5] Container Freezer: Skip frozen cgroups during power management resume Matt Helsley
2008-08-11 23:53 ` Matt Helsley
2008-08-11 23:53 ` Matt Helsley
2008-08-12 20:50 ` Rafael J. Wysocki
2008-08-12 20:50 ` Rafael J. Wysocki
[not found] ` <20080811235325.485466148-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-12 20:50 ` Rafael J. Wysocki
2008-08-11 23:53 ` [PATCH 5/5] Container Freezer: Prevent frozen tasks or cgroups from changing Matt Helsley
2008-08-11 23:53 ` Matt Helsley
2008-08-11 23:53 ` Matt Helsley
2008-08-12 22:44 ` [PATCH 0/5] Container Freezer v6: Reuse Suspend Freezer Andrew Morton
[not found] ` <20080812154429.c5377bd0.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2008-08-13 3:47 ` [linux-pm] " Vivek Kashyap
2008-08-13 3:47 ` Vivek Kashyap
2008-08-13 4:08 ` Andrew Morton
[not found] ` <20080812210859.ff2fa2f4.akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
2008-08-15 21:54 ` Matt Helsley
2008-08-15 21:54 ` Matt Helsley
2008-08-15 21:54 ` [linux-pm] " Matt Helsley
2008-08-13 4:08 ` Andrew Morton
2008-08-13 4:08 ` Andrew Morton
2008-08-13 3:47 ` Vivek Kashyap
2008-08-12 22:44 ` Andrew Morton
[not found] ` <20080811235323.872291138-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-12 22:44 ` Andrew Morton
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=1218595088.19008.176.camel@localhost.localdomain \
--to=matthltc@us.ibm.com \
--cc=akpm@linux-foundation.org \
--cc=clg@fr.ibm.com \
--cc=containers@lists.linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=lizf@cn.fujitsu.com \
--cc=menage@google.com \
--cc=rjw@sisk.pl \
--cc=serue@us.ibm.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.