Unverified Commit a6e56873 by Christian Brauner Committed by GitHub

Merge pull request #3353 from Blub/lxc.cgroup.dir-components

introduce lxc.cgroup.dir.{monitor,container,container.inner}
parents 514b0270 e93197e7
...@@ -1573,6 +1573,53 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ...@@ -1573,6 +1573,53 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>lxc.cgroup.dir.container</option>
</term>
<listitem>
<para>
This is similar to <option>lxc.cgroup.dir</option>, but must be
used together with <option>lxc.cgroup.dir.monitor</option> and
affects only the container's cgroup path. This option is mutually
exclusive with <option>lxc.cgroup.dir</option>.
Note that the final path the container attaches to may be
extended further by the
<option>lxc.cgroup.dir.container.inner</option> option.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>lxc.cgroup.dir.monitor</option>
</term>
<listitem>
<para>
This is the monitor process counterpart to
<option>lxc.cgroup.dir.container</option>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>lxc.cgroup.dir.container.inner</option>
</term>
<listitem>
<para>
Specify an additional subdirectory where the cgroup namespace
will be created. With this option, the cgroup limits will be
applied to the outer path specified in
<option>lxc.cgroup.dir.container</option>, which is not accessible
from within the container, making it possible to better enforce
limits for privileged containers in a way they cannot override
them.
This only works in conjunction with the
<option>lxc.cgroup.dir.container</option> and
<option>lxc.cgroup.dir.monitor</option> options and has otherwise
no effect.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>lxc.cgroup.relative</option> <option>lxc.cgroup.relative</option>
</term> </term>
<listitem> <listitem>
......
...@@ -725,6 +725,7 @@ static struct hierarchy *add_hierarchy(struct hierarchy ***h, char **clist, char ...@@ -725,6 +725,7 @@ static struct hierarchy *add_hierarchy(struct hierarchy ***h, char **clist, char
new->container_base_path = container_base_path; new->container_base_path = container_base_path;
new->version = type; new->version = type;
new->cgfd_con = -EBADF; new->cgfd_con = -EBADF;
new->cgfd_limit = -EBADF;
new->cgfd_mon = -EBADF; new->cgfd_mon = -EBADF;
newentry = append_null_to_list((void ***)h); newentry = append_null_to_list((void ***)h);
...@@ -956,13 +957,15 @@ static int cgroup_tree_remove(struct hierarchy **hierarchies, ...@@ -956,13 +957,15 @@ static int cgroup_tree_remove(struct hierarchy **hierarchies,
struct hierarchy *h = hierarchies[i]; struct hierarchy *h = hierarchies[i];
int ret; int ret;
if (!h->container_full_path) if (!h->container_limit_path)
continue; continue;
ret = lxc_rm_rf(h->container_full_path); ret = lxc_rm_rf(h->container_limit_path);
if (ret < 0) if (ret < 0)
WARN("Failed to destroy \"%s\"", h->container_full_path); WARN("Failed to destroy \"%s\"", h->container_limit_path);
if (h->container_limit_path != h->container_full_path)
free_disarm(h->container_limit_path);
free_disarm(h->container_full_path); free_disarm(h->container_full_path);
} }
...@@ -1089,7 +1092,12 @@ __cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops, ...@@ -1089,7 +1092,12 @@ __cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops,
goto try_lxc_rm_rf; goto try_lxc_rm_rf;
} }
if (conf && conf->cgroup_meta.dir) if (conf && conf->cgroup_meta.monitor_dir)
pivot_path = must_make_path(h->mountpoint,
h->container_base_path,
conf->cgroup_meta.monitor_dir,
CGROUP_PIVOT, NULL);
else if (conf && conf->cgroup_meta.dir)
pivot_path = must_make_path(h->mountpoint, pivot_path = must_make_path(h->mountpoint,
h->container_base_path, h->container_base_path,
conf->cgroup_meta.dir, conf->cgroup_meta.dir,
...@@ -1147,7 +1155,8 @@ static int mkdir_eexist_on_last(const char *dir, mode_t mode) ...@@ -1147,7 +1155,8 @@ static int mkdir_eexist_on_last(const char *dir, mode_t mode)
} }
static bool cgroup_tree_create(struct hierarchy *h, const char *cgroup_tree, static bool cgroup_tree_create(struct hierarchy *h, const char *cgroup_tree,
const char *cgroup_leaf, bool payload) const char *cgroup_leaf, bool payload,
const char *cgroup_limit_dir)
{ {
__do_free char *path = NULL; __do_free char *path = NULL;
int ret, ret_cpuset; int ret, ret_cpuset;
...@@ -1176,6 +1185,16 @@ static bool cgroup_tree_create(struct hierarchy *h, const char *cgroup_tree, ...@@ -1176,6 +1185,16 @@ static bool cgroup_tree_create(struct hierarchy *h, const char *cgroup_tree,
if (h->cgfd_con < 0) if (h->cgfd_con < 0)
return log_error_errno(false, errno, "Failed to open %s", path); return log_error_errno(false, errno, "Failed to open %s", path);
h->container_full_path = move_ptr(path); h->container_full_path = move_ptr(path);
if (cgroup_limit_dir) {
path = must_make_path(h->mountpoint, h->container_base_path, cgroup_limit_dir, NULL);
h->cgfd_limit = lxc_open_dirfd(path);
if (h->cgfd_limit < 0)
return log_error_errno(false, errno, "Failed to open %s", path);
h->container_limit_path = move_ptr(path);
} else {
h->container_limit_path = h->container_full_path;
h->cgfd_limit = h->cgfd_con;
}
} else { } else {
h->cgfd_mon = lxc_open_dirfd(path); h->cgfd_mon = lxc_open_dirfd(path);
if (h->cgfd_mon < 0) if (h->cgfd_mon < 0)
...@@ -1188,11 +1207,15 @@ static bool cgroup_tree_create(struct hierarchy *h, const char *cgroup_tree, ...@@ -1188,11 +1207,15 @@ static bool cgroup_tree_create(struct hierarchy *h, const char *cgroup_tree,
static void cgroup_tree_leaf_remove(struct hierarchy *h, bool payload) static void cgroup_tree_leaf_remove(struct hierarchy *h, bool payload)
{ {
__do_free char *full_path = NULL; __do_free char *full_path = NULL, *__limit_path = NULL;
char *limit_path = NULL;
if (payload) { if (payload) {
__lxc_unused __do_close int fd = move_fd(h->cgfd_con); __lxc_unused __do_close int fd = move_fd(h->cgfd_con);
full_path = move_ptr(h->container_full_path); full_path = move_ptr(h->container_full_path);
limit_path = move_ptr(h->container_limit_path);
if (limit_path != full_path)
__limit_path = limit_path;
} else { } else {
__lxc_unused __do_close int fd = move_fd(h->cgfd_mon); __lxc_unused __do_close int fd = move_fd(h->cgfd_mon);
full_path = move_ptr(h->monitor_full_path); full_path = move_ptr(h->monitor_full_path);
...@@ -1200,6 +1223,38 @@ static void cgroup_tree_leaf_remove(struct hierarchy *h, bool payload) ...@@ -1200,6 +1223,38 @@ static void cgroup_tree_leaf_remove(struct hierarchy *h, bool payload)
if (full_path && rmdir(full_path)) if (full_path && rmdir(full_path))
SYSWARN("Failed to rmdir(\"%s\") cgroup", full_path); SYSWARN("Failed to rmdir(\"%s\") cgroup", full_path);
if (limit_path && rmdir(limit_path))
SYSWARN("Failed to rmdir(\"%s\") cgroup", limit_path);
}
/*
* Check we have no lxc.cgroup.dir, and that lxc.cgroup.dir.limit_prefix is a
* proper prefix directory of lxc.cgroup.dir.payload.
*
* Returns the prefix length if it is set, otherwise zero on success.
*/
static bool check_cgroup_dir_config(struct lxc_conf *conf)
{
const char *monitor_dir = conf->cgroup_meta.monitor_dir,
*container_dir = conf->cgroup_meta.container_dir,
*namespace_dir = conf->cgroup_meta.namespace_dir;
/* none of the new options are set, all is fine */
if (!monitor_dir && !container_dir && !namespace_dir)
return true;
/* some are set, make sure lxc.cgroup.dir is not also set*/
if (conf->cgroup_meta.dir)
return log_error_errno(false, EINVAL,
"lxc.cgroup.dir conflicts with lxc.cgroup.dir.payload/monitor");
/* make sure both monitor and payload are set */
if (!monitor_dir || !container_dir)
return log_error_errno(false, EINVAL,
"lxc.cgroup.dir.payload and lxc.cgroup.dir.monitor must both be set");
/* namespace_dir may be empty */
return true;
} }
__cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops, __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
...@@ -1210,7 +1265,7 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops, ...@@ -1210,7 +1265,7 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
int idx = 0; int idx = 0;
int i; int i;
size_t len; size_t len;
char *suffix; char *suffix = NULL;
struct lxc_conf *conf; struct lxc_conf *conf;
if (!ops) if (!ops)
...@@ -1227,7 +1282,13 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops, ...@@ -1227,7 +1282,13 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
conf = handler->conf; conf = handler->conf;
if (conf->cgroup_meta.dir) { if (!check_cgroup_dir_config(conf))
return false;
if (conf->cgroup_meta.monitor_dir) {
cgroup_tree = NULL;
monitor_cgroup = strdup(conf->cgroup_meta.monitor_dir);
} else if (conf->cgroup_meta.dir) {
cgroup_tree = conf->cgroup_meta.dir; cgroup_tree = conf->cgroup_meta.dir;
monitor_cgroup = must_concat(&len, conf->cgroup_meta.dir, "/", monitor_cgroup = must_concat(&len, conf->cgroup_meta.dir, "/",
DEFAULT_MONITOR_CGROUP_PREFIX, DEFAULT_MONITOR_CGROUP_PREFIX,
...@@ -1251,14 +1312,16 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops, ...@@ -1251,14 +1312,16 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
if (!monitor_cgroup) if (!monitor_cgroup)
return ret_set_errno(false, ENOMEM); return ret_set_errno(false, ENOMEM);
suffix = monitor_cgroup + len - CGROUP_CREATE_RETRY_LEN; if (!conf->cgroup_meta.monitor_dir) {
*suffix = '\0'; suffix = monitor_cgroup + len - CGROUP_CREATE_RETRY_LEN;
*suffix = '\0';
}
do { do {
if (idx) if (idx && suffix)
sprintf(suffix, "-%d", idx); sprintf(suffix, "-%d", idx);
for (i = 0; ops->hierarchies[i]; i++) { for (i = 0; ops->hierarchies[i]; i++) {
if (cgroup_tree_create(ops->hierarchies[i], cgroup_tree, monitor_cgroup, false)) if (cgroup_tree_create(ops->hierarchies[i], cgroup_tree, monitor_cgroup, false, NULL))
continue; continue;
ERROR("Failed to create cgroup \"%s\"", ops->hierarchies[i]->monitor_full_path ?: "(null)"); ERROR("Failed to create cgroup \"%s\"", ops->hierarchies[i]->monitor_full_path ?: "(null)");
...@@ -1268,9 +1331,9 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops, ...@@ -1268,9 +1331,9 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
idx++; idx++;
break; break;
} }
} while (ops->hierarchies[i] && idx > 0 && idx < 1000); } while (ops->hierarchies[i] && idx > 0 && idx < 1000 && suffix);
if (idx == 1000) if (idx == 1000 || (!suffix && idx != 0))
return ret_set_errno(false, ERANGE); return ret_set_errno(false, ERANGE);
ops->monitor_cgroup = move_ptr(monitor_cgroup); ops->monitor_cgroup = move_ptr(monitor_cgroup);
...@@ -1284,12 +1347,14 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops, ...@@ -1284,12 +1347,14 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
__cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops, __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops,
struct lxc_handler *handler) struct lxc_handler *handler)
{ {
__do_free char *container_cgroup = NULL, *__cgroup_tree = NULL; __do_free char *container_cgroup = NULL,
*__cgroup_tree = NULL,
*limiting_cgroup = NULL;
const char *cgroup_tree; const char *cgroup_tree;
int idx = 0; int idx = 0;
int i; int i;
size_t len; size_t len;
char *suffix; char *suffix = NULL;
struct lxc_conf *conf; struct lxc_conf *conf;
if (!ops) if (!ops)
...@@ -1306,7 +1371,20 @@ __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops, ...@@ -1306,7 +1371,20 @@ __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops,
conf = handler->conf; conf = handler->conf;
if (conf->cgroup_meta.dir) { if (!check_cgroup_dir_config(conf))
return false;
if (conf->cgroup_meta.container_dir) {
cgroup_tree = NULL;
limiting_cgroup = strdup(conf->cgroup_meta.container_dir);
if (!limiting_cgroup)
return ret_set_errno(false, ENOMEM);
container_cgroup = must_make_path(limiting_cgroup,
conf->cgroup_meta.namespace_dir,
NULL);
} else if (conf->cgroup_meta.dir) {
cgroup_tree = conf->cgroup_meta.dir; cgroup_tree = conf->cgroup_meta.dir;
container_cgroup = must_concat(&len, cgroup_tree, "/", container_cgroup = must_concat(&len, cgroup_tree, "/",
DEFAULT_PAYLOAD_CGROUP_PREFIX, DEFAULT_PAYLOAD_CGROUP_PREFIX,
...@@ -1330,14 +1408,18 @@ __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops, ...@@ -1330,14 +1408,18 @@ __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops,
if (!container_cgroup) if (!container_cgroup)
return ret_set_errno(false, ENOMEM); return ret_set_errno(false, ENOMEM);
suffix = container_cgroup + len - CGROUP_CREATE_RETRY_LEN; if (!conf->cgroup_meta.container_dir) {
*suffix = '\0'; suffix = container_cgroup + len - CGROUP_CREATE_RETRY_LEN;
*suffix = '\0';
}
do { do {
if (idx) if (idx && suffix)
sprintf(suffix, "-%d", idx); sprintf(suffix, "-%d", idx);
for (i = 0; ops->hierarchies[i]; i++) { for (i = 0; ops->hierarchies[i]; i++) {
if (cgroup_tree_create(ops->hierarchies[i], cgroup_tree, container_cgroup, true)) if (cgroup_tree_create(ops->hierarchies[i], cgroup_tree,
container_cgroup, true,
limiting_cgroup))
continue; continue;
ERROR("Failed to create cgroup \"%s\"", ops->hierarchies[i]->container_full_path ?: "(null)"); ERROR("Failed to create cgroup \"%s\"", ops->hierarchies[i]->container_full_path ?: "(null)");
...@@ -1347,9 +1429,9 @@ __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops, ...@@ -1347,9 +1429,9 @@ __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops,
idx++; idx++;
break; break;
} }
} while (ops->hierarchies[i] && idx > 0 && idx < 1000); } while (ops->hierarchies[i] && idx > 0 && idx < 1000 && suffix);
if (idx == 1000) if (idx == 1000 || (!suffix && idx != 0))
return ret_set_errno(false, ERANGE); return ret_set_errno(false, ERANGE);
ops->container_cgroup = move_ptr(container_cgroup); ops->container_cgroup = move_ptr(container_cgroup);
...@@ -2039,8 +2121,8 @@ __cgfsng_ops static int cgfsng_unfreeze(struct cgroup_ops *ops, int timeout) ...@@ -2039,8 +2121,8 @@ __cgfsng_ops static int cgfsng_unfreeze(struct cgroup_ops *ops, int timeout)
return cg_unified_unfreeze(ops, timeout); return cg_unified_unfreeze(ops, timeout);
} }
__cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops, static const char *cgfsng_get_cgroup_do(struct cgroup_ops *ops,
const char *controller) const char *controller, bool limiting)
{ {
struct hierarchy *h; struct hierarchy *h;
...@@ -2049,11 +2131,28 @@ __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops, ...@@ -2049,11 +2131,28 @@ __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops,
return log_warn_errno(NULL, ENOENT, "Failed to find hierarchy for controller \"%s\"", return log_warn_errno(NULL, ENOENT, "Failed to find hierarchy for controller \"%s\"",
controller ? controller : "(null)"); controller ? controller : "(null)");
if (limiting)
return h->container_limit_path
? h->container_limit_path + strlen(h->mountpoint)
: NULL;
return h->container_full_path return h->container_full_path
? h->container_full_path + strlen(h->mountpoint) ? h->container_full_path + strlen(h->mountpoint)
: NULL; : NULL;
} }
__cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops,
const char *controller)
{
return cgfsng_get_cgroup_do(ops, controller, false);
}
__cgfsng_ops static const char *cgfsng_get_limiting_cgroup(struct cgroup_ops *ops,
const char *controller)
{
return cgfsng_get_cgroup_do(ops, controller, true);
}
/* Given a cgroup path returned from lxc_cmd_get_cgroup_path, build a full path, /* Given a cgroup path returned from lxc_cmd_get_cgroup_path, build a full path,
* which must be freed by the caller. * which must be freed by the caller.
*/ */
...@@ -2382,7 +2481,7 @@ __cgfsng_ops static int cgfsng_get(struct cgroup_ops *ops, const char *filename, ...@@ -2382,7 +2481,7 @@ __cgfsng_ops static int cgfsng_get(struct cgroup_ops *ops, const char *filename,
if (p) if (p)
*p = '\0'; *p = '\0';
path = lxc_cmd_get_cgroup_path(name, lxcpath, controller); path = lxc_cmd_get_limiting_cgroup_path(name, lxcpath, controller);
/* not running */ /* not running */
if (!path) if (!path)
return -1; return -1;
...@@ -2547,7 +2646,7 @@ __cgfsng_ops static int cgfsng_set(struct cgroup_ops *ops, ...@@ -2547,7 +2646,7 @@ __cgfsng_ops static int cgfsng_set(struct cgroup_ops *ops,
return 0; return 0;
} }
path = lxc_cmd_get_cgroup_path(name, lxcpath, controller); path = lxc_cmd_get_limiting_cgroup_path(name, lxcpath, controller);
/* not running */ /* not running */
if (!path) if (!path)
return -1; return -1;
...@@ -2657,7 +2756,7 @@ static int convert_devpath(const char *invalue, char *dest) ...@@ -2657,7 +2756,7 @@ static int convert_devpath(const char *invalue, char *dest)
* we created the cgroups. * we created the cgroups.
*/ */
static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename, static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename,
const char *value) const char *value, bool is_cpuset)
{ {
__do_free char *controller = NULL; __do_free char *controller = NULL;
char *p; char *p;
...@@ -2683,7 +2782,12 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename, ...@@ -2683,7 +2782,12 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename,
if (!h) if (!h)
return log_error_errno(-ENOENT, ENOENT, "Failed to setup limits for the \"%s\" controller. The controller seems to be unused by \"cgfsng\" cgroup driver or not enabled on the cgroup hierarchy", controller); return log_error_errno(-ENOENT, ENOENT, "Failed to setup limits for the \"%s\" controller. The controller seems to be unused by \"cgfsng\" cgroup driver or not enabled on the cgroup hierarchy", controller);
return lxc_write_openat(h->container_full_path, filename, value, strlen(value)); if (is_cpuset) {
int ret = lxc_write_openat(h->container_full_path, filename, value, strlen(value));
if (ret)
return ret;
}
return lxc_write_openat(h->container_limit_path, filename, value, strlen(value));
} }
__cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops, __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
...@@ -2717,7 +2821,7 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops, ...@@ -2717,7 +2821,7 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
cg = iterator->elem; cg = iterator->elem;
if (do_devices == !strncmp("devices", cg->subsystem, 7)) { if (do_devices == !strncmp("devices", cg->subsystem, 7)) {
if (cg_legacy_set_data(ops, cg->subsystem, cg->value)) { if (cg_legacy_set_data(ops, cg->subsystem, cg->value, strncmp("cpuset", cg->subsystem, 6) == 0)) {
if (do_devices && (errno == EACCES || errno == EPERM)) { if (do_devices && (errno == EACCES || errno == EPERM)) {
SYSWARN("Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value); SYSWARN("Failed to set \"%s\" to \"%s\"", cg->subsystem, cg->value);
continue; continue;
...@@ -2802,7 +2906,7 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops, ...@@ -2802,7 +2906,7 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem, ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem,
cg->value); cg->value);
} else { } else {
ret = lxc_write_openat(h->container_full_path, ret = lxc_write_openat(h->container_limit_path,
cg->subsystem, cg->value, cg->subsystem, cg->value,
strlen(cg->value)); strlen(cg->value));
if (ret < 0) if (ret < 0)
...@@ -2878,7 +2982,7 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops, ...@@ -2878,7 +2982,7 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops,
return log_error_errno(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_limit_path,
BPF_F_ALLOW_MULTI); BPF_F_ALLOW_MULTI);
if (ret) if (ret)
return log_error_errno(false, ENOMEM, "Failed to attach bpf program"); return log_error_errno(false, ENOMEM, "Failed to attach bpf program");
...@@ -3323,6 +3427,7 @@ struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf) ...@@ -3323,6 +3427,7 @@ struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf)
cgfsng_ops->chown = cgfsng_chown; cgfsng_ops->chown = cgfsng_chown;
cgfsng_ops->mount = cgfsng_mount; cgfsng_ops->mount = cgfsng_mount;
cgfsng_ops->devices_activate = cgfsng_devices_activate; cgfsng_ops->devices_activate = cgfsng_devices_activate;
cgfsng_ops->get_limiting_cgroup = cgfsng_get_limiting_cgroup;
return move_ptr(cgfsng_ops); return move_ptr(cgfsng_ops);
} }
...@@ -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 */
...@@ -3832,6 +3832,9 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -3832,6 +3832,9 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_apparmor_raw(conf); lxc_clear_apparmor_raw(conf);
lxc_clear_namespace(conf); lxc_clear_namespace(conf);
free(conf->cgroup_meta.dir); free(conf->cgroup_meta.dir);
free(conf->cgroup_meta.monitor_dir);
free(conf->cgroup_meta.container_dir);
free(conf->cgroup_meta.namespace_dir);
free(conf->cgroup_meta.controllers); free(conf->cgroup_meta.controllers);
free(conf->shmount.path_host); free(conf->shmount.path_host);
free(conf->shmount.path_cont); free(conf->shmount.path_cont);
......
...@@ -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;
}; };
}; };
......
...@@ -71,6 +71,9 @@ lxc_config_define(cap_keep); ...@@ -71,6 +71,9 @@ lxc_config_define(cap_keep);
lxc_config_define(cgroup_controller); lxc_config_define(cgroup_controller);
lxc_config_define(cgroup2_controller); lxc_config_define(cgroup2_controller);
lxc_config_define(cgroup_dir); lxc_config_define(cgroup_dir);
lxc_config_define(cgroup_monitor_dir);
lxc_config_define(cgroup_container_dir);
lxc_config_define(cgroup_container_inner_dir);
lxc_config_define(cgroup_relative); lxc_config_define(cgroup_relative);
lxc_config_define(console_buffer_size); lxc_config_define(console_buffer_size);
lxc_config_define(console_logfile); lxc_config_define(console_logfile);
...@@ -170,6 +173,9 @@ static struct lxc_config_t config_jump_table[] = { ...@@ -170,6 +173,9 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.cap.drop", set_config_cap_drop, get_config_cap_drop, clr_config_cap_drop, }, { "lxc.cap.drop", set_config_cap_drop, get_config_cap_drop, clr_config_cap_drop, },
{ "lxc.cap.keep", set_config_cap_keep, get_config_cap_keep, clr_config_cap_keep, }, { "lxc.cap.keep", set_config_cap_keep, get_config_cap_keep, clr_config_cap_keep, },
{ "lxc.cgroup2", set_config_cgroup2_controller, get_config_cgroup2_controller, clr_config_cgroup2_controller, }, { "lxc.cgroup2", set_config_cgroup2_controller, get_config_cgroup2_controller, clr_config_cgroup2_controller, },
{ "lxc.cgroup.dir.monitor", set_config_cgroup_monitor_dir, get_config_cgroup_monitor_dir, clr_config_cgroup_monitor_dir, },
{ "lxc.cgroup.dir.container", set_config_cgroup_container_dir, get_config_cgroup_container_dir, clr_config_cgroup_container_dir, },
{ "lxc.cgroup.dir.container.inner",set_config_cgroup_container_inner_dir, get_config_cgroup_container_inner_dir, clr_config_cgroup_container_inner_dir,},
{ "lxc.cgroup.dir", set_config_cgroup_dir, get_config_cgroup_dir, clr_config_cgroup_dir, }, { "lxc.cgroup.dir", set_config_cgroup_dir, get_config_cgroup_dir, clr_config_cgroup_dir, },
{ "lxc.cgroup.relative", set_config_cgroup_relative, get_config_cgroup_relative, clr_config_cgroup_relative, }, { "lxc.cgroup.relative", set_config_cgroup_relative, get_config_cgroup_relative, clr_config_cgroup_relative, },
{ "lxc.cgroup", set_config_cgroup_controller, get_config_cgroup_controller, clr_config_cgroup_controller, }, { "lxc.cgroup", set_config_cgroup_controller, get_config_cgroup_controller, clr_config_cgroup_controller, },
...@@ -1721,6 +1727,43 @@ static int set_config_cgroup_dir(const char *key, const char *value, ...@@ -1721,6 +1727,43 @@ static int set_config_cgroup_dir(const char *key, const char *value,
return set_config_string_item(&lxc_conf->cgroup_meta.dir, value); return set_config_string_item(&lxc_conf->cgroup_meta.dir, value);
} }
static int set_config_cgroup_monitor_dir(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
if (lxc_config_value_empty(value))
return clr_config_cgroup_monitor_dir(key, lxc_conf, NULL);
return set_config_string_item(&lxc_conf->cgroup_meta.monitor_dir,
value);
}
static int set_config_cgroup_container_dir(const char *key, const char *value,
struct lxc_conf *lxc_conf,
void *data)
{
if (lxc_config_value_empty(value))
return clr_config_cgroup_container_dir(key, lxc_conf, NULL);
return set_config_string_item(&lxc_conf->cgroup_meta.container_dir,
value);
}
static int set_config_cgroup_container_inner_dir(const char *key,
const char *value,
struct lxc_conf *lxc_conf,
void *data)
{
if (lxc_config_value_empty(value))
return clr_config_cgroup_container_inner_dir(key, lxc_conf, NULL);
if (strchr(value, '/') ||
strcmp(value, ".") == 0 ||
strcmp(value, "..") == 0)
return log_error_errno(-EINVAL, EINVAL, "lxc.cgroup.dir.container.inner must be a single directory name");
return set_config_string_item(&lxc_conf->cgroup_meta.namespace_dir, value);
}
static int set_config_cgroup_relative(const char *key, const char *value, static int set_config_cgroup_relative(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
...@@ -3644,6 +3687,58 @@ static int get_config_cgroup_dir(const char *key, char *retv, int inlen, ...@@ -3644,6 +3687,58 @@ static int get_config_cgroup_dir(const char *key, char *retv, int inlen,
return fulllen; return fulllen;
} }
static int get_config_cgroup_monitor_dir(const char *key, char *retv, int inlen,
struct lxc_conf *lxc_conf, void *data)
{
int len;
int fulllen = 0;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.monitor_dir);
return fulllen;
}
static int get_config_cgroup_container_dir(const char *key, char *retv,
int inlen,
struct lxc_conf *lxc_conf,
void *data)
{
int len;
int fulllen = 0;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.container_dir);
return fulllen;
}
static int get_config_cgroup_container_inner_dir(const char *key, char *retv,
int inlen,
struct lxc_conf *lxc_conf,
void *data)
{
int len;
int fulllen = 0;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
strprint(retv, inlen, "%s", lxc_conf->cgroup_meta.namespace_dir);
return fulllen;
}
static inline int get_config_cgroup_relative(const char *key, char *retv, static inline int get_config_cgroup_relative(const char *key, char *retv,
int inlen, struct lxc_conf *lxc_conf, int inlen, struct lxc_conf *lxc_conf,
void *data) void *data)
...@@ -4458,6 +4553,30 @@ static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf, ...@@ -4458,6 +4553,30 @@ static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf,
return 0; return 0;
} }
static int clr_config_cgroup_monitor_dir(const char *key,
struct lxc_conf *lxc_conf,
void *data)
{
free_disarm(lxc_conf->cgroup_meta.monitor_dir);
return 0;
}
static int clr_config_cgroup_container_dir(const char *key,
struct lxc_conf *lxc_conf,
void *data)
{
free_disarm(lxc_conf->cgroup_meta.container_dir);
return 0;
}
static int clr_config_cgroup_container_inner_dir(const char *key,
struct lxc_conf *lxc_conf,
void *data)
{
free_disarm(lxc_conf->cgroup_meta.namespace_dir);
return 0;
}
static inline int clr_config_cgroup_relative(const char *key, static inline int clr_config_cgroup_relative(const char *key,
struct lxc_conf *lxc_conf, struct lxc_conf *lxc_conf,
void *data) void *data)
......
...@@ -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