X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fcgroup.c;h=1a8fd3728f06acf9179a2170d175507b77e8a91e;hb=3772995afa7df42c3a332fb085a27cb5d266b893;hp=1c818ab300828989c54ea95981649ce351abe00f;hpb=0a1eb06d9aacc1f007be04c4133031e0acc91cdd;p=elogind.git diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 1c818ab30..1a8fd3728 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -33,7 +33,7 @@ void cgroup_context_init(CGroupContext *c) { * structure is preinitialized to 0 */ c->cpu_shares = 1024; - c->memory_limit = c->memory_soft_limit = (uint64_t) -1; + c->memory_limit = (uint64_t) -1; c->blockio_weight = 1000; } @@ -41,7 +41,7 @@ void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) { assert(c); assert(a); - LIST_REMOVE(CGroupDeviceAllow, device_allow, c->device_allow, a); + LIST_REMOVE(device_allow, c->device_allow, a); free(a->path); free(a); } @@ -50,7 +50,7 @@ void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODe assert(c); assert(w); - LIST_REMOVE(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w); + LIST_REMOVE(device_weights, c->blockio_device_weights, w); free(w->path); free(w); } @@ -59,7 +59,7 @@ void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockI assert(c); assert(b); - LIST_REMOVE(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b); + LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b); free(b->path); free(b); } @@ -92,9 +92,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { "%sBlockIOAccounting=%s\n" "%sMemoryAccounting=%s\n" "%sCPUShares=%lu\n" - "%sBlockIOWeight%lu\n" + "%sBlockIOWeight=%lu\n" "%sMemoryLimit=%" PRIu64 "\n" - "%sMemorySoftLimit=%" PRIu64 "\n" "%sDevicePolicy=%s\n", prefix, yes_no(c->cpu_accounting), prefix, yes_no(c->blockio_accounting), @@ -102,7 +101,6 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { prefix, c->cpu_shares, prefix, c->blockio_weight, prefix, c->memory_limit, - prefix, c->memory_soft_limit, prefix, cgroup_device_policy_to_string(c->device_policy)); LIST_FOREACH(device_allow, a, c->device_allow) @@ -114,7 +112,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { LIST_FOREACH(device_weights, w, c->blockio_device_weights) fprintf(f, - "%sBlockIOWeight=%s %lu", + "%sBlockIODeviceWeight=%s %lu", prefix, w->path, w->weight); @@ -256,15 +254,14 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha } if (mask & CGROUP_MEMORY) { - char buf[DECIMAL_STR_MAX(uint64_t) + 1]; + if (c->memory_limit != (uint64_t) -1) { + char buf[DECIMAL_STR_MAX(uint64_t) + 1]; - sprintf(buf, "%" PRIu64 "\n", c->memory_limit); - r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf); - if (r < 0) - log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r)); + sprintf(buf, "%" PRIu64 "\n", c->memory_limit); + r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf); + } else + r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1"); - sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit); - cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf); if (r < 0) log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r)); } @@ -329,8 +326,7 @@ CGroupControllerMask cgroup_context_get_mask(CGroupContext *c) { mask |= CGROUP_BLKIO; if (c->memory_accounting || - c->memory_limit != (uint64_t) -1 || - c->memory_soft_limit != (uint64_t) -1) + c->memory_limit != (uint64_t) -1) mask |= CGROUP_MEMORY; if (c->device_allow || c->device_policy != CGROUP_AUTO) @@ -380,34 +376,46 @@ static CGroupControllerMask unit_get_siblings_mask(Unit *u) { } static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) { - char *path = NULL; + _cleanup_free_ char *path; int r; + bool was_in_hash = false; assert(u); path = unit_default_cgroup_path(u); if (!path) - return -ENOMEM; + return log_oom(); r = hashmap_put(u->manager->cgroup_unit, path, u); - if (r < 0) + if (r == 0) + was_in_hash = true; + else if (r < 0) { + log_error(r == -EEXIST ? + "cgroup %s exists already: %s" : "hashmap_put failed for %s: %s", + path, strerror(-r)); return r; + } /* First, create our own group */ - r = cg_create_with_mask(mask, path); + r = cg_create_everywhere(u->manager->cgroup_supported, mask, path); if (r < 0) log_error("Failed to create cgroup %s: %s", path, strerror(-r)); /* Then, possibly move things over */ - if (u->cgroup_path && !streq(path, u->cgroup_path)) { - r = cg_migrate_with_mask(mask, u->cgroup_path, path); + if (u->cgroup_path) { + r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, path); if (r < 0) - log_error("Failed to migrate cgroup %s: %s", path, strerror(-r)); + log_error("Failed to migrate cgroup from %s to %s: %s", + u->cgroup_path, path, strerror(-r)); + } + + if (!was_in_hash) { + /* Remember the new data */ + free(u->cgroup_path); + u->cgroup_path = path; + path = NULL; } - /* And remember the new data */ - free(u->cgroup_path); - u->cgroup_path = path; u->cgroup_realized = true; u->cgroup_mask = mask; @@ -420,7 +428,7 @@ static int unit_realize_cgroup_now(Unit *u) { assert(u); if (u->in_cgroup_queue) { - LIST_REMOVE(Unit, cgroup_queue, u->manager->cgroup_queue, u); + LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u); u->in_cgroup_queue = false; } @@ -444,7 +452,7 @@ static void unit_add_to_cgroup_queue(Unit *u) { if (u->in_cgroup_queue) return; - LIST_PREPEND(Unit, cgroup_queue, u->manager->cgroup_queue, u); + LIST_PREPEND(cgroup_queue, u->manager->cgroup_queue, u); u->in_cgroup_queue = true; } @@ -503,7 +511,7 @@ int unit_realize_cgroup(Unit *u) { * unit, we need to first create all parents, but there's more * actually: for the weight-based controllers we also need to * make sure that all our siblings (i.e. units that are in the - * same slice as we are) have cgroup too. Otherwise things + * same slice as we are) have cgroups, too. Otherwise things * would become very uneven as each of their processes would * get as much resources as all our group together. This call * will synchronously create the parent cgroups, but will @@ -531,9 +539,9 @@ void unit_destroy_cgroup(Unit *u) { if (!u->cgroup_path) return; - r = cg_trim_with_mask(u->cgroup_mask, u->cgroup_path, true); + r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE)); if (r < 0) - log_error("Failed to destroy cgroup %s: %s", u->cgroup_path, strerror(-r)); + log_debug("Failed to destroy cgroup %s: %s", u->cgroup_path, strerror(-r)); hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); @@ -583,8 +591,8 @@ pid_t unit_search_main_pid(Unit *u) { int manager_setup_cgroup(Manager *m) { _cleanup_free_ char *path = NULL; + char *e; int r; - char *e, *a; assert(m); @@ -604,9 +612,13 @@ int manager_setup_cgroup(Manager *m) { return r; } - /* Already in /system.slice? If so, let's cut this off again */ + /* LEGACY: Already in /system.slice? If so, let's cut this + * off. This is to support live upgrades from older systemd + * versions where PID 1 was moved there. */ if (m->running_as == SYSTEMD_SYSTEM) { e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE); + if (!e) + e = endswith(m->cgroup_root, "/system"); if (e) *e = 0; } @@ -637,9 +649,8 @@ int manager_setup_cgroup(Manager *m) { log_debug("Release agent already installed."); } - /* 4. Realize the system slice and put us in there */ - a = strappenda(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE); - r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, a, 0); + /* 4. Make sure we are in the root cgroup */ + r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, 0); if (r < 0) { log_error("Failed to create root cgroup hierarchy: %s", strerror(-r)); return r; @@ -658,6 +669,9 @@ int manager_setup_cgroup(Manager *m) { /* 6. Figure out which controllers are supported */ m->cgroup_supported = cg_mask_supported(); + /* 7. Always enable hierarchial support if it exists... */ + cg_set_attribute("memory", "/", "memory.use_hierarchy", "1"); + return 0; } @@ -728,13 +742,16 @@ int manager_notify_cgroup_empty(Manager *m, const char *cgroup) { assert(m); assert(cgroup); - r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, true); - if (r == 0) - return 0; - u = manager_get_unit_by_cgroup(m, cgroup); - if (u && UNIT_VTABLE(u)->notify_cgroup_empty) - UNIT_VTABLE(u)->notify_cgroup_empty(u); + if (u) { + r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true); + if (r > 0) { + if (UNIT_VTABLE(u)->notify_cgroup_empty) + UNIT_VTABLE(u)->notify_cgroup_empty(u); + + unit_add_to_gc_queue(u); + } + } return 0; }