Commit 69a8b71b by Serge Hallyn Committed by Stéphane Graber

support use of 'all' containers when cgmanager supports it

Introduce a new list of controllers just containing "all". Make the lists of controllers null-terminated. If the cgmanager api version is high enough, use the 'all' controller rather than walking all controllers, which should greatly reduce the amount of dbus overhead. This will be especially important for those going through a cgproxy. Also remove the call to cleanup cgroups when a cgroup existed. That usually fails (and failure is ignored) since the to-be-cleaned-up cgroup is busy, but we shouldn't even be trying. Note this can create for extra un-cleanedup cgroups, however it's better than us accidentally removing a cgroup that someone else had created and was about to use. Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent 6d0bd793
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#define CGM_SUPPORTS_GET_ABS 3 #define CGM_SUPPORTS_GET_ABS 3
#define CGM_SUPPORTS_NAMED 4 #define CGM_SUPPORTS_NAMED 4
#define CGM_SUPPORTS_MULT_CONTROLLERS 10
#ifdef HAVE_CGMANAGER #ifdef HAVE_CGMANAGER
lxc_log_define(lxc_cgmanager, lxc); lxc_log_define(lxc_cgmanager, lxc);
...@@ -114,7 +115,7 @@ static int32_t api_version; ...@@ -114,7 +115,7 @@ static int32_t api_version;
static struct cgroup_ops cgmanager_ops; static struct cgroup_ops cgmanager_ops;
static int nr_subsystems; static int nr_subsystems;
static char **subsystems; static char **subsystems, **subsystems_inone;
static bool dbus_threads_initialized = false; static bool dbus_threads_initialized = false;
static void cull_user_controllers(void); static void cull_user_controllers(void);
...@@ -181,6 +182,11 @@ static bool cgm_dbus_connect(void) ...@@ -181,6 +182,11 @@ static bool cgm_dbus_connect(void)
return true; return true;
} }
static inline bool cgm_supports_multiple_controllers(void)
{
return api_version >= CGM_SUPPORTS_MULT_CONTROLLERS;
}
static int send_creds(int sock, int rpid, int ruid, int rgid) static int send_creds(int sock, int rpid, int ruid, int rgid)
{ {
struct msghdr msg = { 0 }; struct msghdr msg = { 0 };
...@@ -242,15 +248,19 @@ static bool lxc_cgmanager_escape(void) ...@@ -242,15 +248,19 @@ static bool lxc_cgmanager_escape(void)
{ {
bool ret = true; bool ret = true;
pid_t me = getpid(); pid_t me = getpid();
char **slist = subsystems;
int i; int i;
for (i = 0; i < nr_subsystems; i++) { if (cgm_supports_multiple_controllers())
slist = subsystems_inone;
for (i = 0; slist[i]; i++) {
if (cgmanager_move_pid_abs_sync(NULL, cgroup_manager, if (cgmanager_move_pid_abs_sync(NULL, cgroup_manager,
subsystems[i], "/", me) != 0) { slist[i], "/", me) != 0) {
NihError *nerr; NihError *nerr;
nerr = nih_error_get(); nerr = nih_error_get();
ERROR("call to cgmanager_move_pid_abs_sync(%s) failed: %s", ERROR("call to cgmanager_move_pid_abs_sync(%s) failed: %s",
subsystems[i], nerr->message); slist[i], nerr->message);
nih_free(nerr); nih_free(nerr);
ret = false; ret = false;
break; break;
...@@ -340,7 +350,8 @@ out: ...@@ -340,7 +350,8 @@ out:
static int chown_cgroup_wrapper(void *data) static int chown_cgroup_wrapper(void *data)
{ {
struct chown_data *arg = data; struct chown_data *arg = data;
int i; char **slist = subsystems;
int i, ret = -1;
uid_t destuid; uid_t destuid;
if (setresgid(0,0,0) < 0) if (setresgid(0,0,0) < 0)
...@@ -355,15 +366,21 @@ static int chown_cgroup_wrapper(void *data) ...@@ -355,15 +366,21 @@ static int chown_cgroup_wrapper(void *data)
return -1; return -1;
} }
destuid = get_ns_uid(arg->origuid); destuid = get_ns_uid(arg->origuid);
for (i = 0; i < nr_subsystems; i++) {
if (do_chown_cgroup(subsystems[i], arg->cgroup_path, destuid) < 0) { if (cgm_supports_multiple_controllers())
slist = subsystems_inone;
for (i = 0; slist[i]; i++) {
if (do_chown_cgroup(slist[i], arg->cgroup_path, destuid) < 0) {
ERROR("Failed to chown %s:%s to container root", ERROR("Failed to chown %s:%s to container root",
subsystems[i], arg->cgroup_path); slist[i], arg->cgroup_path);
return -1; goto fail;
} }
} }
ret = 0;
fail:
cgm_dbus_disconnect(); cgm_dbus_disconnect();
return 0; return ret;
} }
/* Internal helper. Must be called with the cgmanager dbus socket open */ /* Internal helper. Must be called with the cgmanager dbus socket open */
...@@ -385,6 +402,7 @@ static bool lxc_cgmanager_chmod(const char *controller, ...@@ -385,6 +402,7 @@ static bool lxc_cgmanager_chmod(const char *controller,
static bool chown_cgroup(const char *cgroup_path, struct lxc_conf *conf) static bool chown_cgroup(const char *cgroup_path, struct lxc_conf *conf)
{ {
struct chown_data data; struct chown_data data;
char **slist = subsystems;
int i; int i;
if (lxc_list_empty(&conf->id_map)) if (lxc_list_empty(&conf->id_map))
...@@ -407,12 +425,15 @@ static bool chown_cgroup(const char *cgroup_path, struct lxc_conf *conf) ...@@ -407,12 +425,15 @@ static bool chown_cgroup(const char *cgroup_path, struct lxc_conf *conf)
* This can't be done in the child namespace because it only group-owns * This can't be done in the child namespace because it only group-owns
* the cgroup * the cgroup
*/ */
for (i = 0; i < nr_subsystems; i++) { if (cgm_supports_multiple_controllers())
if (!lxc_cgmanager_chmod(subsystems[i], cgroup_path, "", 0775)) slist = subsystems_inone;
for (i = 0; slist[i]; i++) {
if (!lxc_cgmanager_chmod(slist[i], cgroup_path, "", 0775))
return false; return false;
if (!lxc_cgmanager_chmod(subsystems[i], cgroup_path, "tasks", 0775)) if (!lxc_cgmanager_chmod(slist[i], cgroup_path, "tasks", 0775))
return false; return false;
if (!lxc_cgmanager_chmod(subsystems[i], cgroup_path, "cgroup.procs", 0775)) if (!lxc_cgmanager_chmod(slist[i], cgroup_path, "cgroup.procs", 0775))
return false; return false;
} }
...@@ -478,6 +499,7 @@ err1: ...@@ -478,6 +499,7 @@ err1:
static void cgm_destroy(void *hdata) static void cgm_destroy(void *hdata)
{ {
struct cgm_data *d = hdata; struct cgm_data *d = hdata;
char **slist = subsystems;
int i; int i;
if (!d || !d->cgroup_path) if (!d || !d->cgroup_path)
...@@ -486,8 +508,11 @@ static void cgm_destroy(void *hdata) ...@@ -486,8 +508,11 @@ static void cgm_destroy(void *hdata)
ERROR("Error connecting to cgroup manager"); ERROR("Error connecting to cgroup manager");
return; return;
} }
for (i = 0; i < nr_subsystems; i++)
cgm_remove_cgroup(subsystems[i], d->cgroup_path); if (cgm_supports_multiple_controllers())
slist = subsystems_inone;
for (i = 0; slist[i]; i++)
cgm_remove_cgroup(slist[i], d->cgroup_path);
free(d->name); free(d->name);
if (d->cgroup_path) if (d->cgroup_path)
...@@ -503,13 +528,18 @@ static void cgm_destroy(void *hdata) ...@@ -503,13 +528,18 @@ static void cgm_destroy(void *hdata)
static inline void cleanup_cgroups(char *path) static inline void cleanup_cgroups(char *path)
{ {
int i; int i;
for (i = 0; i < nr_subsystems; i++) char **slist = subsystems;
cgm_remove_cgroup(subsystems[i], path);
if (cgm_supports_multiple_controllers())
slist = subsystems_inone;
for (i = 0; slist[i]; i++)
cgm_remove_cgroup(slist[i], path);
} }
static inline bool cgm_create(void *hdata) static inline bool cgm_create(void *hdata)
{ {
struct cgm_data *d = hdata; struct cgm_data *d = hdata;
char **slist = subsystems;
int i, index=0, baselen, ret; int i, index=0, baselen, ret;
int32_t existed; int32_t existed;
char result[MAXPATHLEN], *tmp, *cgroup_path; char result[MAXPATHLEN], *tmp, *cgroup_path;
...@@ -545,9 +575,13 @@ again: ...@@ -545,9 +575,13 @@ again:
goto bad; goto bad;
} }
existed = 0; existed = 0;
for (i = 0; i < nr_subsystems; i++) {
if (!lxc_cgmanager_create(subsystems[i], tmp, &existed)) { if (cgm_supports_multiple_controllers())
ERROR("Error creating cgroup %s:%s", subsystems[i], result); slist = subsystems_inone;
for (i = 0; slist[i]; i++) {
if (!lxc_cgmanager_create(slist[i], tmp, &existed)) {
ERROR("Error creating cgroup %s:%s", slist[i], result);
cleanup_cgroups(tmp); cleanup_cgroups(tmp);
goto bad; goto bad;
} }
...@@ -565,7 +599,6 @@ again: ...@@ -565,7 +599,6 @@ again:
return true; return true;
next: next:
cleanup_cgroups(tmp);
index++; index++;
goto again; goto again;
bad: bad:
...@@ -606,10 +639,14 @@ static bool lxc_cgmanager_enter(pid_t pid, const char *controller, ...@@ -606,10 +639,14 @@ static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
/* Internal helper, must be called with cgmanager dbus socket open */ /* Internal helper, must be called with cgmanager dbus socket open */
static bool do_cgm_enter(pid_t pid, const char *cgroup_path, bool abs) static bool do_cgm_enter(pid_t pid, const char *cgroup_path, bool abs)
{ {
char **slist = subsystems;
int i; int i;
for (i = 0; i < nr_subsystems; i++) { if (cgm_supports_multiple_controllers())
if (!lxc_cgmanager_enter(pid, subsystems[i], cgroup_path, abs)) slist = subsystems_inone;
for (i = 0; slist[i]; i++) {
if (!lxc_cgmanager_enter(pid, slist[i], cgroup_path, abs))
return false; return false;
} }
return true; return true;
...@@ -996,6 +1033,12 @@ static bool collect_subsytems(void) ...@@ -996,6 +1033,12 @@ static bool collect_subsytems(void)
if (subsystems) // already initialized if (subsystems) // already initialized
return true; return true;
subsystems_inone = malloc(2 * sizeof(char *));
if (!subsystems_inone)
return false;
subsystems_inone[0] = "all";
subsystems_inone[1] = NULL;
f = fopen_cloexec("/proc/self/cgroup", "r"); f = fopen_cloexec("/proc/self/cgroup", "r");
if (!f) { if (!f) {
f = fopen_cloexec("/proc/1/cgroup", "r"); f = fopen_cloexec("/proc/1/cgroup", "r");
...@@ -1022,12 +1065,13 @@ static bool collect_subsytems(void) ...@@ -1022,12 +1065,13 @@ static bool collect_subsytems(void)
for (p = strtok_r(slist, ",", &saveptr); for (p = strtok_r(slist, ",", &saveptr);
p; p;
p = strtok_r(NULL, ",", &saveptr)) { p = strtok_r(NULL, ",", &saveptr)) {
tmp = realloc(subsystems, (nr_subsystems+1)*sizeof(char *)); tmp = realloc(subsystems, (nr_subsystems+2)*sizeof(char *));
if (!tmp) if (!tmp)
goto out_free; goto out_free;
subsystems = tmp; subsystems = tmp;
tmp[nr_subsystems] = strdup(p); tmp[nr_subsystems] = strdup(p);
tmp[nr_subsystems+1] = NULL;
if (!tmp[nr_subsystems]) if (!tmp[nr_subsystems])
goto out_free; goto out_free;
nr_subsystems++; nr_subsystems++;
......
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