cgmanager: switch to TLS

Drop the thread mutex.  Set a (TLS) boolean at container start to
indicate that the connection should be kept open;  set it back to false
only when container start is complete.  Every cgm_ method opens the
connection if not already open, and closes it if cgm_keep_connection
is false.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
This commit is contained in:
Serge Hallyn 2014-03-04 12:18:08 -06:00 committed by Stéphane Graber
parent 7e4dfe0bc1
commit b149d22a0e

View File

@ -54,28 +54,6 @@
#ifdef HAVE_CGMANAGER #ifdef HAVE_CGMANAGER
lxc_log_define(lxc_cgmanager, lxc); lxc_log_define(lxc_cgmanager, lxc);
static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
static void lock_mutex(pthread_mutex_t *l)
{
int ret;
if ((ret = pthread_mutex_lock(l)) != 0) {
fprintf(stderr, "pthread_mutex_lock returned:%d %s\n", ret, strerror(ret));
exit(1);
}
}
static void unlock_mutex(pthread_mutex_t *l)
{
int ret;
if ((ret = pthread_mutex_unlock(l)) != 0) {
fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret));
exit(1);
}
}
#include <nih-dbus/dbus_connection.h> #include <nih-dbus/dbus_connection.h>
#include <cgmanager/cgmanager-client.h> #include <cgmanager/cgmanager-client.h>
#include <nih/alloc.h> #include <nih/alloc.h>
@ -88,19 +66,37 @@ struct cgm_data {
const char *cgroup_pattern; const char *cgroup_pattern;
}; };
#ifdef HAVE_TLS
static __thread NihDBusProxy *cgroup_manager = NULL;
static __thread DBusConnection *connection = NULL;
static __thread bool cgm_keep_connection = false;
#else
static NihDBusProxy *cgroup_manager = NULL; static NihDBusProxy *cgroup_manager = NULL;
static DBusConnection *connection = NULL;
static bool cgm_keep_connection = false;
#endif
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;
static DBusConnection *connection;
static void cgm_dbus_disconnect(void)
{
cgm_keep_connection = false;
if (cgroup_manager)
nih_free(cgroup_manager);
cgroup_manager = NULL;
if (connection)
dbus_connection_unref(connection);
connection = NULL;
}
#define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock" #define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock"
static bool cgm_dbus_connect(void) static bool do_cgm_dbus_connect(void)
{ {
DBusError dbus_error; DBusError dbus_error;
dbus_error_init(&dbus_error); dbus_error_init(&dbus_error);
lock_mutex(&thread_mutex);
connection = nih_dbus_connect(CGMANAGER_DBUS_SOCK, NULL); connection = nih_dbus_connect(CGMANAGER_DBUS_SOCK, NULL);
if (!connection) { if (!connection) {
NihError *nerr; NihError *nerr;
@ -109,7 +105,6 @@ static bool cgm_dbus_connect(void)
nerr->message); nerr->message);
nih_free(nerr); nih_free(nerr);
dbus_error_free(&dbus_error); dbus_error_free(&dbus_error);
unlock_mutex(&thread_mutex);
return false; return false;
} }
dbus_connection_set_exit_on_disconnect(connection, FALSE); dbus_connection_set_exit_on_disconnect(connection, FALSE);
@ -122,7 +117,7 @@ static bool cgm_dbus_connect(void)
nerr = nih_error_get(); nerr = nih_error_get();
ERROR("Error opening cgmanager proxy: %s", nerr->message); ERROR("Error opening cgmanager proxy: %s", nerr->message);
nih_free(nerr); nih_free(nerr);
unlock_mutex(&thread_mutex); cgm_dbus_disconnect();
return false; return false;
} }
@ -132,19 +127,16 @@ static bool cgm_dbus_connect(void)
nerr = nih_error_get(); nerr = nih_error_get();
ERROR("Error pinging cgroup manager: %s", nerr->message); ERROR("Error pinging cgroup manager: %s", nerr->message);
nih_free(nerr); nih_free(nerr);
cgm_dbus_disconnect();
} }
return true; return true;
} }
static void cgm_dbus_disconnect(void) static bool cgm_dbus_connect(void)
{ {
if (cgroup_manager)
nih_free(cgroup_manager);
cgroup_manager = NULL;
if (connection) if (connection)
dbus_connection_unref(connection); return true;
connection = NULL; return do_cgm_dbus_connect();
unlock_mutex(&thread_mutex);
} }
static int send_creds(int sock, int rpid, int ruid, int rgid) static int send_creds(int sock, int rpid, int ruid, int rgid)
@ -183,11 +175,13 @@ static int send_creds(int sock, int rpid, int ruid, int rgid)
return 0; return 0;
} }
/*
* Called during container startup. The cgmanager socket is open
*/
static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path, int32_t *existed) static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path, int32_t *existed)
{ {
bool ret = true;
if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager");
return false;
}
if ( cgmanager_create_sync(NULL, cgroup_manager, controller, if ( cgmanager_create_sync(NULL, cgroup_manager, controller,
cgroup_path, existed) != 0) { cgroup_path, existed) != 0) {
NihError *nerr; NihError *nerr;
@ -195,16 +189,24 @@ static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path
ERROR("call to cgmanager_create_sync failed: %s", nerr->message); ERROR("call to cgmanager_create_sync failed: %s", nerr->message);
nih_free(nerr); nih_free(nerr);
ERROR("Failed to create %s:%s", controller, cgroup_path); ERROR("Failed to create %s:%s", controller, cgroup_path);
return false; ret = false;
} }
return true; if (!cgm_keep_connection)
cgm_dbus_disconnect();
return ret;
} }
static bool lxc_cgmanager_escape(void) static bool lxc_cgmanager_escape(void)
{ {
bool ret = true;
pid_t me = getpid(); pid_t me = getpid();
int i; int i;
if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager");
return false;
}
for (i = 0; i < nr_subsystems; i++) { for (i = 0; i < nr_subsystems; i++) {
if (cgmanager_move_pid_abs_sync(NULL, cgroup_manager, if (cgmanager_move_pid_abs_sync(NULL, cgroup_manager,
subsystems[i], "/", me) != 0) { subsystems[i], "/", me) != 0) {
@ -213,11 +215,14 @@ static bool lxc_cgmanager_escape(void)
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); subsystems[i], nerr->message);
nih_free(nerr); nih_free(nerr);
return false; ret = false;
break;
} }
} }
return true; if (!cgm_keep_connection)
cgm_dbus_disconnect();
return ret;
} }
struct chown_data { struct chown_data {
@ -313,9 +318,7 @@ static int chown_cgroup_wrapper(void *data)
return do_chown_cgroup(arg->controller, arg->cgroup_path, arg->origuid); return do_chown_cgroup(arg->controller, arg->cgroup_path, arg->origuid);
} }
/* /* Internal helper. Must be called with the cgmanager dbus socket open */
* Called during container startup. The cgmanager socket is open
*/
static bool lxc_cgmanager_chmod(const char *controller, static bool lxc_cgmanager_chmod(const char *controller,
const char *cgroup_path, const char *file, int mode) const char *cgroup_path, const char *file, int mode)
{ {
@ -330,9 +333,7 @@ static bool lxc_cgmanager_chmod(const char *controller,
return true; return true;
} }
/* /* Internal helper. Must be called with the cgmanager dbus socket open */
* Called during container startup. The cgmanager socket is open
*/
static bool chown_cgroup(const char *controller, const char *cgroup_path, static bool chown_cgroup(const char *controller, const char *cgroup_path,
struct lxc_conf *conf) struct lxc_conf *conf)
{ {
@ -358,10 +359,12 @@ static bool chown_cgroup(const char *controller, const char *cgroup_path,
return false; return false;
if (!lxc_cgmanager_chmod(controller, cgroup_path, "cgroup.procs", 0775)) if (!lxc_cgmanager_chmod(controller, cgroup_path, "cgroup.procs", 0775))
return false; return false;
return true; return true;
} }
#define CG_REMOVE_RECURSIVE 1 #define CG_REMOVE_RECURSIVE 1
/* Internal helper. Must be called with the cgmanager dbus socket open */
static void cgm_remove_cgroup(const char *controller, const char *path) static void cgm_remove_cgroup(const char *controller, const char *path)
{ {
int existed; int existed;
@ -378,8 +381,9 @@ static void cgm_remove_cgroup(const char *controller, const char *path)
} }
/* /*
* We are starting up a container. We open the cgmanager socket, and leave it * We are starting up a container. We open the cgmanager socket, and set
* open (and mutex held) for the rest of container startup. * cgm_keep_connection to true so that helpers will keep the connection
* open.
*/ */
static void *cgm_init(const char *name) static void *cgm_init(const char *name)
{ {
@ -390,13 +394,18 @@ static void *cgm_init(const char *name)
return NULL; return NULL;
} }
d = malloc(sizeof(*d)); d = malloc(sizeof(*d));
if (!d) if (!d) {
cgm_dbus_disconnect();
return NULL; return NULL;
}
memset(d, 0, sizeof(*d)); memset(d, 0, sizeof(*d));
d->name = strdup(name); d->name = strdup(name);
if (!d->name) if (!d->name) {
cgm_dbus_disconnect();
goto err1; goto err1;
}
cgm_keep_connection = true;
/* if we are running as root, use system cgroup pattern, otherwise /* if we are running as root, use system cgroup pattern, otherwise
* just create a cgroup under the current one. But also fall back to * just create a cgroup under the current one. But also fall back to
@ -414,10 +423,7 @@ err1:
return NULL; return NULL;
} }
/* /* Called after a failed container startup */
* Called after a failed container startup. The cgmanager socket was just
* closed at end of lxc_spawn. We need to re-open
*/
static void cgm_destroy(void *hdata) static void cgm_destroy(void *hdata)
{ {
struct cgm_data *d = hdata; struct cgm_data *d = hdata;
@ -436,11 +442,13 @@ static void cgm_destroy(void *hdata)
if (d->cgroup_path) if (d->cgroup_path)
free(d->cgroup_path); free(d->cgroup_path);
free(d); free(d);
cgm_dbus_disconnect(); if (!cgm_keep_connection)
cgm_dbus_disconnect();
} }
/* /*
* remove all the cgroups created * remove all the cgroups created
* called internally with dbus connection open
*/ */
static inline void cleanup_cgroups(char *path) static inline void cleanup_cgroups(char *path)
{ {
@ -449,9 +457,6 @@ static inline void cleanup_cgroups(char *path)
cgm_remove_cgroup(subsystems[i], path); cgm_remove_cgroup(subsystems[i], path);
} }
/*
* Called during container startup. The cgmanager socket is open
*/
static inline bool cgm_create(void *hdata) static inline bool cgm_create(void *hdata)
{ {
struct cgm_data *d = hdata; struct cgm_data *d = hdata;
@ -464,14 +469,18 @@ static inline bool cgm_create(void *hdata)
// XXX we should send a hint to the cgmanager that when these // XXX we should send a hint to the cgmanager that when these
// cgroups become empty they should be deleted. Requires a cgmanager // cgroups become empty they should be deleted. Requires a cgmanager
// extension // extension
if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager");
return false;
}
memset(result, 0, MAXPATHLEN); memset(result, 0, MAXPATHLEN);
tmp = lxc_string_replace("%n", d->name, d->cgroup_pattern); tmp = lxc_string_replace("%n", d->name, d->cgroup_pattern);
if (!tmp) if (!tmp)
return false; goto bad;
if (strlen(tmp) >= MAXPATHLEN) { if (strlen(tmp) >= MAXPATHLEN) {
free(tmp); free(tmp);
return false; goto bad;
} }
strcpy(result, tmp); strcpy(result, tmp);
baselen = strlen(result); baselen = strlen(result);
@ -482,19 +491,19 @@ static inline bool cgm_create(void *hdata)
again: again:
if (index == 100) { // turn this into a warn later if (index == 100) { // turn this into a warn later
ERROR("cgroup error? 100 cgroups with this name already running"); ERROR("cgroup error? 100 cgroups with this name already running");
return false; goto bad;
} }
if (index) { if (index) {
ret = snprintf(result+baselen, MAXPATHLEN-baselen, "-%d", index); ret = snprintf(result+baselen, MAXPATHLEN-baselen, "-%d", index);
if (ret < 0 || ret >= MAXPATHLEN-baselen) if (ret < 0 || ret >= MAXPATHLEN-baselen)
return false; goto bad;
} }
existed = 0; existed = 0;
for (i = 0; i < nr_subsystems; i++) { for (i = 0; i < nr_subsystems; i++) {
if (!lxc_cgmanager_create(subsystems[i], tmp, &existed)) { if (!lxc_cgmanager_create(subsystems[i], tmp, &existed)) {
ERROR("Error creating cgroup %s:%s", subsystems[i], result); ERROR("Error creating cgroup %s:%s", subsystems[i], result);
cleanup_cgroups(tmp); cleanup_cgroups(tmp);
return false; goto bad;
} }
if (existed == 1) if (existed == 1)
goto next; goto next;
@ -503,14 +512,20 @@ again:
cgroup_path = strdup(tmp); cgroup_path = strdup(tmp);
if (!cgroup_path) { if (!cgroup_path) {
cleanup_cgroups(tmp); cleanup_cgroups(tmp);
return false; goto bad;
} }
d->cgroup_path = cgroup_path; d->cgroup_path = cgroup_path;
if (!cgm_keep_connection)
cgm_dbus_disconnect();
return true; return true;
next: next:
cleanup_cgroups(tmp); cleanup_cgroups(tmp);
index++; index++;
goto again; goto again;
bad:
if (!cgm_keep_connection)
cgm_dbus_disconnect();
return false;
} }
/* /*
@ -518,6 +533,8 @@ next:
* hierarchy. * hierarchy.
* All the subsystems in this hierarchy are co-mounted, so we only * All the subsystems in this hierarchy are co-mounted, so we only
* need to transition the task into one of the cgroups * need to transition the task into one of the cgroups
*
* Internal helper, must be called with cgmanager dbus socket open
*/ */
static bool lxc_cgmanager_enter(pid_t pid, const char *controller, static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
const char *cgroup_path) const char *cgroup_path)
@ -533,6 +550,7 @@ static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
return true; return true;
} }
/* Internal helper, must be called with cgmanager dbus socket open */
static bool do_cgm_enter(pid_t pid, const char *cgroup_path) static bool do_cgm_enter(pid_t pid, const char *cgroup_path)
{ {
int i; int i;
@ -544,16 +562,23 @@ static bool do_cgm_enter(pid_t pid, const char *cgroup_path)
return true; return true;
} }
/*
* called during container startup. cgmanager socket is open
*/
static inline bool cgm_enter(void *hdata, pid_t pid) static inline bool cgm_enter(void *hdata, pid_t pid)
{ {
struct cgm_data *d = hdata; struct cgm_data *d = hdata;
bool ret = false;
if (!d || !d->cgroup_path) if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager");
return false; return false;
return do_cgm_enter(pid, d->cgroup_path); }
if (!d || !d->cgroup_path)
goto out;
if (do_cgm_enter(pid, d->cgroup_path))
ret = true;
out:
if (!cgm_keep_connection)
cgm_dbus_disconnect();
return ret;
} }
static const char *cgm_get_cgroup(void *hdata, const char *subsystem) static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
@ -569,6 +594,8 @@ static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
* nrtasks is called by the utmp helper by the container monitor. * nrtasks is called by the utmp helper by the container monitor.
* cgmanager socket was closed after cgroup setup was complete, so we need * cgmanager socket was closed after cgroup setup was complete, so we need
* to reopen here. * to reopen here.
*
* Return -1 on error.
*/ */
static int cgm_get_nrtasks(void *hdata) static int cgm_get_nrtasks(void *hdata)
{ {
@ -577,11 +604,11 @@ static int cgm_get_nrtasks(void *hdata)
size_t pids_len; size_t pids_len;
if (!d || !d->cgroup_path) if (!d || !d->cgroup_path)
return false; return -1;
if (!cgm_dbus_connect()) { if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager"); ERROR("Error connecting to cgroup manager");
return false; return -1;
} }
if (cgmanager_get_tasks_sync(NULL, cgroup_manager, subsystems[0], if (cgmanager_get_tasks_sync(NULL, cgroup_manager, subsystems[0],
d->cgroup_path, &pids, &pids_len) != 0) { d->cgroup_path, &pids, &pids_len) != 0) {
@ -589,18 +616,17 @@ static int cgm_get_nrtasks(void *hdata)
nerr = nih_error_get(); nerr = nih_error_get();
ERROR("call to cgmanager_get_tasks_sync failed: %s", nerr->message); ERROR("call to cgmanager_get_tasks_sync failed: %s", nerr->message);
nih_free(nerr); nih_free(nerr);
cgm_dbus_disconnect(); pids_len = -1;
return -1; goto out;
} }
nih_free(pids); nih_free(pids);
cgm_dbus_disconnect(); out:
if (!cgm_keep_connection)
cgm_dbus_disconnect();
return pids_len; return pids_len;
} }
/* /* cgm_get is called to get container cgroup settings, not during startup */
* cgm_get is called to get container cgroup settings. cgmanager is not
* connected.
*/
static int cgm_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath) static int cgm_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath)
{ {
char *result, *controller, *key, *cgroup; char *result, *controller, *key, *cgroup;
@ -619,7 +645,6 @@ static int cgm_get(const char *filename, char *value, size_t len, const char *na
return -1; return -1;
if (!cgm_dbus_connect()) { if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager"); ERROR("Error connecting to cgroup manager");
free(cgroup);
return -1; return -1;
} }
if (cgmanager_get_value_sync(NULL, cgroup_manager, controller, cgroup, filename, &result) != 0) { if (cgmanager_get_value_sync(NULL, cgroup_manager, controller, cgroup, filename, &result) != 0) {
@ -632,10 +657,12 @@ static int cgm_get(const char *filename, char *value, size_t len, const char *na
nerr = nih_error_get(); nerr = nih_error_get();
nih_free(nerr); nih_free(nerr);
free(cgroup); free(cgroup);
cgm_dbus_disconnect(); if (!cgm_keep_connection)
cgm_dbus_disconnect();
return -1; return -1;
} }
cgm_dbus_disconnect(); if (!cgm_keep_connection)
cgm_dbus_disconnect();
free(cgroup); free(cgroup);
newlen = strlen(result); newlen = strlen(result);
if (!value) { if (!value) {
@ -657,6 +684,7 @@ static int cgm_get(const char *filename, char *value, size_t len, const char *na
return newlen; return newlen;
} }
/* internal helper - call with cgmanager dbus connection open */
static int cgm_do_set(const char *controller, const char *file, static int cgm_do_set(const char *controller, const char *file,
const char *cgroup, const char *value) const char *cgroup, const char *value)
{ {
@ -673,9 +701,7 @@ static int cgm_do_set(const char *controller, const char *file,
return ret; return ret;
} }
/* /* cgm_set is called to change cgroup settings, not during startup */
* cgm_set is called to change cgroup settings. cgmanager is not connected
*/
static int cgm_set(const char *filename, const char *value, const char *name, const char *lxcpath) static int cgm_set(const char *filename, const char *value, const char *name, const char *lxcpath)
{ {
char *controller, *key, *cgroup; char *controller, *key, *cgroup;
@ -698,10 +724,11 @@ static int cgm_set(const char *filename, const char *value, const char *name, co
if (!cgm_dbus_connect()) { if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager"); ERROR("Error connecting to cgroup manager");
free(cgroup); free(cgroup);
return -1; return false;
} }
ret = cgm_do_set(controller, filename, cgroup, value); ret = cgm_do_set(controller, filename, cgroup, value);
cgm_dbus_disconnect(); if (!cgm_keep_connection)
cgm_dbus_disconnect();
free(cgroup); free(cgroup);
return ret; return ret;
} }
@ -710,13 +737,11 @@ static void free_subsystems(void)
{ {
int i; int i;
lock_mutex(&thread_mutex);
for (i = 0; i < nr_subsystems; i++) for (i = 0; i < nr_subsystems; i++)
free(subsystems[i]); free(subsystems[i]);
free(subsystems); free(subsystems);
subsystems = NULL; subsystems = NULL;
nr_subsystems = 0; nr_subsystems = 0;
unlock_mutex(&thread_mutex);
} }
static bool collect_subsytems(void) static bool collect_subsytems(void)
@ -728,10 +753,8 @@ static bool collect_subsytems(void)
if (subsystems) // already initialized if (subsystems) // already initialized
return true; return true;
lock_mutex(&thread_mutex);
f = fopen_cloexec("/proc/cgroups", "r"); f = fopen_cloexec("/proc/cgroups", "r");
if (!f) { if (!f) {
unlock_mutex(&thread_mutex);
return false; return false;
} }
while (getline(&line, &sz, f) != -1) { while (getline(&line, &sz, f) != -1) {
@ -756,8 +779,6 @@ static bool collect_subsytems(void)
} }
fclose(f); fclose(f);
unlock_mutex(&thread_mutex);
if (!nr_subsystems) { if (!nr_subsystems) {
ERROR("No cgroup subsystems found"); ERROR("No cgroup subsystems found");
return false; return false;
@ -767,7 +788,6 @@ static bool collect_subsytems(void)
out_free: out_free:
fclose(f); fclose(f);
unlock_mutex(&thread_mutex);
free_subsystems(); free_subsystems();
return false; return false;
} }
@ -785,10 +805,8 @@ struct cgroup_ops *cgm_ops_init(void)
goto err1; goto err1;
// root; try to escape to root cgroup // root; try to escape to root cgroup
if (geteuid() == 0 && !lxc_cgmanager_escape()) { if (geteuid() == 0 && !lxc_cgmanager_escape())
cgm_dbus_disconnect();
goto err2; goto err2;
}
cgm_dbus_disconnect(); cgm_dbus_disconnect();
return &cgmanager_ops; return &cgmanager_ops;
@ -800,13 +818,11 @@ err1:
return NULL; return NULL;
} }
/* /* unfreeze is called by the command api after killing a container. */
* unfreeze is called by the command api after killing a container.
* cgmanager is not connected.
*/
static bool cgm_unfreeze(void *hdata) static bool cgm_unfreeze(void *hdata)
{ {
struct cgm_data *d = hdata; struct cgm_data *d = hdata;
bool ret = true;
if (!d || !d->cgroup_path) if (!d || !d->cgroup_path)
return false; return false;
@ -822,17 +838,13 @@ static bool cgm_unfreeze(void *hdata)
ERROR("call to cgmanager_set_value_sync failed: %s", nerr->message); ERROR("call to cgmanager_set_value_sync failed: %s", nerr->message);
nih_free(nerr); nih_free(nerr);
ERROR("Error unfreezing %s", d->cgroup_path); ERROR("Error unfreezing %s", d->cgroup_path);
cgm_dbus_disconnect(); ret = false;
return false;
} }
cgm_dbus_disconnect(); if (!cgm_keep_connection)
return true; cgm_dbus_disconnect();
return ret;
} }
/*
* setup_limits is called during startup. cgmanager is connected, and mutex
* is held
*/
static bool cgm_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool do_devices) static bool cgm_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool do_devices)
{ {
struct cgm_data *d = hdata; struct cgm_data *d = hdata;
@ -846,6 +858,11 @@ static bool cgm_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool
if (!d || !d->cgroup_path) if (!d || !d->cgroup_path)
return false; return false;
if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager");
return false;
}
lxc_list_for_each(iterator, cgroup_settings) { lxc_list_for_each(iterator, cgroup_settings) {
char controller[100], *p; char controller[100], *p;
cg = iterator->elem; cg = iterator->elem;
@ -870,6 +887,8 @@ static bool cgm_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool
ret = true; ret = true;
INFO("cgroup limits have been setup"); INFO("cgroup limits have been setup");
out: out:
if (!cgm_keep_connection)
cgm_dbus_disconnect();
return ret; return ret;
} }
@ -880,11 +899,17 @@ static bool cgm_chown(void *hdata, struct lxc_conf *conf)
if (!d || !d->cgroup_path) if (!d || !d->cgroup_path)
return false; return false;
if (!cgm_dbus_connect()) {
ERROR("Error connecting to cgroup manager");
return false;
}
for (i = 0; i < nr_subsystems; i++) { for (i = 0; i < nr_subsystems; i++) {
if (!chown_cgroup(subsystems[i], d->cgroup_path, conf)) if (!chown_cgroup(subsystems[i], d->cgroup_path, conf))
WARN("Failed to chown %s:%s to container root", WARN("Failed to chown %s:%s to container root",
subsystems[i], d->cgroup_path); subsystems[i], d->cgroup_path);
} }
if (!cgm_keep_connection)
cgm_dbus_disconnect();
return true; return true;
} }
@ -907,9 +932,9 @@ static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid)
ERROR("Could not load container %s:%s", lxcpath, name); ERROR("Could not load container %s:%s", lxcpath, name);
return false; return false;
} }
if (!collect_subsytems()) { if (!cgm_dbus_connect()) {
ERROR("Error collecting cgroup subsystems"); ERROR("Error connecting to cgroup manager");
goto out; return false;
} }
// cgm_create makes sure that we have the same cgroup name for all // 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, // subsystems, so since this is a slow command over the cmd socket,
@ -926,11 +951,12 @@ static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid)
} }
if (!(pass = do_cgm_enter(pid, cgroup))) if (!(pass = do_cgm_enter(pid, cgroup)))
ERROR("Failed to enter group %s", cgroup); ERROR("Failed to enter group %s", cgroup);
cgm_dbus_disconnect();
out: out:
free(cgroup); free(cgroup);
lxc_container_put(c); lxc_container_put(c);
if (!cgm_keep_connection)
cgm_dbus_disconnect();
return pass; return pass;
} }