Commit 9cfdea88 by Serge Hallyn Committed by Stéphane Graber

cgmanager: don't stay connected

There are only a few times when we need to be connected to the cgroup manager: * when starting a container, from cgm_init until we've set cgroup limits * when changing a cgroup setting (while running) * when cleaning up (when shutting down) * around the cgroup entering at attach So only connect/disconnect the cgmanager socket on-demand as needed. This should have a few benefits. 1. Reduce the # open fds when many containers are running 2. if cgmanager is stopped and restarted, the container doesn't have to deal with the disconnection. This is currently RFC. There are a few issues outstanding: 1. the cgm_set and cgm_get may need to be made thread-safe. 2. a non-daemonized start which fails while cgm is connected, will not disconnected. Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent f8f560f8
...@@ -92,13 +92,13 @@ static NihDBusProxy *cgroup_manager = NULL; ...@@ -92,13 +92,13 @@ static NihDBusProxy *cgroup_manager = NULL;
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;
#define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock" #define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock"
static void cgm_dbus_disconnected(DBusConnection *connection); static void cgm_dbus_disconnected(DBusConnection *connection);
static bool cgm_dbus_connect(void) static bool cgm_dbus_connect(void)
{ {
DBusError dbus_error; DBusError dbus_error;
DBusConnection *connection;
dbus_error_init(&dbus_error); dbus_error_init(&dbus_error);
lock_mutex(&thread_mutex); lock_mutex(&thread_mutex);
...@@ -118,7 +118,6 @@ static bool cgm_dbus_connect(void) ...@@ -118,7 +118,6 @@ static bool cgm_dbus_connect(void)
cgroup_manager = nih_dbus_proxy_new(NULL, connection, cgroup_manager = nih_dbus_proxy_new(NULL, connection,
NULL /* p2p */, NULL /* p2p */,
"/org/linuxcontainers/cgmanager", NULL, NULL); "/org/linuxcontainers/cgmanager", NULL, NULL);
dbus_connection_unref(connection);
if (!cgroup_manager) { if (!cgroup_manager) {
NihError *nerr; NihError *nerr;
nerr = nih_error_get(); nerr = nih_error_get();
...@@ -145,13 +144,19 @@ static void cgm_dbus_disconnect(void) ...@@ -145,13 +144,19 @@ static void cgm_dbus_disconnect(void)
if (cgroup_manager) if (cgroup_manager)
nih_free(cgroup_manager); nih_free(cgroup_manager);
cgroup_manager = NULL; cgroup_manager = NULL;
dbus_connection_unref(connection);
connection = NULL;
unlock_mutex(&thread_mutex); unlock_mutex(&thread_mutex);
} }
static void cgm_dbus_disconnected(DBusConnection *connection) static void cgm_dbus_disconnected(DBusConnection *connection)
{ {
lock_mutex(&thread_mutex);
WARN("Cgroup manager connection was terminated"); WARN("Cgroup manager connection was terminated");
cgroup_manager = NULL; cgroup_manager = NULL;
dbus_connection_unref(connection);
connection = NULL;
unlock_mutex(&thread_mutex);
if (cgm_dbus_connect()) { if (cgm_dbus_connect()) {
INFO("New cgroup manager connection was opened"); INFO("New cgroup manager connection was opened");
} else { } else {
...@@ -398,6 +403,7 @@ static void *cgm_init(const char *name) ...@@ -398,6 +403,7 @@ static void *cgm_init(const char *name)
{ {
struct cgm_data *d; struct cgm_data *d;
cgm_dbus_connect();
d = malloc(sizeof(*d)); d = malloc(sizeof(*d));
if (!d) if (!d)
return NULL; return NULL;
...@@ -430,6 +436,7 @@ static void cgm_destroy(void *hdata) ...@@ -430,6 +436,7 @@ static void cgm_destroy(void *hdata)
if (!d) if (!d)
return; return;
cgm_dbus_connect();
for (i = 0; i < nr_subsystems; i++) for (i = 0; i < nr_subsystems; i++)
cgm_remove_cgroup(subsystems[i], d->cgroup_path); cgm_remove_cgroup(subsystems[i], d->cgroup_path);
...@@ -437,6 +444,7 @@ static void cgm_destroy(void *hdata) ...@@ -437,6 +444,7 @@ 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();
} }
/* /*
...@@ -602,6 +610,7 @@ static int cgm_get(const char *filename, char *value, size_t len, const char *na ...@@ -602,6 +610,7 @@ static int cgm_get(const char *filename, char *value, size_t len, const char *na
cgroup = lxc_cmd_get_cgroup_path(name, lxcpath, controller); cgroup = lxc_cmd_get_cgroup_path(name, lxcpath, controller);
if (!cgroup) if (!cgroup)
return -1; return -1;
cgm_dbus_connect();
lock_mutex(&thread_mutex); lock_mutex(&thread_mutex);
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) {
/* /*
...@@ -614,9 +623,11 @@ static int cgm_get(const char *filename, char *value, size_t len, const char *na ...@@ -614,9 +623,11 @@ static int cgm_get(const char *filename, char *value, size_t len, const char *na
nih_free(nerr); nih_free(nerr);
free(cgroup); free(cgroup);
unlock_mutex(&thread_mutex); unlock_mutex(&thread_mutex);
cgm_dbus_disconnect();
return -1; return -1;
} }
unlock_mutex(&thread_mutex); unlock_mutex(&thread_mutex);
cgm_dbus_disconnect();
free(cgroup); free(cgroup);
newlen = strlen(result); newlen = strlen(result);
if (!value) { if (!value) {
...@@ -675,7 +686,9 @@ static int cgm_set(const char *filename, const char *value, const char *name, co ...@@ -675,7 +686,9 @@ static int cgm_set(const char *filename, const char *value, const char *name, co
controller, lxcpath, name); controller, lxcpath, name);
return -1; return -1;
} }
cgm_dbus_connect();
ret = cgm_do_set(controller, filename, cgroup, value); ret = cgm_do_set(controller, filename, cgroup, value);
cgm_dbus_disconnect();
free(cgroup); free(cgroup);
return ret; return ret;
} }
...@@ -875,8 +888,10 @@ static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid) ...@@ -875,8 +888,10 @@ static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid)
goto out; goto out;
} }
cgm_dbus_connect();
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);
......
...@@ -175,3 +175,9 @@ void restart_cgroups(void) ...@@ -175,3 +175,9 @@ void restart_cgroups(void)
ops = NULL; ops = NULL;
cgroup_ops_init(); cgroup_ops_init();
} }
void cgroup_disconnect(void)
{
if (ops && ops->disconnect)
ops->disconnect();
}
...@@ -66,5 +66,6 @@ extern int cgroup_nrtasks(struct lxc_handler *handler); ...@@ -66,5 +66,6 @@ extern int cgroup_nrtasks(struct lxc_handler *handler);
extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem); extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
extern bool cgroup_unfreeze(struct lxc_handler *handler); extern bool cgroup_unfreeze(struct lxc_handler *handler);
extern void restart_cgroups(void); extern void restart_cgroups(void);
extern void cgroup_disconnect(void);
#endif #endif
...@@ -952,6 +952,8 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -952,6 +952,8 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net; goto out_delete_net;
} }
cgroup_disconnect();
/* Tell the child to complete its initialization and wait for /* Tell the child to complete its initialization and wait for
* it to exec or return an error. (the child will never * it to exec or return an error. (the child will never
* return LXC_SYNC_POST_CGROUP+1. It will either close the * return LXC_SYNC_POST_CGROUP+1. It will either close the
......
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