Unverified Commit dc89b0d7 by Wolfgang Bumiller Committed by Christian Brauner

introduce lxc.cgroup.dir.{monitor,container,container.inner}

This is a new approach to #1302 with a container-side configuration instead of a global boolean flag. Contrary to the previous PR using an optional additional parameter for the get-cgroup command, this introduces two new additional commands to get the limiting cgroup path and cgroup2 file descriptor. If the limiting option is not in use, these behave identical to their full-path counterparts. If these variables are used the payload will end up in the concatenation of lxc.cgroup.dir.container and lxc.cgroup.dir.container.inner (which may be empty), and the monitor will end up in lxc.cgruop.dir.monitor. The directories are fixed, no retry count logic is applied, failing to create these directories will simply be a hard error. Signed-off-by: 's avatarWolfgang Bumiller <w.bumiller@proxmox.com> Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 0c9e185c
...@@ -54,7 +54,11 @@ typedef enum { ...@@ -54,7 +54,11 @@ typedef enum {
* init's cgroup (if root). * init's cgroup (if root).
* *
* @container_full_path * @container_full_path
* - The full path to the containers cgroup. * - The full path to the container's cgroup.
*
* @container_limit_path
* - The full path to the container's limiting cgroup. May simply point to
* container_full_path.
* *
* @monitor_full_path * @monitor_full_path
* - The full path to the monitor's cgroup. * - The full path to the monitor's cgroup.
...@@ -77,15 +81,18 @@ struct hierarchy { ...@@ -77,15 +81,18 @@ struct hierarchy {
char *mountpoint; char *mountpoint;
char *container_base_path; char *container_base_path;
char *container_full_path; char *container_full_path;
char *container_limit_path;
char *monitor_full_path; char *monitor_full_path;
int version; int version;
/* cgroup2 only */ /* cgroup2 only */
unsigned int bpf_device_controller:1; unsigned int bpf_device_controller:1;
/* monitor cgroup fd */
int cgfd_con;
/* container cgroup fd */ /* container cgroup fd */
int cgfd_con;
/* limiting cgroup fd (may be equal to cgfd_con if not separated) */
int cgfd_limit;
/* monitor cgroup fd */
int cgfd_mon; int cgfd_mon;
}; };
...@@ -169,6 +176,7 @@ struct cgroup_ops { ...@@ -169,6 +176,7 @@ struct cgroup_ops {
bool (*monitor_delegate_controllers)(struct cgroup_ops *ops); bool (*monitor_delegate_controllers)(struct cgroup_ops *ops);
bool (*payload_delegate_controllers)(struct cgroup_ops *ops); bool (*payload_delegate_controllers)(struct cgroup_ops *ops);
void (*payload_finalize)(struct cgroup_ops *ops); void (*payload_finalize)(struct cgroup_ops *ops);
const char *(*get_limiting_cgroup)(struct cgroup_ops *ops, const char *controller);
}; };
extern struct cgroup_ops *cgroup_init(struct lxc_conf *conf); extern struct cgroup_ops *cgroup_init(struct lxc_conf *conf);
......
...@@ -84,6 +84,8 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd) ...@@ -84,6 +84,8 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd)
[LXC_CMD_UNFREEZE] = "unfreeze", [LXC_CMD_UNFREEZE] = "unfreeze",
[LXC_CMD_GET_CGROUP2_FD] = "get_cgroup2_fd", [LXC_CMD_GET_CGROUP2_FD] = "get_cgroup2_fd",
[LXC_CMD_GET_INIT_PIDFD] = "get_init_pidfd", [LXC_CMD_GET_INIT_PIDFD] = "get_init_pidfd",
[LXC_CMD_GET_LIMITING_CGROUP] = "get_limiting_cgroup",
[LXC_CMD_GET_LIMITING_CGROUP2_FD] = "get_limiting_cgroup2_fd",
}; };
if (cmd >= LXC_CMD_MAX) if (cmd >= LXC_CMD_MAX)
...@@ -142,7 +144,9 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd) ...@@ -142,7 +144,9 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
rsp->data = rspdata; rsp->data = rspdata;
} }
if (cmd->req.cmd == LXC_CMD_GET_CGROUP2_FD) { if (cmd->req.cmd == LXC_CMD_GET_CGROUP2_FD ||
cmd->req.cmd == LXC_CMD_GET_LIMITING_CGROUP2_FD)
{
int cgroup2_fd = move_fd(fd_rsp); int cgroup2_fd = move_fd(fd_rsp);
rsp->data = INT_TO_PTR(cgroup2_fd); rsp->data = INT_TO_PTR(cgroup2_fd);
} }
...@@ -483,25 +487,14 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req, ...@@ -483,25 +487,14 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
return 0; return 0;
} }
/* static char *lxc_cmd_get_cgroup_path_do(const char *name, const char *lxcpath,
* lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a const char *subsystem,
* particular subsystem. This is the cgroup path relative to the root lxc_cmd_t command)
* of the cgroup filesystem.
*
* @name : name of container to connect to
* @lxcpath : the lxcpath in which the container is running
* @subsystem : the subsystem being asked about
*
* Returns the path on success, NULL on failure. The caller must free() the
* returned path.
*/
char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
const char *subsystem)
{ {
int ret, stopped; int ret, stopped;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .req = {
.cmd = LXC_CMD_GET_CGROUP, .cmd = command,
.data = subsystem, .data = subsystem,
.datalen = 0, .datalen = 0,
}, },
...@@ -525,24 +518,72 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath, ...@@ -525,24 +518,72 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
return cmd.rsp.data; return cmd.rsp.data;
} }
static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req, /*
struct lxc_handler *handler, * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
struct lxc_epoll_descr *descr) * particular subsystem. This is the cgroup path relative to the root
* of the cgroup filesystem.
*
* @name : name of container to connect to
* @lxcpath : the lxcpath in which the container is running
* @subsystem : the subsystem being asked about
*
* Returns the path on success, NULL on failure. The caller must free() the
* returned path.
*/
char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
const char *subsystem)
{
return lxc_cmd_get_cgroup_path_do(name, lxcpath, subsystem,
LXC_CMD_GET_CGROUP);
}
/*
* lxc_cmd_get_limiting_cgroup_path: Calculate a container's limiting cgroup
* path for a particular subsystem. This is the cgroup path relative to the
* root of the cgroup filesystem. This may be the same as the path returned by
* lxc_cmd_get_cgroup_path if the container doesn't have a limiting path prefix
* set.
*
* @name : name of container to connect to
* @lxcpath : the lxcpath in which the container is running
* @subsystem : the subsystem being asked about
*
* Returns the path on success, NULL on failure. The caller must free() the
* returned path.
*/
char *lxc_cmd_get_limiting_cgroup_path(const char *name, const char *lxcpath,
const char *subsystem)
{
return lxc_cmd_get_cgroup_path_do(name, lxcpath, subsystem,
LXC_CMD_GET_LIMITING_CGROUP);
}
static int lxc_cmd_get_cgroup_callback_do(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler,
struct lxc_epoll_descr *descr,
bool limiting_cgroup)
{ {
int ret; int ret;
const char *path; const char *path;
const void *reqdata;
struct lxc_cmd_rsp rsp; struct lxc_cmd_rsp rsp;
struct cgroup_ops *cgroup_ops = handler->cgroup_ops; struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
const char *(*get_fn)(struct cgroup_ops *ops, const char *controller);
if (req->datalen > 0) { if (req->datalen > 0) {
ret = validate_string_request(fd, req); ret = validate_string_request(fd, req);
if (ret != 0) if (ret != 0)
return ret; return ret;
reqdata = req->data;
path = cgroup_ops->get_cgroup(cgroup_ops, req->data);
} else { } else {
path = cgroup_ops->get_cgroup(cgroup_ops, NULL); reqdata = NULL;
} }
get_fn = (limiting_cgroup ? cgroup_ops->get_cgroup
: cgroup_ops->get_limiting_cgroup);
path = get_fn(cgroup_ops, reqdata);
if (!path) if (!path)
return -1; return -1;
...@@ -557,6 +598,20 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req, ...@@ -557,6 +598,20 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
return 0; return 0;
} }
static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler,
struct lxc_epoll_descr *descr)
{
return lxc_cmd_get_cgroup_callback_do(fd, req, handler, descr, false);
}
static int lxc_cmd_get_limiting_cgroup_callback(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler,
struct lxc_epoll_descr *descr)
{
return lxc_cmd_get_cgroup_callback_do(fd, req, handler, descr, true);
}
/* /*
* lxc_cmd_get_config_item: Get config item the running container * lxc_cmd_get_config_item: Get config item the running container
* *
...@@ -1366,28 +1421,48 @@ int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath) ...@@ -1366,28 +1421,48 @@ int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath)
return PTR_TO_INT(cmd.rsp.data); return PTR_TO_INT(cmd.rsp.data);
} }
static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req, static int lxc_cmd_get_cgroup2_fd_callback_do(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler, struct lxc_handler *handler,
struct lxc_epoll_descr *descr) struct lxc_epoll_descr *descr,
bool limiting_cgroup)
{ {
struct lxc_cmd_rsp rsp = { struct lxc_cmd_rsp rsp = {
.ret = -EINVAL, .ret = -EINVAL,
}; };
struct cgroup_ops *ops = handler->cgroup_ops; struct cgroup_ops *ops = handler->cgroup_ops;
int ret; int ret, send_fd;
if (!pure_unified_layout(ops) || !ops->unified) if (!pure_unified_layout(ops) || !ops->unified)
return lxc_cmd_rsp_send(fd, &rsp); return lxc_cmd_rsp_send(fd, &rsp);
send_fd = limiting_cgroup ? ops->unified->cgfd_limit
: ops->unified->cgfd_con;
rsp.ret = 0; rsp.ret = 0;
ret = lxc_abstract_unix_send_fds(fd, &ops->unified->cgfd_con, 1, &rsp, ret = lxc_abstract_unix_send_fds(fd, &send_fd, 1, &rsp, sizeof(rsp));
sizeof(rsp));
if (ret < 0) if (ret < 0)
return log_error(LXC_CMD_REAP_CLIENT_FD, "Failed to send cgroup2 fd"); return log_error(LXC_CMD_REAP_CLIENT_FD, "Failed to send cgroup2 fd");
return 0; return 0;
} }
static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler,
struct lxc_epoll_descr *descr)
{
return lxc_cmd_get_cgroup2_fd_callback_do(fd, req, handler, descr,
false);
}
static int lxc_cmd_get_limiting_cgroup2_fd_callback(int fd,
struct lxc_cmd_req *req,
struct lxc_handler *handler,
struct lxc_epoll_descr *descr)
{
return lxc_cmd_get_cgroup2_fd_callback_do(fd, req, handler, descr,
true);
}
static int lxc_cmd_process(int fd, struct lxc_cmd_req *req, static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler, struct lxc_handler *handler,
struct lxc_epoll_descr *descr) struct lxc_epoll_descr *descr)
...@@ -1415,6 +1490,8 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req, ...@@ -1415,6 +1490,8 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
[LXC_CMD_UNFREEZE] = lxc_cmd_unfreeze_callback, [LXC_CMD_UNFREEZE] = lxc_cmd_unfreeze_callback,
[LXC_CMD_GET_CGROUP2_FD] = lxc_cmd_get_cgroup2_fd_callback, [LXC_CMD_GET_CGROUP2_FD] = lxc_cmd_get_cgroup2_fd_callback,
[LXC_CMD_GET_INIT_PIDFD] = lxc_cmd_get_init_pidfd_callback, [LXC_CMD_GET_INIT_PIDFD] = lxc_cmd_get_init_pidfd_callback,
[LXC_CMD_GET_LIMITING_CGROUP] = lxc_cmd_get_limiting_cgroup_callback,
[LXC_CMD_GET_LIMITING_CGROUP2_FD] = lxc_cmd_get_limiting_cgroup2_fd_callback,
}; };
if (req->cmd >= LXC_CMD_MAX) if (req->cmd >= LXC_CMD_MAX)
......
...@@ -38,6 +38,8 @@ typedef enum { ...@@ -38,6 +38,8 @@ typedef enum {
LXC_CMD_UNFREEZE, LXC_CMD_UNFREEZE,
LXC_CMD_GET_CGROUP2_FD, LXC_CMD_GET_CGROUP2_FD,
LXC_CMD_GET_INIT_PIDFD, LXC_CMD_GET_INIT_PIDFD,
LXC_CMD_GET_LIMITING_CGROUP,
LXC_CMD_GET_LIMITING_CGROUP2_FD,
LXC_CMD_MAX, LXC_CMD_MAX,
} lxc_cmd_t; } lxc_cmd_t;
...@@ -129,5 +131,9 @@ extern int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath, ...@@ -129,5 +131,9 @@ extern int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
extern int lxc_cmd_freeze(const char *name, const char *lxcpath, int timeout); extern int lxc_cmd_freeze(const char *name, const char *lxcpath, int timeout);
extern int lxc_cmd_unfreeze(const char *name, const char *lxcpath, int timeout); extern int lxc_cmd_unfreeze(const char *name, const char *lxcpath, int timeout);
extern int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath); extern int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath);
extern char *lxc_cmd_get_limiting_cgroup_path(const char *name,
const char *lxcpath,
const char *subsystem);
extern int lxc_cmd_get_limiting_cgroup2_fd(const char *name, const char *lxcpath);
#endif /* __commands_h */ #endif /* __commands_h */
...@@ -60,6 +60,9 @@ struct lxc_cgroup { ...@@ -60,6 +60,9 @@ struct lxc_cgroup {
struct /* meta */ { struct /* meta */ {
char *controllers; char *controllers;
char *dir; char *dir;
char *monitor_dir;
char *container_dir;
char *namespace_dir;
bool relative; bool relative;
}; };
}; };
......
...@@ -303,7 +303,7 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf, ...@@ -303,7 +303,7 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf,
* the handler the restore task created. * the handler the restore task created.
*/ */
if (!strcmp(opts->action, "dump") || !strcmp(opts->action, "pre-dump")) { if (!strcmp(opts->action, "dump") || !strcmp(opts->action, "pre-dump")) {
path = lxc_cmd_get_cgroup_path(opts->c->name, opts->c->config_path, controllers[0]); path = lxc_cmd_get_limiting_cgroup_path(opts->c->name, opts->c->config_path, controllers[0]);
if (!path) { if (!path) {
ERROR("failed to get cgroup path for %s", controllers[0]); ERROR("failed to get cgroup path for %s", controllers[0]);
goto err; goto err;
...@@ -311,7 +311,7 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf, ...@@ -311,7 +311,7 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf,
} else { } else {
const char *p; const char *p;
p = cgroup_ops->get_cgroup(cgroup_ops, controllers[0]); p = cgroup_ops->get_limiting_cgroup(cgroup_ops, controllers[0]);
if (!p) { if (!p) {
ERROR("failed to get cgroup path for %s", controllers[0]); ERROR("failed to get cgroup path for %s", controllers[0]);
goto err; goto err;
...@@ -406,9 +406,9 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf, ...@@ -406,9 +406,9 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf,
DECLARE_ARG("-t"); DECLARE_ARG("-t");
DECLARE_ARG(pid); DECLARE_ARG(pid);
freezer_relative = lxc_cmd_get_cgroup_path(opts->c->name, freezer_relative = lxc_cmd_get_limiting_cgroup_path(opts->c->name,
opts->c->config_path, opts->c->config_path,
"freezer"); "freezer");
if (!freezer_relative) { if (!freezer_relative) {
ERROR("failed getting freezer path"); ERROR("failed getting freezer path");
goto err; goto err;
......
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