From d53d94743c5e5e3a4a668b0c707826a90a08949a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Sep 2015 16:48:24 +0200 Subject: core: refactor cpu shares/blockio weight cgroup logic Let's stop using the "unsigned long" type for weights/shares, and let's just use uint64_t for this, as that's what we expose on the bus. Unify parsers, and always validate the range for these fields. Correct the default blockio weight to 500, since that's what the kernel actually uses. When parsing the weight/shares settings from unit files accept the empty string as a way to reset the weight/shares value. When getting it via the bus, uniformly map (uint64_t) -1 to unset. Open up StartupCPUShares= and StartupBlockIOWeight= to transient units. --- src/core/cgroup.c | 54 ++++++++++---------- src/core/cgroup.h | 14 +++--- src/core/dbus-cgroup.c | 125 +++++++++++++++++++---------------------------- src/core/load-fragment.c | 54 ++++++++------------ src/core/unit.c | 4 +- 5 files changed, 107 insertions(+), 144 deletions(-) (limited to 'src/core') diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 48000d4e6e..4999a1e116 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -37,14 +37,16 @@ void cgroup_context_init(CGroupContext *c) { /* Initialize everything to the kernel defaults, assuming the * structure is preinitialized to 0 */ - c->cpu_shares = (unsigned long) -1; - c->startup_cpu_shares = (unsigned long) -1; + c->cpu_shares = CGROUP_CPU_SHARES_INVALID; + c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID; + c->cpu_quota_per_sec_usec = USEC_INFINITY; + c->memory_limit = (uint64_t) -1; - c->blockio_weight = (unsigned long) -1; - c->startup_blockio_weight = (unsigned long) -1; - c->tasks_max = (uint64_t) -1; - c->cpu_quota_per_sec_usec = USEC_INFINITY; + c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID; + c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID; + + c->tasks_max = (uint64_t) -1; } void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) { @@ -102,11 +104,12 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { "%sCPUAccounting=%s\n" "%sBlockIOAccounting=%s\n" "%sMemoryAccounting=%s\n" - "%sCPUShares=%lu\n" - "%sStartupCPUShares=%lu\n" + "%sTasksAccounting=%s\n" + "%sCPUShares=%" PRIu64 "\n" + "%sStartupCPUShares=%" PRIu64 "\n" "%sCPUQuotaPerSecSec=%s\n" - "%sBlockIOWeight=%lu\n" - "%sStartupBlockIOWeight=%lu\n" + "%sBlockIOWeight=%" PRIu64 "\n" + "%sStartupBlockIOWeight=%" PRIu64 "\n" "%sMemoryLimit=%" PRIu64 "\n" "%sTasksMax=%" PRIu64 "\n" "%sDevicePolicy=%s\n" @@ -114,6 +117,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { prefix, yes_no(c->cpu_accounting), prefix, yes_no(c->blockio_accounting), prefix, yes_no(c->memory_accounting), + prefix, yes_no(c->tasks_accounting), prefix, c->cpu_shares, prefix, c->startup_cpu_shares, prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1), @@ -133,7 +137,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { LIST_FOREACH(device_weights, w, c->blockio_device_weights) fprintf(f, - "%sBlockIODeviceWeight=%s %lu", + "%sBlockIODeviceWeight=%s %" PRIu64, prefix, w->path, w->weight); @@ -309,11 +313,11 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M * and missing cgroups, i.e. EROFS and ENOENT. */ if ((mask & CGROUP_MASK_CPU) && !is_root) { - char buf[MAX(DECIMAL_STR_MAX(unsigned long), DECIMAL_STR_MAX(usec_t)) + 1]; + char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1]; - sprintf(buf, "%lu\n", - IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != (unsigned long) -1 ? c->startup_cpu_shares : - c->cpu_shares != (unsigned long) -1 ? c->cpu_shares : 1024); + sprintf(buf, "%" PRIu64 "\n", + IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->startup_cpu_shares : + c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT); r = cg_set_attribute("cpu", path, "cpu.shares", buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, @@ -336,15 +340,15 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M } if (mask & CGROUP_MASK_BLKIO) { - char buf[MAX3(DECIMAL_STR_MAX(unsigned long)+1, - DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(unsigned long)*1, - DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)]; + char buf[MAX(DECIMAL_STR_MAX(uint64_t)+1, + DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)]; CGroupBlockIODeviceWeight *w; CGroupBlockIODeviceBandwidth *b; if (!is_root) { - sprintf(buf, "%lu\n", IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != (unsigned long) -1 ? c->startup_blockio_weight : - c->blockio_weight != (unsigned long) -1 ? c->blockio_weight : 1000); + sprintf(buf, "%" PRIu64 "\n", + IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->startup_blockio_weight : + c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->blockio_weight : CGROUP_BLKIO_WEIGHT_DEFAULT); r = cg_set_attribute("blkio", path, "blkio.weight", buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, @@ -358,7 +362,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M if (r < 0) continue; - sprintf(buf, "%u:%u %lu", major(dev), minor(dev), w->weight); + sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight); r = cg_set_attribute("blkio", path, "blkio.weight_device", buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, @@ -493,14 +497,14 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) { /* Figure out which controllers we need */ if (c->cpu_accounting || - c->cpu_shares != (unsigned long) -1 || - c->startup_cpu_shares != (unsigned long) -1 || + c->cpu_shares != CGROUP_CPU_SHARES_INVALID || + c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID || c->cpu_quota_per_sec_usec != USEC_INFINITY) mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU; if (c->blockio_accounting || - c->blockio_weight != (unsigned long) -1 || - c->startup_blockio_weight != (unsigned long) -1 || + c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID || + c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID || c->blockio_device_weights || c->blockio_device_bandwidths) mask |= CGROUP_MASK_BLKIO; diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 3ba09d56a4..3d455d93ed 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -58,7 +58,7 @@ struct CGroupDeviceAllow { struct CGroupBlockIODeviceWeight { LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights); char *path; - unsigned long weight; + uint64_t weight; }; struct CGroupBlockIODeviceBandwidth { @@ -74,12 +74,12 @@ struct CGroupContext { bool memory_accounting; bool tasks_accounting; - unsigned long cpu_shares; - unsigned long startup_cpu_shares; + uint64_t cpu_shares; + uint64_t startup_cpu_shares; usec_t cpu_quota_per_sec_usec; - unsigned long blockio_weight; - unsigned long startup_blockio_weight; + uint64_t blockio_weight; + uint64_t startup_blockio_weight; LIST_HEAD(CGroupBlockIODeviceWeight, blockio_device_weights); LIST_HEAD(CGroupBlockIODeviceBandwidth, blockio_device_bandwidths); @@ -88,9 +88,9 @@ struct CGroupContext { CGroupDevicePolicy device_policy; LIST_HEAD(CGroupDeviceAllow, device_allow); - bool delegate; - uint64_t tasks_max; + + bool delegate; }; #include "unit.h" diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 94de92c3dd..78841ba656 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -133,34 +133,16 @@ static int property_get_device_allow( return sd_bus_message_close_container(reply); } -static int property_get_ulong_as_u64( - sd_bus *bus, - const char *path, - const char *interface, - const char *property, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error) { - - unsigned long *ul = userdata; - - assert(bus); - assert(reply); - assert(ul); - - return sd_bus_message_append(reply, "t", *ul == (unsigned long) -1 ? (uint64_t) -1 : (uint64_t) *ul); -} - const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0), SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0), - SD_BUS_PROPERTY("CPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, cpu_shares), 0), - SD_BUS_PROPERTY("StartupCPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_cpu_shares), 0), + SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0), + SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0), SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0), SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0), - SD_BUS_PROPERTY("BlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, blockio_weight), 0), - SD_BUS_PROPERTY("StartupBlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_blockio_weight), 0), + SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0), + SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0), SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0), SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0), SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0), @@ -237,49 +219,45 @@ int bus_cgroup_set_property( return 1; } else if (streq(name, "CPUShares")) { - uint64_t u64; - unsigned long ul; + uint64_t shares; - r = sd_bus_message_read(message, "t", &u64); + r = sd_bus_message_read(message, "t", &shares); if (r < 0) return r; - if (u64 == (uint64_t) -1) - ul = (unsigned long) -1; - else { - ul = (unsigned long) u64; - if (ul <= 0 || (uint64_t) ul != u64) - return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range"); - } + if (!CGROUP_CPU_SHARES_IS_OK(shares)) + return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range"); if (mode != UNIT_CHECK) { - c->cpu_shares = ul; + c->cpu_shares = shares; u->cgroup_realized_mask &= ~CGROUP_MASK_CPU; - unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul); + + if (shares == CGROUP_CPU_SHARES_INVALID) + unit_write_drop_in_private(u, mode, name, "CPUShares="); + else + unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64, shares); } return 1; } else if (streq(name, "StartupCPUShares")) { - uint64_t u64; - unsigned long ul; + uint64_t shares; - r = sd_bus_message_read(message, "t", &u64); + r = sd_bus_message_read(message, "t", &shares); if (r < 0) return r; - if (u64 == (uint64_t) -1) - ul = (unsigned long) -1; - else { - ul = (unsigned long) u64; - if (ul <= 0 || (uint64_t) ul != u64) - return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range"); - } + if (!CGROUP_CPU_SHARES_IS_OK(shares)) + return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range"); if (mode != UNIT_CHECK) { - c->startup_cpu_shares = ul; + c->startup_cpu_shares = shares; u->cgroup_realized_mask &= ~CGROUP_MASK_CPU; - unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%lu", ul); + + if (shares == CGROUP_CPU_SHARES_INVALID) + unit_write_drop_in_private(u, mode, name, "StartupCPUShares="); + else + unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64, shares); } return 1; @@ -318,49 +296,45 @@ int bus_cgroup_set_property( return 1; } else if (streq(name, "BlockIOWeight")) { - uint64_t u64; - unsigned long ul; + uint64_t weight; - r = sd_bus_message_read(message, "t", &u64); + r = sd_bus_message_read(message, "t", &weight); if (r < 0) return r; - if (u64 == (uint64_t) -1) - ul = (unsigned long) -1; - else { - ul = (unsigned long) u64; - if (ul < 10 || ul > 1000) - return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range"); - } + if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight)) + return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range"); if (mode != UNIT_CHECK) { - c->blockio_weight = ul; + c->blockio_weight = weight; u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO; - unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul); + + if (weight == CGROUP_BLKIO_WEIGHT_INVALID) + unit_write_drop_in_private(u, mode, name, "BlockIOWeight="); + else + unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64, weight); } return 1; } else if (streq(name, "StartupBlockIOWeight")) { - uint64_t u64; - unsigned long ul; + uint64_t weight; - r = sd_bus_message_read(message, "t", &u64); + r = sd_bus_message_read(message, "t", &weight); if (r < 0) return r; - if (u64 == (uint64_t) -1) - ul = (unsigned long) -1; - else { - ul = (unsigned long) u64; - if (ul < 10 || ul > 1000) - return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range"); - } + if (CGROUP_BLKIO_WEIGHT_IS_OK(weight)) + return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range"); if (mode != UNIT_CHECK) { - c->startup_blockio_weight = ul; + c->startup_blockio_weight = weight; u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO; - unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%lu", ul); + + if (weight == CGROUP_BLKIO_WEIGHT_INVALID) + unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight="); + else + unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64, weight); } return 1; @@ -455,17 +429,16 @@ int bus_cgroup_set_property( } else if (streq(name, "BlockIODeviceWeight")) { const char *path; - uint64_t u64; + uint64_t weight; unsigned n = 0; r = sd_bus_message_enter_container(message, 'a', "(st)"); if (r < 0) return r; - while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) { - unsigned long ul = u64; + while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) { - if (ul < 10 || ul > 1000) + if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID) return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range"); if (mode != UNIT_CHECK) { @@ -491,7 +464,7 @@ int bus_cgroup_set_property( LIST_PREPEND(device_weights,c->blockio_device_weights, a); } - a->weight = ul; + a->weight = weight; } n++; @@ -520,7 +493,7 @@ int bus_cgroup_set_property( fputs("BlockIODeviceWeight=\n", f); LIST_FOREACH(device_weights, a, c->blockio_device_weights) - fprintf(f, "BlockIODeviceWeight=%s %lu\n", a->path, a->weight); + fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight); fflush(f); unit_write_drop_in_private(u, mode, name, buf); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index f7a8539910..b476d472b3 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2605,26 +2605,19 @@ int config_parse_cpu_shares( void *data, void *userdata) { - unsigned long *shares = data, lu; + uint64_t *shares = data; int r; assert(filename); assert(lvalue); assert(rvalue); - if (isempty(rvalue)) { - *shares = (unsigned long) -1; - return 0; - } - - r = safe_atolu(rvalue, &lu); - if (r < 0 || lu <= 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "CPU shares '%s' invalid. Ignoring.", rvalue); + r = cg_cpu_shares_parse(rvalue, shares); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "CPU shares '%s' invalid. Ignoring.", rvalue); return 0; } - *shares = lu; return 0; } @@ -2805,26 +2798,19 @@ int config_parse_blockio_weight( void *data, void *userdata) { - unsigned long *weight = data, lu; + uint64_t *weight = data; int r; assert(filename); assert(lvalue); assert(rvalue); - if (isempty(rvalue)) { - *weight = (unsigned long) -1; - return 0; - } - - r = safe_atolu(rvalue, &lu); - if (r < 0 || lu < 10 || lu > 1000) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Block IO weight '%s' invalid. Ignoring.", rvalue); + r = cg_blkio_weight_parse(rvalue, weight); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", rvalue); return 0; } - *weight = lu; return 0; } @@ -2843,8 +2829,8 @@ int config_parse_blockio_device_weight( _cleanup_free_ char *path = NULL; CGroupBlockIODeviceWeight *w; CGroupContext *c = data; - unsigned long lu; const char *weight; + uint64_t u; size_t n; int r; @@ -2861,9 +2847,10 @@ int config_parse_blockio_device_weight( n = strcspn(rvalue, WHITESPACE); weight = rvalue + n; - if (!*weight) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Expected block device and device weight. Ignoring."); + weight += strspn(weight, WHITESPACE); + + if (isempty(weight)) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Expected block device and device weight. Ignoring."); return 0; } @@ -2872,19 +2859,18 @@ int config_parse_blockio_device_weight( return log_oom(); if (!path_startswith(path, "/dev")) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Invalid device node path '%s'. Ignoring.", path); + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path); return 0; } - weight += strspn(weight, WHITESPACE); - r = safe_atolu(weight, &lu); - if (r < 0 || lu < 10 || lu > 1000) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Block IO weight '%s' invalid. Ignoring.", rvalue); + r = cg_blkio_weight_parse(weight, &u); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", weight); return 0; } + assert(u != CGROUP_BLKIO_WEIGHT_INVALID); + w = new0(CGroupBlockIODeviceWeight, 1); if (!w) return log_oom(); @@ -2892,7 +2878,7 @@ int config_parse_blockio_device_weight( w->path = path; path = NULL; - w->weight = lu; + w->weight = u; LIST_PREPEND(device_weights, c->blockio_device_weights, w); return 0; diff --git a/src/core/unit.c b/src/core/unit.c index 2ebfb09a7a..f12d1c95cb 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1177,8 +1177,8 @@ static int unit_add_startup_units(Unit *u) { if (!c) return 0; - if (c->startup_cpu_shares == (unsigned long) -1 && - c->startup_blockio_weight == (unsigned long) -1) + if (c->startup_cpu_shares == CGROUP_CPU_SHARES_INVALID && + c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID) return 0; return set_put(u->manager->startup_units, u); -- cgit v1.2.3-54-g00ecf From 5269eb6b32f662d21638e54bb13171a5b97fe58f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Sep 2015 17:25:35 +0200 Subject: core: allocate sets of startup and failed units on-demand There's a good chance we never needs these sets, hence allocate them only when needed. --- src/core/manager.c | 21 ++++++++++----------- src/core/manager.h | 2 +- src/core/unit.c | 9 +++++++-- 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index d918007bb8..8fa2e5079e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -602,14 +602,6 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) { if (r < 0) goto fail; - r = set_ensure_allocated(&m->startup_units, NULL); - if (r < 0) - goto fail; - - r = set_ensure_allocated(&m->failed_units, NULL); - if (r < 0) - goto fail; - r = sd_event_default(&m->event); if (r < 0) goto fail; @@ -3069,8 +3061,9 @@ const char *manager_get_runtime_prefix(Manager *m) { getenv("XDG_RUNTIME_DIR"); } -void manager_update_failed_units(Manager *m, Unit *u, bool failed) { +int manager_update_failed_units(Manager *m, Unit *u, bool failed) { unsigned size; + int r; assert(m); assert(u->manager == m); @@ -3078,13 +3071,19 @@ void manager_update_failed_units(Manager *m, Unit *u, bool failed) { size = set_size(m->failed_units); if (failed) { + r = set_ensure_allocated(&m->failed_units, NULL); + if (r < 0) + return log_oom(); + if (set_put(m->failed_units, u) < 0) - log_oom(); + return log_oom(); } else - set_remove(m->failed_units, u); + (void) set_remove(m->failed_units, u); if (set_size(m->failed_units) != size) bus_manager_send_change_signal(m); + + return 0; } ManagerState manager_state(Manager *m) { diff --git a/src/core/manager.h b/src/core/manager.h index 78a0e50a33..5cf0dbd508 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -369,7 +369,7 @@ const char *manager_get_runtime_prefix(Manager *m); ManagerState manager_state(Manager *m); -void manager_update_failed_units(Manager *m, Unit *u, bool failed); +int manager_update_failed_units(Manager *m, Unit *u, bool failed); const char *manager_state_to_string(ManagerState m) _const_; ManagerState manager_state_from_string(const char *s) _pure_; diff --git a/src/core/unit.c b/src/core/unit.c index f12d1c95cb..3bfc2460bc 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -528,7 +528,7 @@ void unit_free(Unit *u) { unit_release_cgroup(u); - manager_update_failed_units(u->manager, u, false); + (void) manager_update_failed_units(u->manager, u, false); set_remove(u->manager->startup_units, u); free(u->description); @@ -1172,6 +1172,7 @@ static int unit_add_mount_dependencies(Unit *u) { static int unit_add_startup_units(Unit *u) { CGroupContext *c; + int r; c = unit_get_cgroup_context(u); if (!c) @@ -1181,6 +1182,10 @@ static int unit_add_startup_units(Unit *u) { c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID) return 0; + r = set_ensure_allocated(&u->manager->startup_units, NULL); + if (r < 0) + return r; + return set_put(u->manager->startup_units, u); } @@ -1807,7 +1812,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su } /* Keep track of failed units */ - manager_update_failed_units(u->manager, u, ns == UNIT_FAILED); + (void) manager_update_failed_units(u->manager, u, ns == UNIT_FAILED); /* Make sure the cgroup is always removed when we become inactive */ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) -- cgit v1.2.3-54-g00ecf From 54eb2300ae07d28922a18a9d14dc597850535e9c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Sep 2015 18:14:11 +0200 Subject: execute: invalidate idle pipe after use Not strictly necessary, but makes clear the fds are invalidated. Make sure we do the same here as in most other cases. --- src/core/execute.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/execute.c b/src/core/execute.c index d1acda6682..8773d9cdfb 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1160,8 +1160,8 @@ static void do_idle_pipe_dance(int idle_pipe[4]) { assert(idle_pipe); - safe_close(idle_pipe[1]); - safe_close(idle_pipe[2]); + idle_pipe[1] = safe_close(idle_pipe[1]); + idle_pipe[2] = safe_close(idle_pipe[2]); if (idle_pipe[0] >= 0) { int r; @@ -1176,11 +1176,11 @@ static void do_idle_pipe_dance(int idle_pipe[4]) { fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC); } - safe_close(idle_pipe[0]); + idle_pipe[0] = safe_close(idle_pipe[0]); } - safe_close(idle_pipe[3]); + idle_pipe[3] = safe_close(idle_pipe[3]); } static int build_environment( -- cgit v1.2.3-54-g00ecf From c7cc737fce8e5ba8438c1613756b48a0c2ecbb0f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Sep 2015 18:15:08 +0200 Subject: execute: fix return type from write() --- src/core/execute.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/execute.c b/src/core/execute.c index 8773d9cdfb..3c308e3e3e 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1169,9 +1169,11 @@ static void do_idle_pipe_dance(int idle_pipe[4]) { r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC); if (idle_pipe[3] >= 0 && r == 0 /* timeout */) { + ssize_t n; + /* Signal systemd that we are bored and want to continue. */ - r = write(idle_pipe[3], "x", 1); - if (r > 0) + n = write(idle_pipe[3], "x", 1); + if (n > 0) /* Wait for systemd to react to the signal above. */ fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC); } -- cgit v1.2.3-54-g00ecf From cd72bd8a4650c9e78a04cb7df1cbce697e14e512 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Sep 2015 18:15:58 +0200 Subject: core: invalidate idle pipe event source in manager_close_idle_pipe() In all occasions when this function is called we do so anyway, so let's move this inside, to make things easier. --- src/core/manager.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/manager.c b/src/core/manager.c index 8fa2e5079e..3b64d524da 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -317,6 +317,8 @@ static int manager_watch_idle_pipe(Manager *m) { static void manager_close_idle_pipe(Manager *m) { assert(m); + m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source); + safe_close_pair(m->idle_pipe); safe_close_pair(m->idle_pipe + 2); } @@ -936,7 +938,6 @@ Manager* manager_free(Manager *m) { sd_event_source_unref(m->notify_event_source); sd_event_source_unref(m->time_change_event_source); sd_event_source_unref(m->jobs_in_progress_event_source); - sd_event_source_unref(m->idle_pipe_event_source); sd_event_source_unref(m->run_queue_event_source); safe_close(m->signal_fd); @@ -1954,7 +1955,6 @@ static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32 m->no_console_output = m->n_on_console > 0; - m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source); manager_close_idle_pipe(m); return 0; @@ -2694,7 +2694,6 @@ void manager_check_finished(Manager *m) { manager_flip_auto_status(m, false); /* Notify Type=idle units that we are done now */ - m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source); manager_close_idle_pipe(m); /* Turn off confirm spawn now */ -- cgit v1.2.3-54-g00ecf From 1afaa7e8d29c0fd70a621d96a59487ab54b157fc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Sep 2015 18:18:01 +0200 Subject: transaction: clarify via void-casting that we ignore the pipe2() return value for a reason --- src/core/transaction.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/transaction.c b/src/core/transaction.c index b8f69ec6f3..2d120af4b5 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -736,8 +736,8 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0 && m->idle_pipe[2] < 0 && m->idle_pipe[3] < 0) { - pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC); - pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC); + (void) pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC); + (void) pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC); } } -- cgit v1.2.3-54-g00ecf From e7ab4d1ac9f8d99eecd5e2d22eb482a1fb0fbf23 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Sep 2015 18:21:53 +0200 Subject: cgroup: unify how we invalidate cgroup controller settings Let's make sure that we follow the same codepaths when adjusting a cgroup property via the dbus SetProperty() call, and when we execute the StartupCPUShares= effect. --- src/core/cgroup.c | 26 ++++++++++++++++++++++++++ src/core/cgroup.h | 4 ++++ src/core/dbus-cgroup.c | 30 +++++++++++++++--------------- src/core/manager.c | 11 ++--------- 4 files changed, 47 insertions(+), 24 deletions(-) (limited to 'src/core') diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 4999a1e116..7d2a2ba67a 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -1581,6 +1581,32 @@ bool unit_cgroup_delegate(Unit *u) { return c->delegate; } +void unit_invalidate_cgroup(Unit *u, CGroupMask m) { + assert(u); + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return; + + if (m == 0) + return; + + if ((u->cgroup_realized_mask & m) == 0) + return; + + u->cgroup_realized_mask &= ~m; + unit_add_to_cgroup_queue(u); +} + +void manager_invalidate_startup_units(Manager *m) { + Iterator i; + Unit *u; + + assert(m); + + SET_FOREACH(u, m->startup_units, i) + unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_BLKIO); +} + static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = { [CGROUP_AUTO] = "auto", [CGROUP_CLOSED] = "closed", diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 3d455d93ed..e897b31451 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -149,5 +149,9 @@ bool unit_cgroup_delegate(Unit *u); int unit_notify_cgroup_empty(Unit *u); int manager_notify_cgroup_empty(Manager *m, const char *group); +void unit_invalidate_cgroup(Unit *u, CGroupMask m); + +void manager_invalidate_startup_units(Manager *m); + const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_; CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_; diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 78841ba656..f334dc928d 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -212,7 +212,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->cpu_accounting = b; - u->cgroup_realized_mask &= ~CGROUP_MASK_CPUACCT; + unit_invalidate_cgroup(u, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU); unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no"); } @@ -230,7 +230,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->cpu_shares = shares; - u->cgroup_realized_mask &= ~CGROUP_MASK_CPU; + unit_invalidate_cgroup(u, CGROUP_MASK_CPU); if (shares == CGROUP_CPU_SHARES_INVALID) unit_write_drop_in_private(u, mode, name, "CPUShares="); @@ -252,7 +252,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->startup_cpu_shares = shares; - u->cgroup_realized_mask &= ~CGROUP_MASK_CPU; + unit_invalidate_cgroup(u, CGROUP_MASK_CPU); if (shares == CGROUP_CPU_SHARES_INVALID) unit_write_drop_in_private(u, mode, name, "StartupCPUShares="); @@ -274,7 +274,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->cpu_quota_per_sec_usec = u64; - u->cgroup_realized_mask &= ~CGROUP_MASK_CPU; + unit_invalidate_cgroup(u, CGROUP_MASK_CPU); unit_write_drop_in_private_format(u, mode, "CPUQuota", "CPUQuota=%0.f%%", (double) (c->cpu_quota_per_sec_usec / 10000)); } @@ -289,7 +289,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->blockio_accounting = b; - u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO; + unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no"); } @@ -307,7 +307,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->blockio_weight = weight; - u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO; + unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); if (weight == CGROUP_BLKIO_WEIGHT_INVALID) unit_write_drop_in_private(u, mode, name, "BlockIOWeight="); @@ -329,7 +329,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->startup_blockio_weight = weight; - u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO; + unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); if (weight == CGROUP_BLKIO_WEIGHT_INVALID) unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight="); @@ -403,7 +403,7 @@ int bus_cgroup_set_property( cgroup_context_free_blockio_device_bandwidth(c, a); } - u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO; + unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); f = open_memstream(&buf, &size); if (!f) @@ -485,7 +485,7 @@ int bus_cgroup_set_property( cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); } - u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO; + unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); f = open_memstream(&buf, &size); if (!f) @@ -510,7 +510,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->memory_accounting = b; - u->cgroup_realized_mask &= ~CGROUP_MASK_MEMORY; + unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY); unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no"); } @@ -525,7 +525,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->memory_limit = limit; - u->cgroup_realized_mask &= ~CGROUP_MASK_MEMORY; + unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY); if (limit == (uint64_t) -1) unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity"); @@ -551,7 +551,7 @@ int bus_cgroup_set_property( char *buf; c->device_policy = p; - u->cgroup_realized_mask &= ~CGROUP_MASK_DEVICES; + unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES); buf = strjoina("DevicePolicy=", policy); unit_write_drop_in_private(u, mode, name, buf); @@ -630,7 +630,7 @@ int bus_cgroup_set_property( cgroup_context_free_device_allow(c, c->device_allow); } - u->cgroup_realized_mask &= ~CGROUP_MASK_DEVICES; + unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES); f = open_memstream(&buf, &size); if (!f) @@ -655,7 +655,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->tasks_accounting = b; - u->cgroup_realized_mask &= ~CGROUP_MASK_PIDS; + unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no"); } @@ -670,7 +670,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->tasks_max = limit; - u->cgroup_realized_mask &= ~CGROUP_MASK_PIDS; + unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); if (limit == (uint64_t) -1) unit_write_drop_in_private(u, mode, name, "TasksMax=infinity"); diff --git a/src/core/manager.c b/src/core/manager.c index 3b64d524da..8e518fbaaf 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2667,9 +2667,6 @@ static void manager_notify_finished(Manager *m) { } void manager_check_finished(Manager *m) { - Unit *u = NULL; - Iterator i; - assert(m); if (m->n_reloading > 0) @@ -2682,11 +2679,9 @@ void manager_check_finished(Manager *m) { return; if (hashmap_size(m->jobs) > 0) { - if (m->jobs_in_progress_event_source) /* Ignore any failure, this is only for feedback */ - (void) sd_event_source_set_time(m->jobs_in_progress_event_source, - now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC); + (void) sd_event_source_set_time(m->jobs_in_progress_event_source, now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC); return; } @@ -2712,9 +2707,7 @@ void manager_check_finished(Manager *m) { manager_notify_finished(m); - SET_FOREACH(u, m->startup_units, i) - if (u->cgroup_path) - cgroup_context_apply(unit_get_cgroup_context(u), unit_get_own_mask(u), u->cgroup_path, manager_state(m)); + manager_invalidate_startup_units(m); } static int create_generator_dir(Manager *m, char **generator, const char *name) { -- cgit v1.2.3-54-g00ecf