[Devel] [PATCH 2/2] [RFC] Enable non-blocking writes to the cgroup freezer.state file
Matt Helsley
matthltc at us.ibm.com
Mon Oct 26 08:15:30 PDT 2009
Currently the cgroup freezer never blocks in the kernel.
This patch uses the f_flags parameter of the cgroups write_string
op to determine if blocking in the kernel is requested. Without
O_NONBLOCK the write blocks until freezing fails for other reasons
(though only -EAGAIN is possible now), the writer receives a signal,
or the cgroup is completely frozen. When O_NONBLOCK is set
writes to the freezer state return when some of the tasks in the
cgroup could not be frozen.
The change to the num_cant_freeze_now count enables blocking
while the test of dont_block outside of all the locks re-enables
non-blocking operations when O_NONBLOCK is set.
The change to EAGAIN from EBUSY for the write path should bring us
in line with standard non-blocking errno values (See Bugs/Weirdness).
Passes existing LTP tests and a vfork testcase from Nathan Lynch.
Signed-off-by: Matt Helsley <matthltc at us.ibm.com>
Cc: Nathan Lynch <ntl at pobox.com>
Cc: Li Zefan <lizf at cn.fujitsu.com>
Cc: Paul Menage <menage at google.com>
NOTE: This patch has one small hunk (passing !!O_NONBLOCK to
freezer_change_state()) for the checkpoint/restart tree. The
rest applies to mainline too.
Bugs/Weirdness to look into:
A task freezing itself now gets EINTR
freeze_self_thaw.sh 9/11: TINFO 3910 freezing itself
/bin/echo: write error: Interrupted system call
I think this happens after it gets woken up, not after
it becomes frozen:
stop_freeze_sleep_thaw_cont consistently WARNS during test
cleanup.
When using O_NONBLOCK I am getting E2BIG instead of EAGAIN
for some reason.
---
kernel/cgroup_freezer.c | 20 +++++++++++++++-----
1 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index c97680f..9fe9e65 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -288,12 +288,11 @@ static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
continue;
if (is_task_frozen_enough(task))
continue;
- if (!freezing(task) && !freezer_should_skip(task))
- num_cant_freeze_now++;
+ num_cant_freeze_now++;
}
cgroup_iter_end(cgroup, &it);
- return num_cant_freeze_now ? -EBUSY : 0;
+ return num_cant_freeze_now ? -EAGAIN : 0;
}
static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
@@ -320,7 +319,7 @@ static int freezer_change_state(struct cgroup *cgroup,
spin_lock_irq(&freezer->lock);
if (freezer->state == CGROUP_CHECKPOINTING) {
- retval = -EBUSY;
+ retval = -EAGAIN;
goto out;
}
update_freezer_state(cgroup, freezer);
@@ -339,7 +338,6 @@ static int freezer_change_state(struct cgroup *cgroup,
}
out:
spin_unlock_irq(&freezer->lock);
-
return retval;
}
@@ -356,10 +354,22 @@ static int freezer_write(struct cgroup *cgroup, struct cftype *cft,
else
return -EINVAL;
+retry:
if (!cgroup_lock_live_group(cgroup))
return -ENODEV;
retval = freezer_change_state(cgroup, goal_state);
cgroup_unlock();
+
+ if ((f_flags & O_NONBLOCK) || (retval != -EAGAIN))
+ return retval;
+
+ /* block while we haven't changed the state to the goal state */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ if (!signal_pending(current))
+ goto retry;
+ retval = -EINTR;
return retval;
}
--
1.5.6.3
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
More information about the Devel
mailing list