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@xxxxxxxxxx> Cc: Nathan Lynch <ntl@xxxxxxxxx> Cc: Li Zefan <lizf@xxxxxxxxxxxxxx> Cc: Paul Menage <menage@xxxxxxxxxx> 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@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers