From: Christian Brauner Date: Tue, 2 Feb 2021 17:27:12 +0000 (+0100) Subject: cgroups: add cgroup_freeze() and cgroup_unfreeze() X-Git-Tag: lxc-5.0.0~305^2~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c8af3332bc70f6b8a0c733a4c89ee6d657cc8379;p=thirdparty%2Flxc.git cgroups: add cgroup_freeze() and cgroup_unfreeze() These are unified hierarchy only methods which don't need to initialize a full cgroup driver. Instead, they rely on the command socket to retrieve a cgroup2 file descriptor to the container's cgroup. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index b47a63c06..533c1f449 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -37,6 +37,7 @@ #include "cgroup2_devices.h" #include "cgroup_utils.h" #include "commands.h" +#include "commands_utils.h" #include "conf.h" #include "config.h" #include "log.h" @@ -2026,24 +2027,18 @@ static bool cg_legacy_freeze(struct cgroup_ops *ops) static int freezer_cgroup_events_cb(int fd, uint32_t events, void *cbdata, struct lxc_epoll_descr *descr) { - __do_close int duped_fd = -EBADF; __do_free char *line = NULL; __do_fclose FILE *f = NULL; int state = PTR_TO_INT(cbdata); size_t len; const char *state_string; - duped_fd = dup(fd); - if (duped_fd < 0) + if (lseek(fd, 0, SEEK_SET) < (off_t)-1) return LXC_MAINLOOP_ERROR; - if (lseek(duped_fd, 0, SEEK_SET) < (off_t)-1) - return LXC_MAINLOOP_ERROR; - - f = fdopen(duped_fd, "re"); + f = fdopen_at(fd, "", "re", PROTECT_OPEN, PROTECT_LOOKUP_BENEATH); if (!f) return LXC_MAINLOOP_ERROR; - move_fd(duped_fd); if (state == 1) state_string = "frozen 1"; @@ -3556,3 +3551,79 @@ int cgroup_set(struct lxc_conf *conf, const char *name, const char *lxcpath, return ret; } + +static int __cgroup_freeze(int unified_fd, + const char *state_string, + int state_num, + int timeout, + const char *epoll_error, + const char *wait_error) +{ + __do_close int events_fd = -EBADF; + call_cleaner(lxc_mainloop_close) struct lxc_epoll_descr *descr_ptr = NULL; + int ret; + struct lxc_epoll_descr descr = {}; + + if (timeout != 0) { + ret = lxc_mainloop_open(&descr); + if (ret) + return log_error_errno(-1, errno, "%s", epoll_error); + + /* automatically cleaned up now */ + descr_ptr = &descr; + + events_fd = open_at(unified_fd, "cgroup.events", PROTECT_OPEN, PROTECT_LOOKUP_BENEATH, 0); + if (events_fd < 0) + return log_error_errno(-errno, errno, "Failed to open cgroup.events file"); + + ret = lxc_mainloop_add_handler_events(&descr, events_fd, EPOLLPRI, freezer_cgroup_events_cb, INT_TO_PTR(state_num)); + if (ret < 0) + return log_error_errno(-1, errno, "Failed to add cgroup.events fd handler to mainloop"); + } + + ret = lxc_writeat(unified_fd, "cgroup.freeze", state_string, 1); + if (ret < 0) + return log_error_errno(-1, errno, "Failed to open cgroup.freeze file"); + + if (timeout != 0) { + ret = lxc_mainloop(&descr, timeout); + if (ret) + return log_error_errno(-1, errno, "%s", wait_error); + } + + return log_trace(0, "Container now %s", (state_num == 1) ? "frozen" : "unfrozen"); +} + +bool cgroup_freeze(struct lxc_conf *conf, const char *name, const char *lxcpath, int timeout) +{ + __do_close int unified_fd = -EBADF; + int ret; + + unified_fd = lxc_cmd_get_cgroup2_fd(name, lxcpath); + if (unified_fd < 0) + return ret_errno(ENOCGROUP2); + + lxc_cmd_notify_state_listeners(name, lxcpath, FREEZING); + ret = __cgroup_freeze(unified_fd, "1", 1, timeout, + "Failed to create epoll instance to wait for container freeze", + "Failed to wait for container to be frozen"); + lxc_cmd_notify_state_listeners(name, lxcpath, !ret ? FROZEN : RUNNING); + return ret == 0; +} + +bool cgroup_unfreeze(struct lxc_conf *conf, const char *name, const char *lxcpath, int timeout) +{ + __do_close int unified_fd = -EBADF; + int ret; + + unified_fd = lxc_cmd_get_cgroup2_fd(name, lxcpath); + if (unified_fd < 0) + return ret_errno(ENOCGROUP2); + + lxc_cmd_notify_state_listeners(name, lxcpath, THAWED); + ret = __cgroup_freeze(unified_fd, "0", 0, timeout, + "Failed to create epoll instance to wait for container freeze", + "Failed to wait for container to be frozen"); + lxc_cmd_notify_state_listeners(name, lxcpath, !ret ? RUNNING : FROZEN); + return ret == 0; +} diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h index 969842703..4566f5217 100644 --- a/src/lxc/cgroups/cgroup.h +++ b/src/lxc/cgroups/cgroup.h @@ -197,6 +197,10 @@ __hidden extern int cgroup_get(struct lxc_conf *conf, const char *name, __hidden extern int cgroup_set(struct lxc_conf *conf, const char *name, const char *lxcpath, const char *filename, const char *value); +__hidden extern bool cgroup_freeze(struct lxc_conf *conf, const char *name, + const char *lxcpath, int timeout); +__hidden extern bool cgroup_unfreeze(struct lxc_conf *conf, const char *name, + const char *lxcpath, int timeout); static inline bool pure_unified_layout(const struct cgroup_ops *ops) {