attach: don't pointlessly call cgroup_init()

We can let attach detect that it is running on a cgroup layout without
writable cgroup hierarchies. In that case attach can finish early and
doesn't need to run the heavy-handed cgroup parsing code.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2022-01-13 18:48:15 +01:00
parent 575704fe80
commit d979b58c38
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
3 changed files with 52 additions and 11 deletions

View File

@ -3116,10 +3116,14 @@ static const char *stable_order(const char *controllers)
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;
/*
@ -3147,6 +3151,7 @@ static int __initialize_cgroups(struct cgroup_ops *ops, bool relative,
char *unified_mnt;
type = UNIFIED_HIERARCHY;
layout_mask |= CGFSNG_LAYOUT_UNIFIED;
current_cgroup = current_unified_cgroup(relative, line);
if (IS_ERR(current_cgroup))
@ -3205,6 +3210,7 @@ static int __initialize_cgroups(struct cgroup_ops *ops, bool relative,
char *__controllers, *__current_cgroup;
type = LEGACY_HIERARCHY;
layout_mask |= CGFSNG_LAYOUT_UNIFIED;
__controllers = strchr(line, ':');
if (!__controllers)
@ -3309,6 +3315,28 @@ static int __initialize_cgroups(struct cgroup_ops *ops, bool relative,
}
}
/*
* 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");
@ -3470,6 +3498,10 @@ static int __cgroup_attach_many(const struct lxc_conf *conf, const char *name,
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;
@ -3487,9 +3519,6 @@ static int __cgroup_attach_many(const struct lxc_conf *conf, const char *name,
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;
}

View File

@ -327,21 +327,24 @@ static inline int prepare_cgroup_ctx(struct cgroup_ops *ops,
{
__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;

View File

@ -211,7 +211,11 @@ static ssize_t lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
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;
@ -762,9 +766,14 @@ int lxc_cmd_get_cgroup_ctx(const char *name, const char *lxcpath,
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;
}