return unprefix(controllers);
}
+#define CGFSNG_LAYOUT_LEGACY BIT(0)
+#define CGFSNG_LAYOUT_UNIFIED BIT(1)
+
static int __initialize_cgroups(struct cgroup_ops *ops, bool relative,
bool unprivileged)
{
__do_free char *cgroup_info = NULL;
+ unsigned int layout_mask = 0;
char *it;
/*
char *unified_mnt;
type = UNIFIED_HIERARCHY;
+ layout_mask |= CGFSNG_LAYOUT_UNIFIED;
current_cgroup = current_unified_cgroup(relative, line);
if (IS_ERR(current_cgroup))
char *__controllers, *__current_cgroup;
type = LEGACY_HIERARCHY;
+ layout_mask |= CGFSNG_LAYOUT_UNIFIED;
__controllers = strchr(line, ':');
if (!__controllers)
}
}
+ /*
+ * If we still don't know the cgroup layout at this point it means we
+ * have not found any writable cgroup hierarchies. Infer the layout
+ * from the layout bitmask we created when parsing the cgroups.
+ *
+ * Keep the ordering in the switch otherwise the bistmask-based
+ * matching won't work.
+ */
+ if (ops->cgroup_layout == CGROUP_LAYOUT_UNKNOWN) {
+ switch (layout_mask) {
+ case (CGFSNG_LAYOUT_LEGACY | CGFSNG_LAYOUT_UNIFIED):
+ ops->cgroup_layout = CGROUP_LAYOUT_HYBRID;
+ break;
+ case CGFSNG_LAYOUT_LEGACY:
+ ops->cgroup_layout = CGROUP_LAYOUT_LEGACY;
+ break;
+ case CGFSNG_LAYOUT_UNIFIED:
+ ops->cgroup_layout = CGROUP_LAYOUT_UNIFIED;
+ break;
+ }
+ }
+
if (!controllers_available(ops))
return syserror_set(-ENOENT, "One or more requested controllers unavailable or not delegated");
if (ret < 0)
return ret_errno(ENOSYS);
+ if (ctx->fd_len == 0)
+ return log_trace(0, "Container runs with unwritable %s cgroup layout",
+ cgroup_layout_name(ctx->layout));
+
pidstr_len = strnprintf(pidstr, sizeof(pidstr), "%d", pid);
if (pidstr_len < 0)
return pidstr_len;
TRACE("Attached to cgroup fd %d", dfd_con);
}
- if (idx == 0)
- return syserror_set(-ENOENT, "Failed to attach to cgroups");
-
TRACE("Attached to %s cgroup layout", cgroup_layout_name(ctx->layout));
return 0;
}
{
__u32 idx;
- if (!ops || !ops->hierarchies)
+ if (!ops)
return ret_errno(ENOENT);
+ /* Always let the client now what cgroup layout we're dealing with. */
+ ctx->layout = ops->cgroup_layout;
+
+ /* No writable cgroup hierarchies. */
+ if (!ops->hierarchies)
+ return 0;
+
for (idx = 0; ops->hierarchies[idx]; idx++) {
if (idx >= CGROUP_CTX_MAX_FD)
return ret_errno(E2BIG);
ctx->fd[idx] = ops->hierarchies[idx]->dfd_con;
}
-
- if (idx == 0)
- return ret_errno(ENOENT);
-
ctx->fd_len = idx;
- ctx->layout = ops->cgroup_layout;
+
if (ops->unified && ops->unified->dfd_con > 0)
ctx->utilities = ops->unified->utilities;
break;
case LXC_CMD_GET_CGROUP_CTX:
fds->fd_count_max = CGROUP_CTX_MAX_FD;
- fds->flags |= UNIX_FDS_ACCEPT_LESS;
+ /*
+ * The container might run without any cgroup support at all,
+ * i.e. no writable cgroup hierarchy was found.
+ */
+ fds->flags |= UNIX_FDS_ACCEPT_LESS | UNIX_FDS_ACCEPT_NONE ;
break;
default:
fds->fd_count_max = 0;
return sysdebug("Failed to process \"%s\"",
lxc_cmd_str(LXC_CMD_GET_CGROUP_CTX));
- if (cmd.rsp.ret < 0)
+ if (cmd.rsp.ret < 0) {
+ /* Container does not have any writable cgroups. */
+ if (ret_ctx->fd_len == 0)
+ return 0;
+
return sysdebug_set(cmd.rsp.ret, "Failed to receive file descriptor for \"%s\"",
lxc_cmd_str(LXC_CMD_GET_CGROUP_CTX));
+ }
return 0;
}