[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