freezer: cleanup

parent ecaf0c7b
...@@ -2745,23 +2745,24 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops, ...@@ -2745,23 +2745,24 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops,
devices = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE); devices = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE);
if (!devices) if (!devices)
return log_error(false, ENOMEM, return log_error_errno(false, ENOMEM,
"Failed to create new bpf program"); "Failed to create new bpf program");
ret = bpf_program_init(devices); ret = bpf_program_init(devices);
if (ret) if (ret)
return log_error(false, ENOMEM, return log_error_errno(false, ENOMEM,
"Failed to initialize bpf program"); "Failed to initialize bpf program");
lxc_list_for_each(it, &conf->devices) { lxc_list_for_each(it, &conf->devices) {
struct device_item *cur = it->elem; struct device_item *cur = it->elem;
ret = bpf_program_append_device(devices, cur); ret = bpf_program_append_device(devices, cur);
if (ret) if (ret)
return log_error(false, return log_error_errno(false,
ENOMEM, "Failed to add new rule to bpf device program: type %c, major %d, minor %d, access %s, allow %d, global_rule %d", ENOMEM, "Failed to add new rule to bpf device program: type %c, major %d, minor %d, access %s, allow %d, global_rule %d",
cur->type, cur->major, cur->minor, cur->type, cur->major,
cur->access, cur->allow, cur->global_rule); cur->minor, cur->access,
cur->allow, cur->global_rule);
TRACE("Added rule to bpf device program: type %c, major %d, minor %d, access %s, allow %d, global_rule %d", TRACE("Added rule to bpf device program: type %c, major %d, minor %d, access %s, allow %d, global_rule %d",
cur->type, cur->major, cur->minor, cur->access, cur->type, cur->major, cur->minor, cur->access,
cur->allow, cur->global_rule); cur->allow, cur->global_rule);
...@@ -2769,13 +2770,15 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops, ...@@ -2769,13 +2770,15 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops,
ret = bpf_program_finalize(devices); ret = bpf_program_finalize(devices);
if (ret) if (ret)
return log_error(false, ENOMEM, "Failed to finalize bpf program"); return log_error_errno(false, ENOMEM,
"Failed to finalize bpf program");
ret = bpf_program_cgroup_attach(devices, BPF_CGROUP_DEVICE, ret = bpf_program_cgroup_attach(devices, BPF_CGROUP_DEVICE,
unified->container_full_path, unified->container_full_path,
BPF_F_ALLOW_MULTI); BPF_F_ALLOW_MULTI);
if (ret) if (ret)
return log_error(false, ENOMEM, "Failed to attach bpf program"); return log_error_errno(false, ENOMEM,
"Failed to attach bpf program");
/* Replace old bpf program. */ /* Replace old bpf program. */
devices_old = move_ptr(conf->cgroup2_devices); devices_old = move_ptr(conf->cgroup2_devices);
...@@ -2999,22 +3002,6 @@ static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative, ...@@ -2999,22 +3002,6 @@ static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative,
return true; return true;
} }
static int cg_is_pure_unified(void)
{
int ret;
struct statfs fs;
ret = statfs(DEFAULT_CGROUP_MOUNTPOINT, &fs);
if (ret < 0)
return -ENOMEDIUM;
if (is_fs_type(&fs, CGROUP2_SUPER_MAGIC))
return CGROUP2_SUPER_MAGIC;
return 0;
}
/* Get current cgroup from /proc/self/cgroup for the cgroupfs v2 hierarchy. */ /* Get current cgroup from /proc/self/cgroup for the cgroupfs v2 hierarchy. */
static char *cg_unified_get_current_cgroup(bool relative) static char *cg_unified_get_current_cgroup(bool relative)
{ {
...@@ -3055,7 +3042,7 @@ static int cg_unified_init(struct cgroup_ops *ops, bool relative, ...@@ -3055,7 +3042,7 @@ static int cg_unified_init(struct cgroup_ops *ops, bool relative,
struct hierarchy *new; struct hierarchy *new;
char *base_cgroup = NULL; char *base_cgroup = NULL;
ret = cg_is_pure_unified(); ret = unified_cgroup_hierarchy();
if (ret == -ENOMEDIUM) if (ret == -ENOMEDIUM)
return -ENOMEDIUM; return -ENOMEDIUM;
......
...@@ -184,4 +184,12 @@ extern void cgroup_exit(struct cgroup_ops *ops); ...@@ -184,4 +184,12 @@ extern void cgroup_exit(struct cgroup_ops *ops);
extern void prune_init_scope(char *cg); extern void prune_init_scope(char *cg);
static inline void __auto_cgroup_exit__(struct cgroup_ops **ops)
{
if (*ops)
cgroup_exit(*ops);
}
#define __do_cgroup_exit __attribute__((__cleanup__(__auto_cgroup_exit__)))
#endif #endif
...@@ -511,23 +511,23 @@ bool bpf_devices_cgroup_supported(void) ...@@ -511,23 +511,23 @@ bool bpf_devices_cgroup_supported(void)
int ret; int ret;
if (geteuid() != 0) if (geteuid() != 0)
return log_error(false, EINVAL, return log_error_errno(false,
"The bpf device cgroup requires real root"); EINVAL, "The bpf device cgroup requires real root");
prog = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE); prog = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE);
if (prog < 0) if (prog < 0)
return log_error(false, return log_error_errno(false,
errno, "Failed to allocate new bpf device cgroup program"); errno, "Failed to allocate new bpf device cgroup program");
ret = bpf_program_add_instructions(prog, dummy, ARRAY_SIZE(dummy)); ret = bpf_program_add_instructions(prog, dummy, ARRAY_SIZE(dummy));
if (ret < 0) if (ret < 0)
return log_error(false, return log_error_errno(false,
errno, "Failed to add new instructions to bpf device cgroup program"); errno, "Failed to add new instructions to bpf device cgroup program");
ret = bpf_program_load_kernel(prog, NULL, 0); ret = bpf_program_load_kernel(prog, NULL, 0);
if (ret < 0) if (ret < 0)
return log_error(false, return log_error_errno(false,
errno, "Failed to load new bpf device cgroup program"); errno, "Failed to load new bpf device cgroup program");
return log_trace(true, "The bpf device cgroup is supported"); return log_trace(true, "The bpf device cgroup is supported");
} }
......
...@@ -28,10 +28,13 @@ ...@@ -28,10 +28,13 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/vfs.h>
#include <unistd.h> #include <unistd.h>
#include "cgroup.h"
#include "cgroup_utils.h" #include "cgroup_utils.h"
#include "config.h" #include "config.h"
#include "file_utils.h"
#include "macro.h" #include "macro.h"
#include "memory_utils.h" #include "memory_utils.h"
#include "utils.h" #include "utils.h"
...@@ -101,3 +104,19 @@ bool test_writeable_v2(char *mountpoint, char *path) ...@@ -101,3 +104,19 @@ bool test_writeable_v2(char *mountpoint, char *path)
return (access(cgroup_threads_file, W_OK) == 0); return (access(cgroup_threads_file, W_OK) == 0);
} }
int unified_cgroup_hierarchy(void)
{
int ret;
struct statfs fs;
ret = statfs(DEFAULT_CGROUP_MOUNTPOINT, &fs);
if (ret < 0)
return -ENOMEDIUM;
if (is_fs_type(&fs, CGROUP2_SUPER_MAGIC))
return CGROUP2_SUPER_MAGIC;
return 0;
}
...@@ -48,4 +48,6 @@ extern bool test_writeable_v1(char *mountpoint, char *path); ...@@ -48,4 +48,6 @@ extern bool test_writeable_v1(char *mountpoint, char *path);
*/ */
extern bool test_writeable_v2(char *mountpoint, char *path); extern bool test_writeable_v2(char *mountpoint, char *path);
extern int unified_cgroup_hierarchy(void);
#endif /* __LXC_CGROUP_UTILS_H */ #endif /* __LXC_CGROUP_UTILS_H */
...@@ -33,7 +33,8 @@ ...@@ -33,7 +33,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "cgroup.h" #include "cgroups/cgroup.h"
#include "cgroups/cgroup_utils.h"
#include "commands.h" #include "commands.h"
#include "config.h" #include "config.h"
#include "error.h" #include "error.h"
...@@ -45,15 +46,21 @@ ...@@ -45,15 +46,21 @@
lxc_log_define(freezer, lxc); lxc_log_define(freezer, lxc);
static void notify_state_listeners(const char *name, const char *lxcpath,
lxc_state_t state)
{
(void)lxc_cmd_serve_state_clients(name, lxcpath, state);
(void)lxc_monitor_send_state(name, state, lxcpath);
}
static int do_freeze_thaw(bool freeze, struct lxc_conf *conf, const char *name, static int do_freeze_thaw(bool freeze, struct lxc_conf *conf, const char *name,
const char *lxcpath) const char *lxcpath)
{ {
__do_cgroup_exit struct cgroup_ops *cgroup_ops = NULL;
lxc_state_t new_state = freeze ? FROZEN : THAWED;
int ret; int ret;
char v[100];
struct cgroup_ops *cgroup_ops;
const char *state; const char *state;
size_t state_len; size_t state_len;
lxc_state_t new_state = freeze ? FROZEN : THAWED;
state = lxc_state2str(new_state); state = lxc_state2str(new_state);
state_len = strlen(state); state_len = strlen(state);
...@@ -62,66 +69,41 @@ static int do_freeze_thaw(bool freeze, struct lxc_conf *conf, const char *name, ...@@ -62,66 +69,41 @@ static int do_freeze_thaw(bool freeze, struct lxc_conf *conf, const char *name,
if (!cgroup_ops) if (!cgroup_ops)
return -1; return -1;
if (cgroup_ops->cgroup_layout != CGROUP_LAYOUT_UNIFIED) { ret = cgroup_ops->set(cgroup_ops, "freezer.state", state, name, lxcpath);
ret = cgroup_ops->set(cgroup_ops, "freezer.state", state, name, if (ret < 0)
lxcpath); return log_error(-1, "Failed to %s %s",
if (ret < 0) { freeze ? "freeze" : "unfreeze", name);
cgroup_exit(cgroup_ops);
ERROR("Failed to %s %s", for (;;) {
(new_state == FROZEN ? "freeze" : "unfreeze"), char cur_state[MAX_STATE_LENGTH] = "";
name);
return -1; ret = cgroup_ops->get(cgroup_ops, "freezer.state", cur_state,
sizeof(cur_state), name, lxcpath);
if (ret < 0)
return log_error(-1, "Failed to get freezer state of %s", name);
cur_state[lxc_char_right_gc(cur_state, strlen(cur_state))] = '\0';
ret = strncmp(cur_state, state, state_len);
if (ret == 0) {
notify_state_listeners(name, lxcpath, new_state);
return 0;
} }
for (;;) { sleep(1);
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;
}
v[sizeof(v) - 1] = '\0';
v[lxc_char_right_gc(v, strlen(v))] = '\0';
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);
}
} }
if (freeze)
ret = lxc_cmd_freeze(name, lxcpath, -1);
else
ret = lxc_cmd_unfreeze(name, lxcpath, -1);
cgroup_exit(cgroup_ops);
if (ret < 0)
return error_log_errno(-1, "Failed to %s container",
freeze ? "freeze" : "unfreeze");
return 0; return 0;
} }
static void notify_state_listeners(const char *name, const char *lxcpath,
lxc_state_t state)
{
lxc_cmd_serve_state_clients(name, lxcpath, state);
lxc_monitor_send_state(name, state, lxcpath);
}
int lxc_freeze(struct lxc_conf *conf, const char *name, const char *lxcpath) int lxc_freeze(struct lxc_conf *conf, const char *name, const char *lxcpath)
{ {
int ret; int ret;
notify_state_listeners(name, lxcpath, FREEZING); notify_state_listeners(name, lxcpath, FREEZING);
ret = do_freeze_thaw(true, conf, name, lxcpath); if (unified_cgroup_hierarchy() > 0)
ret = lxc_cmd_freeze(name, lxcpath, -1);
else
ret = do_freeze_thaw(true, conf, name, lxcpath);
notify_state_listeners(name, lxcpath, !ret ? FROZEN : RUNNING); notify_state_listeners(name, lxcpath, !ret ? FROZEN : RUNNING);
return ret; return ret;
} }
...@@ -131,7 +113,10 @@ int lxc_unfreeze(struct lxc_conf *conf, const char *name, const char *lxcpath) ...@@ -131,7 +113,10 @@ int lxc_unfreeze(struct lxc_conf *conf, const char *name, const char *lxcpath)
int ret; int ret;
notify_state_listeners(name, lxcpath, THAWED); notify_state_listeners(name, lxcpath, THAWED);
ret = do_freeze_thaw(false, conf, name, lxcpath); if (unified_cgroup_hierarchy() > 0)
ret = lxc_cmd_unfreeze(name, lxcpath, -1);
else
ret = do_freeze_thaw(false, conf, name, lxcpath);
notify_state_listeners(name, lxcpath, !ret ? RUNNING : FROZEN); notify_state_listeners(name, lxcpath, !ret ? RUNNING : FROZEN);
return ret; return ret;
} }
...@@ -518,11 +518,17 @@ ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \ ...@@ -518,11 +518,17 @@ ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \
__ret__; \ __ret__; \
}) })
#define log_error(__ret__, __errno__, format, ...) \ #define log_error_errno(__ret__, __errno__, format, ...) \
({ \ ({ \
errno = __errno__; \ errno = __errno__; \
SYSERROR(format, ##__VA_ARGS__); \ SYSERROR(format, ##__VA_ARGS__); \
__ret__; \ __ret__; \
})
#define log_error(__ret__, format, ...) \
({ \
ERROR(format, ##__VA_ARGS__); \
__ret__; \
}) })
extern int lxc_log_fd; extern int lxc_log_fd;
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#ifndef __LXC_STATE_H #ifndef __LXC_STATE_H
#define __LXC_STATE_H #define __LXC_STATE_H
#define MAX_STATE_LENGTH (8 + 1)
typedef enum { typedef enum {
STOPPED, STOPPED,
STARTING, STARTING,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment