summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-05-31 19:46:42 +0200
committerLennart Poettering <lennart@poettering.net>2012-05-31 19:46:42 +0200
commit8c8c43515cee56dfc2298998a9e5958308c46f99 (patch)
tree3d7f891b8478df86683058b9a0e160c69b5c6c8b
parent952d817a41dfe207d159f8278f4d7f1f7654c572 (diff)
logind: properly clean up user cgroups when they run empty
-rw-r--r--src/login/logind-session.c6
-rw-r--r--src/login/logind-user.c6
-rw-r--r--src/login/logind.c65
-rw-r--r--src/login/logind.h5
4 files changed, 70 insertions, 12 deletions
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 5c8d54931..58514ea0d 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -85,13 +85,13 @@ void session_free(Session *s) {
s->seat->active = NULL;
LIST_REMOVE(Session, sessions_by_seat, s->seat->sessions, s);
}
if (s->cgroup_path)
- hashmap_remove(s->manager->cgroups, s->cgroup_path);
+ hashmap_remove(s->manager->session_cgroups, s->cgroup_path);
free(s->cgroup_path);
strv_free(s->controllers);
free(s->tty);
free(s->display);
@@ -524,13 +524,13 @@ static int session_create_cgroup(Session *s) {
if (r < 0)
log_warning("Failed to reset controller %s: %s", *k, strerror(-r));
}
}
- hashmap_put(s->manager->cgroups, s->cgroup_path, s);
+ hashmap_put(s->manager->session_cgroups, s->cgroup_path, s);
return 0;
}
int session_start(Session *s) {
int r;
@@ -643,13 +643,13 @@ static int session_terminate_cgroup(Session *s) {
}
}
STRV_FOREACH(k, s->user->manager->controllers)
cg_trim(*k, s->cgroup_path, true);
- hashmap_remove(s->manager->cgroups, s->cgroup_path);
+ hashmap_remove(s->manager->session_cgroups, s->cgroup_path);
free(s->cgroup_path);
s->cgroup_path = NULL;
return 0;
}
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index b971845e1..8bd773086 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -72,12 +72,14 @@ void user_free(User *u) {
if (u->in_gc_queue)
LIST_REMOVE(User, gc_queue, u->manager->user_gc_queue, u);
while (u->sessions)
session_free(u->sessions);
+ if (u->cgroup_path)
+ hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
free(u->cgroup_path);
free(u->service);
free(u->runtime_path);
hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
@@ -310,12 +312,14 @@ static int user_create_cgroup(User *u) {
r = cg_create(*k, p);
if (r < 0)
log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r));
}
+ hashmap_put(u->manager->user_cgroups, u->cgroup_path, u);
+
return 0;
}
static int user_start_service(User *u) {
assert(u);
@@ -414,12 +418,14 @@ static int user_terminate_cgroup(User *u) {
r = -EBUSY;
}
STRV_FOREACH(k, u->manager->controllers)
cg_trim(*k, u->cgroup_path, true);
+ hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
+
free(u->cgroup_path);
u->cgroup_path = NULL;
return r;
}
diff --git a/src/login/logind.c b/src/login/logind.c
index 632987c8b..62f7914fe 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -61,19 +61,22 @@ Manager *manager_new(void) {
m->seats = hashmap_new(string_hash_func, string_compare_func);
m->sessions = hashmap_new(string_hash_func, string_compare_func);
m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
m->buttons = hashmap_new(string_hash_func, string_compare_func);
- m->cgroups = hashmap_new(string_hash_func, string_compare_func);
+ m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
+ m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
+
m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
- !m->cgroups || !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
+ !m->user_cgroups || !m->session_cgroups ||
+ !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
manager_free(m);
return NULL;
}
m->reset_controllers = strv_new("cpu", NULL);
m->kill_exclude_users = strv_new("root", NULL);
@@ -128,13 +131,15 @@ void manager_free(Manager *m) {
hashmap_free(m->seats);
hashmap_free(m->sessions);
hashmap_free(m->users);
hashmap_free(m->inhibitors);
hashmap_free(m->buttons);
- hashmap_free(m->cgroups);
+ hashmap_free(m->user_cgroups);
+ hashmap_free(m->session_cgroups);
+
hashmap_free(m->session_fds);
hashmap_free(m->inhibitor_fds);
hashmap_free(m->button_fds);
if (m->console_active_fd >= 0)
close_nointr_nofail(m->console_active_fd);
@@ -1005,13 +1010,13 @@ int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **sess
char *p;
assert(m);
assert(cgroup);
assert(session);
- s = hashmap_get(m->cgroups, cgroup);
+ s = hashmap_get(m->session_cgroups, cgroup);
if (s) {
*session = s;
return 1;
}
p = strdup(cgroup);
@@ -1029,21 +1034,62 @@ int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **sess
*session = NULL;
return 0;
}
*e = 0;
- s = hashmap_get(m->cgroups, p);
+ s = hashmap_get(m->session_cgroups, p);
if (s) {
free(p);
*session = s;
return 1;
}
}
}
+int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
+ User *u;
+ char *p;
+
+ assert(m);
+ assert(cgroup);
+ assert(user);
+
+ u = hashmap_get(m->user_cgroups, cgroup);
+ if (u) {
+ *user = u;
+ return 1;
+ }
+
+ p = strdup(cgroup);
+ if (!p) {
+ log_error("Out of memory.");
+ return -ENOMEM;
+ }
+
+ for (;;) {
+ char *e;
+
+ e = strrchr(p, '/');
+ if (!e || e == p) {
+ free(p);
+ *user = NULL;
+ return 0;
+ }
+
+ *e = 0;
+
+ u = hashmap_get(m->user_cgroups, p);
+ if (u) {
+ free(p);
+ *user = u;
+ return 1;
+ }
+ }
+}
+
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
char *p;
int r;
assert(m);
assert(pid >= 1);
@@ -1058,19 +1104,22 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
return r;
}
void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
Session *s;
+ User *u;
int r;
r = manager_get_session_by_cgroup(m, cgroup, &s);
- if (r <= 0)
- return;
+ if (r > 0)
+ session_add_to_gc_queue(s);
- session_add_to_gc_queue(s);
+ r = manager_get_user_by_cgroup(m, cgroup, &u);
+ if (r > 0)
+ user_add_to_gc_queue(u);
}
static void manager_dispatch_other(Manager *m, int fd) {
Session *s;
Inhibitor *i;
Button *b;
diff --git a/src/login/logind.h b/src/login/logind.h
index 6fcef6f31..5e828bf01 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -78,13 +78,15 @@ struct Manager {
bool kill_user_processes;
unsigned long session_counter;
unsigned long inhibit_counter;
- Hashmap *cgroups;
+ Hashmap *session_cgroups;
+ Hashmap *user_cgroups;
+
Hashmap *session_fds;
Hashmap *inhibitor_fds;
Hashmap *button_fds;
/* If a shutdown was delayed due to a inhibitor this contains
the unit name we are supposed to start after the delay is
@@ -143,12 +145,13 @@ int manager_spawn_autovt(Manager *m, int vtnr);
void manager_cgroup_notify_empty(Manager *m, const char *cgroup);
void manager_gc(Manager *m, bool drop_not_started);
int manager_get_idle_hint(Manager *m, dual_timestamp *t);
+int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user);
int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session);
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session);
extern const DBusObjectPathVTable bus_manager_vtable;
DBusHandlerResult bus_message_filter(DBusConnection *c, DBusMessage *message, void *userdata);