The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/3120

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 583ffd34c3a10633f06076b628e461d56f047b70 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brau...@ubuntu.com>
Date: Thu, 15 Aug 2019 19:50:39 +0200
Subject: [PATCH] cgroups: support cgroup2 freezer

Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
---
 src/lxc/cgroups/cgfsng.c | 103 ++++++++++++++++++++++++++++++++++-----
 src/lxc/cgroups/cgroup.h |   1 +
 src/lxc/freezer.c        |  57 +++++++++++++---------
 3 files changed, 128 insertions(+), 33 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index c29c0958e9..1f6c51a8c1 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -43,6 +43,8 @@
 #include <grp.h>
 #include <linux/kdev_t.h>
 #include <linux/types.h>
+#include <poll.h>
+#include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -1958,28 +1960,106 @@ __cgfsng_ops static bool cgfsng_get_hierarchies(struct 
cgroup_ops *ops, int n, c
        return true;
 }
 
-#define THAWED "THAWED"
-#define THAWED_LEN (strlen(THAWED))
+static bool poll_file_ready(int lfd)
+{
+       int ret;
+       struct pollfd pfd = {
+           .fd = lfd,
+           .events = POLLIN,
+           .revents = 0,
+       };
+
+again:
+       ret = poll(&pfd, 1, 60000);
+       if (ret < 0) {
+               if (errno == EINTR)
+                       goto again;
 
-/* TODO: If the unified cgroup hierarchy grows a freezer controller this needs
- * to be adapted.
- */
-__cgfsng_ops static bool cgfsng_unfreeze(struct cgroup_ops *ops)
+               SYSERROR("Failed to poll() on file descriptor");
+               return false;
+       }
+
+       return (pfd.revents & POLLIN);
+}
+
+__cgfsng_ops static bool cgfsng_freeze(struct cgroup_ops *ops)
 {
        int ret;
-       __do_free char *fullpath = NULL;
+       __do_close_prot_errno int fd = -EBADF;
+       __do_free char *events_file = NULL, *fullpath = NULL, *line = NULL;
+       __do_fclose FILE *f = NULL;
        struct hierarchy *h;
 
-       h = get_hierarchy(ops, "freezer");
+       if (ops->cgroup_layout != CGROUP_LAYOUT_UNIFIED) {
+               h = get_hierarchy(ops, "freezer");
+               if (!h)
+                       return false;
+
+               fullpath = must_make_path(h->container_full_path,
+                                         "freezer.state", NULL);
+               return lxc_write_to_file(fullpath, "FROZEN",
+                                        STRLITERALLEN("FROZEN"), false,
+                                        0666) == 0;
+       }
+
+       h = ops->unified;
        if (!h)
                return false;
 
-       fullpath = must_make_path(h->container_full_path, "freezer.state", 
NULL);
-       ret = lxc_write_to_file(fullpath, THAWED, THAWED_LEN, false, 0666);
+       fullpath = must_make_path(h->container_full_path, "cgroup.freeze", 
NULL);
+       ret = lxc_write_to_file(fullpath, "1", 1, false, 0666);
        if (ret < 0)
                return false;
 
-       return true;
+       events_file =
+           must_make_path(h->container_full_path, "cgroup.events", NULL);
+       fd = open(events_file, O_RDONLY | O_CLOEXEC);
+       if (fd < 0)
+               return false;
+
+       f = fdopen(fd, "re");
+       if (!f)
+               return false;
+       move_fd(fd);
+
+       for (int i = 0; i < 10 && poll_file_ready(fd); i++) {
+               size_t len;
+
+               while (getline(&line, &len, f) != -1) {
+                       if (strcmp(line, "frozen 1") == 0)
+                               return true;
+               }
+
+               fseek(f, 0, SEEK_SET);
+       };
+
+       return false;
+}
+
+__cgfsng_ops static bool cgfsng_unfreeze(struct cgroup_ops *ops)
+{
+       int ret;
+       __do_free char *fullpath = NULL;
+       struct hierarchy *h;
+
+       if (ops->cgroup_layout != CGROUP_LAYOUT_UNIFIED) {
+               h = get_hierarchy(ops, "freezer");
+               if (!h)
+                       return false;
+
+               fullpath = must_make_path(h->container_full_path,
+                                         "freezer.state", NULL);
+               return lxc_write_to_file(fullpath, "THAWED",
+                                        STRLITERALLEN("THAWED"), false,
+                                        0666) == 0;
+       }
+
+       h = ops->unified;
+       if (!h)
+               return false;
+
+       fullpath = must_make_path(h->container_full_path, "cgroup.freeze", 
NULL);
+       return lxc_write_to_file(fullpath, "0", 1, false, 0666) == 0;
 }
 
 __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops,
@@ -2767,6 +2847,7 @@ struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf)
        cgfsng_ops->get_cgroup = cgfsng_get_cgroup;
        cgfsng_ops->get = cgfsng_get;
        cgfsng_ops->set = cgfsng_set;
+       cgfsng_ops->freeze = cgfsng_freeze;
        cgfsng_ops->unfreeze = cgfsng_unfreeze;
        cgfsng_ops->setup_limits = cgfsng_setup_limits;
        cgfsng_ops->driver = "cgfsng";
diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
index b5d4c42bc1..f3f0f67266 100644
--- a/src/lxc/cgroups/cgroup.h
+++ b/src/lxc/cgroups/cgroup.h
@@ -154,6 +154,7 @@ struct cgroup_ops {
                   const char *value, const char *name, const char *lxcpath);
        int (*get)(struct cgroup_ops *ops, const char *filename, char *value,
                   size_t len, const char *name, const char *lxcpath);
+       bool (*freeze)(struct cgroup_ops *ops);
        bool (*unfreeze)(struct cgroup_ops *ops);
        bool (*setup_limits)(struct cgroup_ops *ops, struct lxc_conf *conf,
                             bool with_devices);
diff --git a/src/lxc/freezer.c b/src/lxc/freezer.c
index 953d9d8b83..1843f2a606 100644
--- a/src/lxc/freezer.c
+++ b/src/lxc/freezer.c
@@ -62,36 +62,49 @@ static int do_freeze_thaw(bool freeze, struct lxc_conf 
*conf, const char *name,
        if (!cgroup_ops)
                return -1;
 
-       ret = cgroup_ops->set(cgroup_ops, "freezer.state", state, name, 
lxcpath);
-       if (ret < 0) {
-               cgroup_exit(cgroup_ops);
-               ERROR("Failed to %s %s",
-                     (new_state == FROZEN ? "freeze" : "unfreeze"), name);
-               return -1;
-       }
-
-       for (;;) {
-               ret = cgroup_ops->get(cgroup_ops, "freezer.state", v, sizeof(v),
-                                     name, lxcpath);
+       if (cgroup_ops->cgroup_layout != CGROUP_LAYOUT_UNIFIED) {
+               ret = cgroup_ops->set(cgroup_ops, "freezer.state", state, name,
+                                     lxcpath);
                if (ret < 0) {
                        cgroup_exit(cgroup_ops);
-                       ERROR("Failed to get freezer state of %s", name);
+                       ERROR("Failed to %s %s",
+                             (new_state == FROZEN ? "freeze" : "unfreeze"),
+                             name);
                        return -1;
                }
 
-               v[sizeof(v) - 1] = '\0';
-               v[lxc_char_right_gc(v, strlen(v))] = '\0';
+               for (;;) {
+                       ret = cgroup_ops->get(cgroup_ops, "freezer.state", v,
+                                             sizeof(v), name, lxcpath);
+                       if (ret < 0) {
+                               cgroup_exit(cgroup_ops);
+                               ERROR("Failed to get freezer state of %s", 
name);
+                               return -1;
+                       }
 
-               ret = strncmp(v, state, state_len);
-               if (ret == 0) {
-                       cgroup_exit(cgroup_ops);
-                       lxc_cmd_serve_state_clients(name, lxcpath, new_state);
-                       lxc_monitor_send_state(name, new_state, lxcpath);
-                       return 0;
-               }
+                       v[sizeof(v) - 1] = '\0';
+                       v[lxc_char_right_gc(v, strlen(v))] = '\0';
 
-               sleep(1);
+                       ret = strncmp(v, state, state_len);
+                       if (ret == 0) {
+                               cgroup_exit(cgroup_ops);
+                               lxc_cmd_serve_state_clients(name, lxcpath,
+                                                           new_state);
+                               lxc_monitor_send_state(name, new_state, 
lxcpath);
+                               return 0;
+                       }
+
+                       sleep(1);
+               }
        }
+
+       ret = cgroup_ops->freeze(cgroup_ops);
+       cgroup_exit(cgroup_ops);
+       if (ret < 0)
+               return error_log_errno(-1, "Failed to %s container",
+                                      freeze ? "freeze" : "unfreeze");
+
+       return 0;
 }
 
 int lxc_freeze(struct lxc_conf *conf, const char *name, const char *lxcpath)
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to