From: Serge Hallyn Date: Fri, 28 Feb 2014 23:50:22 +0000 (-0600) Subject: cgmanager: don't stay connected X-Git-Tag: lxc-1.1.0.alpha1~254 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=73d28d4295aea27abc38a309ba94b2046675abc1;p=thirdparty%2Flxc.git 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: Serge Hallyn Acked-by: Stéphane Graber --- diff --git a/src/lxc/cgmanager.c b/src/lxc/cgmanager.c index 73916756c..7be94a7b3 100644 --- a/src/lxc/cgmanager.c +++ b/src/lxc/cgmanager.c @@ -92,13 +92,13 @@ static NihDBusProxy *cgroup_manager = NULL; static struct cgroup_ops cgmanager_ops; static int nr_subsystems; static char **subsystems; +static DBusConnection *connection; #define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock" static void cgm_dbus_disconnected(DBusConnection *connection); static bool cgm_dbus_connect(void) { DBusError dbus_error; - DBusConnection *connection; dbus_error_init(&dbus_error); lock_mutex(&thread_mutex); @@ -118,7 +118,6 @@ static bool cgm_dbus_connect(void) cgroup_manager = nih_dbus_proxy_new(NULL, connection, NULL /* p2p */, "/org/linuxcontainers/cgmanager", NULL, NULL); - dbus_connection_unref(connection); if (!cgroup_manager) { NihError *nerr; nerr = nih_error_get(); @@ -145,13 +144,19 @@ static void cgm_dbus_disconnect(void) if (cgroup_manager) nih_free(cgroup_manager); cgroup_manager = NULL; + dbus_connection_unref(connection); + connection = NULL; unlock_mutex(&thread_mutex); } static void cgm_dbus_disconnected(DBusConnection *connection) { + lock_mutex(&thread_mutex); WARN("Cgroup manager connection was terminated"); cgroup_manager = NULL; + dbus_connection_unref(connection); + connection = NULL; + unlock_mutex(&thread_mutex); if (cgm_dbus_connect()) { INFO("New cgroup manager connection was opened"); } else { @@ -398,6 +403,7 @@ static void *cgm_init(const char *name) { struct cgm_data *d; + cgm_dbus_connect(); d = malloc(sizeof(*d)); if (!d) return NULL; @@ -430,6 +436,7 @@ static void cgm_destroy(void *hdata) if (!d) return; + cgm_dbus_connect(); for (i = 0; i < nr_subsystems; i++) cgm_remove_cgroup(subsystems[i], d->cgroup_path); @@ -437,6 +444,7 @@ static void cgm_destroy(void *hdata) if (d->cgroup_path) free(d->cgroup_path); free(d); + cgm_dbus_disconnect(); } /* @@ -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); if (!cgroup) return -1; + cgm_dbus_connect(); lock_mutex(&thread_mutex); 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 nih_free(nerr); free(cgroup); unlock_mutex(&thread_mutex); + cgm_dbus_disconnect(); return -1; } unlock_mutex(&thread_mutex); + cgm_dbus_disconnect(); free(cgroup); newlen = strlen(result); if (!value) { @@ -675,7 +686,9 @@ static int cgm_set(const char *filename, const char *value, const char *name, co controller, lxcpath, name); return -1; } + cgm_dbus_connect(); ret = cgm_do_set(controller, filename, cgroup, value); + cgm_dbus_disconnect(); free(cgroup); return ret; } @@ -875,8 +888,10 @@ static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid) goto out; } + cgm_dbus_connect(); if (!(pass = do_cgm_enter(pid, cgroup))) ERROR("Failed to enter group %s", cgroup); + cgm_dbus_disconnect(); out: free(cgroup); diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c index d931520b2..23c8c96e5 100644 --- a/src/lxc/cgroup.c +++ b/src/lxc/cgroup.c @@ -175,3 +175,9 @@ void restart_cgroups(void) ops = NULL; cgroup_ops_init(); } + +void cgroup_disconnect(void) +{ + if (ops && ops->disconnect) + ops->disconnect(); +} diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h index e3cf6e0ff..8cba03066 100644 --- a/src/lxc/cgroup.h +++ b/src/lxc/cgroup.h @@ -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 bool cgroup_unfreeze(struct lxc_handler *handler); extern void restart_cgroups(void); +extern void cgroup_disconnect(void); #endif diff --git a/src/lxc/start.c b/src/lxc/start.c index fe3d09335..97c82070d 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -952,6 +952,8 @@ static int lxc_spawn(struct lxc_handler *handler) goto out_delete_net; } + cgroup_disconnect(); + /* Tell the child to complete its initialization and wait for * it to exec or return an error. (the child will never * return LXC_SYNC_POST_CGROUP+1. It will either close the