[lxc-devel] [lxc/master] cgroups: support cgroup2 freezer
brauner on Github
lxc-bot at linuxcontainers.org
Thu Aug 15 17:51:26 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 364 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190815/7afd91c8/attachment.bin>
-------------- next part --------------
From 583ffd34c3a10633f06076b628e461d56f047b70 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Thu, 15 Aug 2019 19:50:39 +0200
Subject: [PATCH] cgroups: support cgroup2 freezer
Signed-off-by: Christian Brauner <christian.brauner at 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)
More information about the lxc-devel
mailing list