From 38c52d4606c77ff2b2b60a08f663a1983d8254b0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 20 Apr 2011 03:53:12 +0200 Subject: [PATCH] cgroup: don't accidentaly trim on reload https://bugzilla.redhat.com/show_bug.cgi?id=678555 --- src/cgroup.c | 8 ++++---- src/cgroup.h | 4 ++-- src/manager.c | 20 ++++++++++++++++++-- src/manager.h | 1 + src/service.c | 2 +- src/unit.c | 2 +- 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/cgroup.c b/src/cgroup.c index ca19a4fd..0c6f20d4 100644 --- a/src/cgroup.c +++ b/src/cgroup.c @@ -63,7 +63,7 @@ int cgroup_bonding_realize_list(CGroupBonding *first) { return 0; } -void cgroup_bonding_free(CGroupBonding *b) { +void cgroup_bonding_free(CGroupBonding *b, bool remove_or_trim) { assert(b); if (b->unit) { @@ -82,7 +82,7 @@ void cgroup_bonding_free(CGroupBonding *b) { } } - if (b->realized && b->ours) { + if (b->realized && b->ours && remove_or_trim) { if (cgroup_bonding_is_empty(b) > 0) cg_delete(b->controller, b->path); @@ -95,11 +95,11 @@ void cgroup_bonding_free(CGroupBonding *b) { free(b); } -void cgroup_bonding_free_list(CGroupBonding *first) { +void cgroup_bonding_free_list(CGroupBonding *first, bool remove_or_trim) { CGroupBonding *b, *n; LIST_FOREACH_SAFE(by_unit, b, n, first) - cgroup_bonding_free(b); + cgroup_bonding_free(b, remove_or_trim); } void cgroup_bonding_trim(CGroupBonding *b, bool delete_root) { diff --git a/src/cgroup.h b/src/cgroup.h index a6ac90fb..c6dff431 100644 --- a/src/cgroup.h +++ b/src/cgroup.h @@ -53,8 +53,8 @@ struct CGroupBonding { int cgroup_bonding_realize(CGroupBonding *b); int cgroup_bonding_realize_list(CGroupBonding *first); -void cgroup_bonding_free(CGroupBonding *b); -void cgroup_bonding_free_list(CGroupBonding *first); +void cgroup_bonding_free(CGroupBonding *b, bool remove_or_trim); +void cgroup_bonding_free_list(CGroupBonding *first, bool remove_or_trim); int cgroup_bonding_install(CGroupBonding *b, pid_t pid); int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid); diff --git a/src/manager.c b/src/manager.c index b59339b1..9c817b0e 100644 --- a/src/manager.c +++ b/src/manager.c @@ -2654,6 +2654,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds) { assert(f); assert(fds); + m->n_serializing ++; + fprintf(f, "current-job-id=%i\n", m->current_job_id); fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr)); @@ -2674,10 +2676,15 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds) { fputs(u->meta.id, f); fputc('\n', f); - if ((r = unit_serialize(u, f, fds)) < 0) + if ((r = unit_serialize(u, f, fds)) < 0) { + m->n_serializing --; return r; + } } + assert(m->n_serializing > 0); + m->n_serializing --; + if (ferror(f)) return -EIO; @@ -2781,15 +2788,21 @@ int manager_reload(Manager *m) { if ((r = manager_open_serialization(m, &f)) < 0) return r; + m->n_serializing ++; + if (!(fds = fdset_new())) { + m->n_serializing --; r = -ENOMEM; goto finish; } - if ((r = manager_serialize(m, f, fds)) < 0) + if ((r = manager_serialize(m, f, fds)) < 0) { + m->n_serializing --; goto finish; + } if (fseeko(f, 0, SEEK_SET) < 0) { + m->n_serializing --; r = -errno; goto finish; } @@ -2798,6 +2811,9 @@ int manager_reload(Manager *m) { manager_clear_jobs_and_units(m); manager_undo_generators(m); + assert(m->n_serializing > 0); + m->n_serializing --; + /* Find new unit paths */ lookup_paths_free(&m->lookup_paths); if ((q = lookup_paths_init(&m->lookup_paths, m->running_as)) < 0) diff --git a/src/manager.h b/src/manager.h index 4b405d61..07b92c8e 100644 --- a/src/manager.h +++ b/src/manager.h @@ -223,6 +223,7 @@ struct Manager { ExecOutput default_std_output, default_std_error; + int n_serializing; int n_deserializing; unsigned n_installed_jobs; diff --git a/src/service.c b/src/service.c index 7f8d005f..0845d21b 100644 --- a/src/service.c +++ b/src/service.c @@ -1470,7 +1470,7 @@ static void service_set_state(Service *s, ServiceState state) { /* For the inactive states unit_notify() will trim the cgroup, * but for exit we have to do that ourselves... */ - if (state == SERVICE_EXITED) + if (state == SERVICE_EXITED && s->meta.manager->n_deserializing <= 0) cgroup_bonding_trim_list(s->meta.cgroup_bondings, true); if (old_state != state) diff --git a/src/unit.c b/src/unit.c index d7405b92..aed25e4f 100644 --- a/src/unit.c +++ b/src/unit.c @@ -368,7 +368,7 @@ void unit_free(Unit *u) { u->meta.manager->n_in_gc_queue--; } - cgroup_bonding_free_list(u->meta.cgroup_bondings); + cgroup_bonding_free_list(u->meta.cgroup_bondings, u->meta.manager->n_serializing <= 0); free(u->meta.description); free(u->meta.fragment_path); -- 2.39.5