return true;
}
-static inline bool cgm_supports_multiple_controllers(void)
+static bool cgm_supports_multiple_controllers;
+/*
+ * if cgm_all_controllers_same is true, then cgm_supports_multiple_controllers
+ * is true
+ */
+static bool cgm_all_controllers_same;
+
+static void check_supports_multiple_controllers(void)
{
- return api_version >= CGM_SUPPORTS_MULT_CONTROLLERS;
+ FILE *f;
+ char *line = NULL, *prevpath = NULL;
+ size_t sz = 0;
+
+ cgm_supports_multiple_controllers = false;
+ cgm_all_controllers_same = false;
+
+ if (api_version < CGM_SUPPORTS_MULT_CONTROLLERS) {
+ cgm_supports_multiple_controllers = false;
+ return;
+ }
+
+ cgm_supports_multiple_controllers = true;
+
+ f = fopen("/proc/self/cgroup", "r");
+ if (!f)
+ return;
+
+ cgm_all_controllers_same = true;
+
+ while (getline(&line, &sz, f) != -1) {
+ /* file format: hierarchy:subsystems:group */
+ char *colon;
+ if (!line[0])
+ continue;
+
+ colon = strchr(line, ':');
+ if (!colon)
+ continue;
+ colon = strchr(colon+1, ':');
+ if (!colon)
+ continue;
+ colon++;
+ if (!prevpath) {
+ prevpath = alloca(strlen(colon)+1);
+ strcpy(prevpath, colon);
+ continue;
+ }
+ if (strcmp(prevpath, colon) != 0) {
+ cgm_all_controllers_same = false;
+ fclose(f);
+ return;
+ }
+ }
+ fclose(f);
}
static int send_creds(int sock, int rpid, int ruid, int rgid)
char **slist = subsystems;
int i;
- if (cgm_supports_multiple_controllers())
+ if (cgm_all_controllers_same)
slist = subsystems_inone;
for (i = 0; slist[i]; i++) {
}
destuid = get_ns_uid(arg->origuid);
- if (cgm_supports_multiple_controllers())
+ if (cgm_supports_multiple_controllers)
slist = subsystems_inone;
for (i = 0; slist[i]; i++) {
* This can't be done in the child namespace because it only group-owns
* the cgroup
*/
- if (cgm_supports_multiple_controllers())
+ if (cgm_supports_multiple_controllers)
slist = subsystems_inone;
for (i = 0; slist[i]; i++) {
ERROR("Error connecting to cgroup manager");
return NULL;
}
+
+ check_supports_multiple_controllers();
+
d = malloc(sizeof(*d));
if (!d) {
cgm_dbus_disconnect();
return;
}
- if (cgm_supports_multiple_controllers())
+ if (cgm_supports_multiple_controllers)
slist = subsystems_inone;
for (i = 0; slist[i]; i++)
cgm_remove_cgroup(slist[i], d->cgroup_path);
int i;
char **slist = subsystems;
- if (cgm_supports_multiple_controllers())
+ if (cgm_supports_multiple_controllers)
slist = subsystems_inone;
for (i = 0; slist[i]; i++)
cgm_remove_cgroup(slist[i], path);
}
existed = 0;
- if (cgm_supports_multiple_controllers())
+ if (cgm_supports_multiple_controllers)
slist = subsystems_inone;
for (i = 0; slist[i]; i++) {
return true;
}
-/* Internal helper, must be called with cgmanager dbus socket open */
-static bool do_cgm_enter(pid_t pid, const char *cgroup_path, bool abs)
-{
- char **slist = subsystems;
- int i;
-
- if (cgm_supports_multiple_controllers())
- slist = subsystems_inone;
-
- for (i = 0; slist[i]; i++) {
- if (!lxc_cgmanager_enter(pid, slist[i], cgroup_path, abs))
- return false;
- }
- return true;
-}
-
static inline bool cgm_enter(void *hdata, pid_t pid)
{
struct cgm_data *d = hdata;
+ char **slist = subsystems;
bool ret = false;
+ int i;
+
+ if (!d || !d->cgroup_path)
+ return false;
if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager");
return false;
}
- if (!d || !d->cgroup_path)
- goto out;
- if (do_cgm_enter(pid, d->cgroup_path, false))
- ret = true;
+
+ if (cgm_all_controllers_same)
+ slist = subsystems_inone;
+
+ for (i = 0; slist[i]; i++) {
+ if (!lxc_cgmanager_enter(pid, slist[i], d->cgroup_path, false))
+ goto out;
+ }
+ ret = true;
out:
cgm_dbus_disconnect();
return ret;
WARN("Failed to warn cgm_get of error; parent may hang");
exit(1);
}
- cgroup = try_get_abs_cgroup(name, lxcpath, subsystems[0]);
+ cgroup = try_get_abs_cgroup(name, lxcpath, controller);
if (!cgroup) {
cgm_dbus_disconnect();
ret = write(outp, &len, sizeof(len));
WARN("Failed to warn cgm_set of error; parent may hang");
exit(1);
}
- cgroup = try_get_abs_cgroup(name, lxcpath, subsystems[0]);
+ cgroup = try_get_abs_cgroup(name, lxcpath, controller);
if (!cgroup) {
cgm_dbus_disconnect();
ret = write(outp, &retval, sizeof(retval));
*/
static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid)
{
- bool pass;
+ bool pass = true;
char *cgroup = NULL;
+ char **slist = subsystems;
+ int i;
if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager");
return false;
}
- // cgm_create makes sure that we have the same cgroup name for all
- // subsystems, so since this is a slow command over the cmd socket,
- // just get the cgroup name for the first one.
- cgroup = try_get_abs_cgroup(name, lxcpath, subsystems[0]);
- if (!cgroup) {
- ERROR("Failed to get cgroup for controller %s", subsystems[0]);
- cgm_dbus_disconnect();
- return false;
- }
- pass = do_cgm_enter(pid, cgroup, abs_cgroup_supported());
+ check_supports_multiple_controllers();
+
+ if (cgm_all_controllers_same)
+ slist = subsystems_inone;
+
+ for (i = 0; slist[i]; i++) {
+ cgroup = try_get_abs_cgroup(name, lxcpath, slist[i]);
+ if (!cgroup) {
+ ERROR("Failed to get cgroup for controller %s", slist[i]);
+ cgm_dbus_disconnect();
+ return false;
+ }
+
+ if (!lxc_cgmanager_enter(pid, slist[i], cgroup, abs_cgroup_supported())) {
+ pass = false;
+ break;
+ }
+
+ }
cgm_dbus_disconnect();
if (!pass)
ERROR("Failed to enter group %s", cgroup);