diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/automount.c | 6 | ||||
-rw-r--r-- | src/core/cgroup.c | 244 | ||||
-rw-r--r-- | src/core/cgroup.h | 42 | ||||
-rw-r--r-- | src/core/dbus-cgroup.c | 192 | ||||
-rw-r--r-- | src/core/dbus-execute.c | 54 | ||||
-rw-r--r-- | src/core/dbus-unit.c | 26 | ||||
-rw-r--r-- | src/core/dbus.c | 9 | ||||
-rw-r--r-- | src/core/device.c | 3 | ||||
-rw-r--r-- | src/core/execute.c | 52 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 5 | ||||
-rw-r--r-- | src/core/load-fragment.c | 169 | ||||
-rw-r--r-- | src/core/load-fragment.h | 2 | ||||
-rw-r--r-- | src/core/main.c | 6 | ||||
-rw-r--r-- | src/core/manager.c | 41 | ||||
-rw-r--r-- | src/core/manager.h | 7 | ||||
-rw-r--r-- | src/core/service.c | 2 | ||||
-rw-r--r-- | src/core/swap.c | 3 | ||||
-rw-r--r-- | src/core/transaction.c | 4 | ||||
-rw-r--r-- | src/core/unit.c | 47 | ||||
-rw-r--r-- | src/core/unit.h | 5 |
20 files changed, 616 insertions, 303 deletions
diff --git a/src/core/automount.c b/src/core/automount.c index 5bb61b95d3..c88e3311bc 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -129,10 +129,8 @@ static void automount_done(Unit *u) { a->where = mfree(a->where); - set_free(a->tokens); - a->tokens = NULL; - set_free(a->expire_tokens); - a->expire_tokens = NULL; + a->tokens = set_free(a->tokens); + a->expire_tokens = set_free(a->expire_tokens); a->expire_event_source = sd_event_source_unref(a->expire_event_source); } diff --git a/src/core/cgroup.c b/src/core/cgroup.c index baa7cc5488..0c790c33da 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -22,10 +22,11 @@ #include <fcntl.h> #include <fnmatch.h> -#include "process-util.h" +#include "cgroup-util.h" #include "path-util.h" +#include "process-util.h" #include "special.h" -#include "cgroup-util.h" + #include "cgroup.h" #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC) @@ -36,13 +37,18 @@ 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->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; + + c->netclass_type = CGROUP_NETCLASS_TYPE_NONE; } void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) { @@ -100,23 +106,27 @@ 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" "%sDelegate=%s\n", 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), prefix, c->blockio_weight, prefix, c->startup_blockio_weight, prefix, c->memory_limit, + prefix, c->tasks_max, prefix, cgroup_device_policy_to_string(c->device_policy), prefix, yes_no(c->delegate)); @@ -129,7 +139,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); @@ -283,7 +293,7 @@ fail: return -errno; } -void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state) { +void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, uint32_t netclass, ManagerState state) { bool is_root; int r; @@ -305,11 +315,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, @@ -332,15 +342,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, @@ -354,7 +364,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, @@ -466,6 +476,32 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M log_debug("Ignoring device %s while writing cgroup attribute.", a->path); } } + + if ((mask & CGROUP_MASK_PIDS) && !is_root) { + + if (c->tasks_max != (uint64_t) -1) { + char buf[DECIMAL_STR_MAX(uint64_t) + 2]; + + sprintf(buf, "%" PRIu64 "\n", c->tasks_max); + r = cg_set_attribute("pids", path, "pids.max", buf); + } else + r = cg_set_attribute("pids", path, "pids.max", "max"); + + if (r < 0) + log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to set pids.max on %s: %m", path); + } + + if (mask & CGROUP_MASK_NET_CLS) { + char buf[DECIMAL_STR_MAX(uint32_t)]; + + sprintf(buf, "%" PRIu32, netclass); + + r = cg_set_attribute("net_cls", path, "net_cls.classid", buf); + if (r < 0) + log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to set net_cls.classid on %s: %m", path); + } } CGroupMask cgroup_context_get_mask(CGroupContext *c) { @@ -474,14 +510,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; @@ -494,6 +530,13 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) { c->device_policy != CGROUP_AUTO) mask |= CGROUP_MASK_DEVICES; + if (c->tasks_accounting || + c->tasks_max != (uint64_t) -1) + mask |= CGROUP_MASK_PIDS; + + if (c->netclass_type != CGROUP_NETCLASS_TYPE_NONE) + mask |= CGROUP_MASK_NET_CLS; + return mask; } @@ -861,6 +904,103 @@ static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask) { return u->cgroup_realized && u->cgroup_realized_mask == target_mask; } +static int unit_find_free_netclass_cgroup(Unit *u, uint32_t *ret) { + + uint32_t start, i; + Manager *m; + + assert(u); + + m = u->manager; + + i = start = m->cgroup_netclass_registry_last; + + do { + i++; + + if (!hashmap_get(m->cgroup_netclass_registry, UINT_TO_PTR(i))) { + m->cgroup_netclass_registry_last = i; + *ret = i; + return 0; + } + + if (i == UINT32_MAX) + i = CGROUP_NETCLASS_FIXED_MAX; + + } while (i != start); + + return -ENOBUFS; +} + +int unit_add_to_netclass_cgroup(Unit *u) { + + CGroupContext *cc; + Unit *first; + void *key; + int r; + + assert(u); + + cc = unit_get_cgroup_context(u); + if (!cc) + return 0; + + switch (cc->netclass_type) { + case CGROUP_NETCLASS_TYPE_NONE: + return 0; + + case CGROUP_NETCLASS_TYPE_FIXED: + u->cgroup_netclass_id = cc->netclass_id; + break; + + case CGROUP_NETCLASS_TYPE_AUTO: + /* Allocate a new ID in case it was requested and not done yet */ + if (u->cgroup_netclass_id == 0) { + r = unit_find_free_netclass_cgroup(u, &u->cgroup_netclass_id); + if (r < 0) + return r; + + log_debug("Dynamically assigned netclass cgroup id %" PRIu32 " to %s", u->cgroup_netclass_id, u->id); + } + + break; + } + + r = hashmap_ensure_allocated(&u->manager->cgroup_netclass_registry, &trivial_hash_ops); + if (r < 0) + return r; + + key = UINT32_TO_PTR(u->cgroup_netclass_id); + first = hashmap_get(u->manager->cgroup_netclass_registry, key); + + if (first) { + LIST_PREPEND(cgroup_netclass, first, u); + return hashmap_replace(u->manager->cgroup_netclass_registry, key, u); + } + + return hashmap_put(u->manager->cgroup_netclass_registry, key, u); +} + +int unit_remove_from_netclass_cgroup(Unit *u) { + + Unit *head; + void *key; + + assert(u); + + key = UINT32_TO_PTR(u->cgroup_netclass_id); + + LIST_FIND_HEAD(cgroup_netclass, u, head); + LIST_REMOVE(cgroup_netclass, head, u); + + if (head) + return hashmap_replace(u->manager->cgroup_netclass_registry, key, head); + + hashmap_remove(u->manager->cgroup_netclass_registry, key); + + return 0; +} + /* Check if necessary controllers and attributes for a unit are in place. * * If so, do nothing. @@ -896,7 +1036,7 @@ static int unit_realize_cgroup_now(Unit *u, ManagerState state) { return r; /* Finally, apply the necessary attributes. */ - cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, state); + cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, u->cgroup_netclass_id, state); return 0; } @@ -1459,6 +1599,28 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) { return safe_atou64(v, ret); } +int unit_get_tasks_current(Unit *u, uint64_t *ret) { + _cleanup_free_ char *v = NULL; + int r; + + assert(u); + assert(ret); + + if (!u->cgroup_path) + return -ENODATA; + + if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0) + return -ENODATA; + + r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + + return safe_atou64(v, ret); +} + static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) { _cleanup_free_ char *v = NULL; uint64_t ns; @@ -1532,6 +1694,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 438f5bf50f..457544b49f 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -26,6 +26,11 @@ #include "list.h" #include "time-util.h" +/* Maximum value for fixed (manual) net class ID assignment, + * and also the value at which the range of automatic assignments starts + */ +#define CGROUP_NETCLASS_FIXED_MAX UINT32_C(65535) + typedef struct CGroupContext CGroupContext; typedef struct CGroupDeviceAllow CGroupDeviceAllow; typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight; @@ -47,6 +52,17 @@ typedef enum CGroupDevicePolicy { _CGROUP_DEVICE_POLICY_INVALID = -1 } CGroupDevicePolicy; +typedef enum CGroupNetClassType { + /* Default - do not assign a net class */ + CGROUP_NETCLASS_TYPE_NONE, + + /* Automatically assign a net class */ + CGROUP_NETCLASS_TYPE_AUTO, + + /* Assign the net class that was provided by the user */ + CGROUP_NETCLASS_TYPE_FIXED, +} CGroupNetClassType; + struct CGroupDeviceAllow { LIST_FIELDS(CGroupDeviceAllow, device_allow); char *path; @@ -58,7 +74,7 @@ struct CGroupDeviceAllow { struct CGroupBlockIODeviceWeight { LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights); char *path; - unsigned long weight; + uint64_t weight; }; struct CGroupBlockIODeviceBandwidth { @@ -72,13 +88,14 @@ struct CGroupContext { bool cpu_accounting; bool blockio_accounting; 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); @@ -87,6 +104,11 @@ struct CGroupContext { CGroupDevicePolicy device_policy; LIST_HEAD(CGroupDeviceAllow, device_allow); + CGroupNetClassType netclass_type; + uint32_t netclass_id; + + uint64_t tasks_max; + bool delegate; }; @@ -96,7 +118,7 @@ struct CGroupContext { void cgroup_context_init(CGroupContext *c); void cgroup_context_done(CGroupContext *c); void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix); -void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state); +void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, uint32_t netclass_id, ManagerState state); CGroupMask cgroup_context_get_mask(CGroupContext *c); @@ -124,6 +146,9 @@ int unit_watch_cgroup(Unit *u); int unit_attach_pids_to_cgroup(Unit *u); +int unit_add_to_netclass_cgroup(Unit *u); +int unit_remove_from_netclass_cgroup(Unit *u); + int manager_setup_cgroup(Manager *m); void manager_shutdown_cgroup(Manager *m, bool delete); @@ -137,6 +162,7 @@ int unit_search_main_pid(Unit *u, pid_t *ret); int unit_watch_all_pids(Unit *u); int unit_get_memory_current(Unit *u, uint64_t *ret); +int unit_get_tasks_current(Unit *u, uint64_t *ret); int unit_get_cpu_usage(Unit *u, nsec_t *ret); int unit_reset_cpu_usage(Unit *u); @@ -145,5 +171,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 ba2f4e53b9..f334dc928d 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), @@ -168,6 +150,8 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0), SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0), SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0), + SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0), + SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0), SD_BUS_VTABLE_END }; @@ -228,56 +212,52 @@ 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"); } 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; - u->cgroup_realized_mask &= ~CGROUP_MASK_CPU; - unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul); + c->cpu_shares = shares; + unit_invalidate_cgroup(u, CGROUP_MASK_CPU); + + 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; - u->cgroup_realized_mask &= ~CGROUP_MASK_CPU; - unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%lu", ul); + c->startup_cpu_shares = shares; + unit_invalidate_cgroup(u, CGROUP_MASK_CPU); + + 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; @@ -294,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)); } @@ -309,56 +289,52 @@ 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"); } 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; - u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO; - unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul); + c->blockio_weight = weight; + unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); + + 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; - u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO; - unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%lu", ul); + c->startup_blockio_weight = weight; + unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); + + 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; @@ -427,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) @@ -453,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) { @@ -489,7 +464,7 @@ int bus_cgroup_set_property( LIST_PREPEND(device_weights,c->blockio_device_weights, a); } - a->weight = ul; + a->weight = weight; } n++; @@ -510,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) @@ -518,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); @@ -535,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"); } @@ -550,8 +525,12 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->memory_limit = limit; - u->cgroup_realized_mask &= ~CGROUP_MASK_MEMORY; - unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit); + unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY); + + if (limit == (uint64_t) -1) + unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity"); + else + unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit); } return 1; @@ -572,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); @@ -651,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) @@ -667,6 +646,39 @@ int bus_cgroup_set_property( return 1; + } else if (streq(name, "TasksAccounting")) { + int b; + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + c->tasks_accounting = b; + unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); + unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no"); + } + + return 1; + + } else if (streq(name, "TasksMax")) { + uint64_t limit; + + r = sd_bus_message_read(message, "t", &limit); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + c->tasks_max = limit; + unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); + + if (limit == (uint64_t) -1) + unit_write_drop_in_private(u, mode, name, "TasksMax=infinity"); + else + unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit); + } + + return 1; } if (u->transient && u->load_state == UNIT_STUB) { diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index ed55fcfca2..fd13c6d019 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -933,7 +933,10 @@ int bus_exec_context_set_transient_property( return 1; - } else if (streq(name, "IgnoreSIGPIPE")) { + } else if (STR_IN_SET(name, + "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", + "PrivateTmp", "PrivateDevices", "PrivateNetwork", + "NoNewPrivileges")) { int b; r = sd_bus_message_read(message, "b", &b); @@ -941,39 +944,22 @@ int bus_exec_context_set_transient_property( return r; if (mode != UNIT_CHECK) { - c->ignore_sigpipe = b; - - unit_write_drop_in_private_format(u, mode, name, "IgnoreSIGPIPE=%s\n", yes_no(b)); - } - - return 1; - - } else if (streq(name, "TTYVHangup")) { - int b; - - r = sd_bus_message_read(message, "b", &b); - if (r < 0) - return r; - - if (mode != UNIT_CHECK) { - c->tty_vhangup = b; - - unit_write_drop_in_private_format(u, mode, name, "TTYVHangup=%s\n", yes_no(b)); - } - - return 1; - - } else if (streq(name, "TTYReset")) { - int b; - - r = sd_bus_message_read(message, "b", &b); - if (r < 0) - return r; - - if (mode != UNIT_CHECK) { - c->tty_reset = b; - - unit_write_drop_in_private_format(u, mode, name, "TTYReset=%s\n", yes_no(b)); + if (streq(name, "IgnoreSIGPIPE")) + c->ignore_sigpipe = b; + else if (streq(name, "TTYVHangup")) + c->tty_vhangup = b; + else if (streq(name, "TTYReset")) + c->tty_reset = b; + else if (streq(name, "PrivateTmp")) + c->private_tmp = b; + else if (streq(name, "PrivateDevices")) + c->private_devices = b; + else if (streq(name, "PrivateNetwork")) + c->private_network = b; + else if (streq(name, "NoNewPrivileges")) + c->no_new_privileges = b; + + unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, yes_no(b)); } return 1; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index f9275ed935..cd88a87340 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -679,6 +679,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0), SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NetClass", "u", bus_property_get_unsigned, offsetof(Unit, cgroup_netclass_id), 0), SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED), @@ -736,6 +737,30 @@ static int property_get_current_memory( return sd_bus_message_append(reply, "t", sz); } +static int property_get_current_tasks( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + uint64_t cn = (uint64_t) -1; + Unit *u = userdata; + int r; + + assert(bus); + assert(reply); + assert(u); + + r = unit_get_tasks_current(u, &cn); + if (r < 0 && r != -ENODATA) + log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m"); + + return sd_bus_message_append(reply, "t", cn); +} + static int property_get_cpu_usage( sd_bus *bus, const char *path, @@ -796,6 +821,7 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = { SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0), SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0), SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0), + SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0), SD_BUS_VTABLE_END }; diff --git a/src/core/dbus.c b/src/core/dbus.c index 0a2180c6a7..2d6a1ff836 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -1055,12 +1055,10 @@ void bus_done(Manager *m) { while ((b = set_steal_first(m->private_buses))) destroy_bus(m, &b); - set_free(m->private_buses); - m->private_buses = NULL; + m->private_buses = set_free(m->private_buses); m->subscribed = sd_bus_track_unref(m->subscribed); - strv_free(m->deserialized_subscribed); - m->deserialized_subscribed = NULL; + m->deserialized_subscribed = strv_free(m->deserialized_subscribed); if (m->private_listen_event_source) m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source); @@ -1191,8 +1189,7 @@ int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) { } } - strv_free(*l); - *l = NULL; + *l = strv_free(*l); return r; } diff --git a/src/core/device.c b/src/core/device.c index 7fdfacfddf..0b54518691 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -594,8 +594,7 @@ static void device_shutdown(Manager *m) { m->udev_monitor = NULL; } - hashmap_free(m->devices_by_sysfs); - m->devices_by_sysfs = NULL; + m->devices_by_sysfs = hashmap_free(m->devices_by_sysfs); } static int device_enumerate(Manager *m) { diff --git a/src/core/execute.c b/src/core/execute.c index 6abb0a5d5d..3c308e3e3e 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; @@ -1169,18 +1169,20 @@ 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); } - 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( @@ -1992,11 +1994,8 @@ void exec_context_done(ExecContext *c) { assert(c); - strv_free(c->environment); - c->environment = NULL; - - strv_free(c->environment_files); - c->environment_files = NULL; + c->environment = strv_free(c->environment); + c->environment_files = strv_free(c->environment_files); for (l = 0; l < ELEMENTSOF(c->rlimit); l++) c->rlimit[l] = mfree(c->rlimit[l]); @@ -2008,8 +2007,7 @@ void exec_context_done(ExecContext *c) { c->user = mfree(c->user); c->group = mfree(c->group); - strv_free(c->supplementary_groups); - c->supplementary_groups = NULL; + c->supplementary_groups = strv_free(c->supplementary_groups); c->pam_name = mfree(c->pam_name); @@ -2018,14 +2016,9 @@ void exec_context_done(ExecContext *c) { c->capabilities = NULL; } - strv_free(c->read_only_dirs); - c->read_only_dirs = NULL; - - strv_free(c->read_write_dirs); - c->read_write_dirs = NULL; - - strv_free(c->inaccessible_dirs); - c->inaccessible_dirs = NULL; + c->read_only_dirs = strv_free(c->read_only_dirs); + c->read_write_dirs = strv_free(c->read_write_dirs); + c->inaccessible_dirs = strv_free(c->inaccessible_dirs); if (c->cpuset) CPU_FREE(c->cpuset); @@ -2034,17 +2027,11 @@ void exec_context_done(ExecContext *c) { c->selinux_context = mfree(c->selinux_context); c->apparmor_profile = mfree(c->apparmor_profile); - set_free(c->syscall_filter); - c->syscall_filter = NULL; + c->syscall_filter = set_free(c->syscall_filter); + c->syscall_archs = set_free(c->syscall_archs); + c->address_families = set_free(c->address_families); - set_free(c->syscall_archs); - c->syscall_archs = NULL; - - set_free(c->address_families); - c->address_families = NULL; - - strv_free(c->runtime_directory); - c->runtime_directory = NULL; + c->runtime_directory = strv_free(c->runtime_directory); bus_endpoint_free(c->bus_endpoint); c->bus_endpoint = NULL; @@ -2079,8 +2066,7 @@ void exec_command_done(ExecCommand *c) { c->path = mfree(c->path); - strv_free(c->argv); - c->argv = NULL; + c->argv = strv_free(c->argv); } void exec_command_done_array(ExecCommand *c, unsigned n) { diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index edd55b9e45..ec744214c1 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -124,7 +124,10 @@ $1.StartupBlockIOWeight, config_parse_blockio_weight, 0, $1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0, offsetof($1, cgroup_context) $1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context) $1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context) -$1.Delegate, config_parse_bool, 0, offsetof($1, cgroup_context.delegate)' +$1.TasksAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.tasks_accounting) +$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context) +$1.Delegate, config_parse_bool, 0, offsetof($1, cgroup_context.delegate) +$1.NetClass, config_parse_netclass, 0, offsetof($1, cgroup_context)' )m4_dnl Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description) Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index b695c57da8..1217b4651e 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -1888,8 +1888,7 @@ int config_parse_unit_env_file(const char *unit, if (isempty(rvalue)) { /* Empty assignment frees the list */ - strv_free(*env); - *env = NULL; + *env = strv_free(*env); return 0; } @@ -1937,8 +1936,7 @@ int config_parse_environ(const char *unit, if (isempty(rvalue)) { /* Empty assignment resets the list */ - strv_free(*env); - *env = NULL; + *env = strv_free(*env); return 0; } @@ -2245,8 +2243,7 @@ int config_parse_documentation(const char *unit, if (isempty(rvalue)) { /* Empty assignment resets the list */ - strv_free(u->documentation); - u->documentation = NULL; + u->documentation = strv_free(u->documentation); return 0; } @@ -2305,8 +2302,7 @@ int config_parse_syscall_filter( if (isempty(rvalue)) { /* Empty assignment resets the list */ - set_free(c->syscall_filter); - c->syscall_filter = NULL; + c->syscall_filter = set_free(c->syscall_filter); c->syscall_whitelist = false; return 0; } @@ -2404,8 +2400,7 @@ int config_parse_syscall_archs( int r; if (isempty(rvalue)) { - set_free(*archs); - *archs = NULL; + *archs = set_free(*archs); return 0; } @@ -2501,8 +2496,7 @@ int config_parse_address_families( if (isempty(rvalue)) { /* Empty assignment resets the list */ - set_free(c->address_families); - c->address_families = NULL; + c->address_families = set_free(c->address_families); c->address_families_whitelist = false; return 0; } @@ -2611,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; } @@ -2689,24 +2676,51 @@ int config_parse_memory_limit( void *userdata) { CGroupContext *c = data; - off_t bytes; + uint64_t bytes; int r; - if (isempty(rvalue)) { + if (isempty(rvalue) || streq(rvalue, "infinity")) { c->memory_limit = (uint64_t) -1; return 0; } - assert_cc(sizeof(uint64_t) == sizeof(off_t)); - r = parse_size(rvalue, 1024, &bytes); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Memory limit '%s' invalid. Ignoring.", rvalue); + if (r < 0 || bytes < 1) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Memory limit '%s' invalid. Ignoring.", rvalue); + return 0; + } + + c->memory_limit = bytes; + return 0; +} + +int config_parse_tasks_max( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + uint64_t u; + int r; + + if (isempty(rvalue) || streq(rvalue, "infinity")) { + c->tasks_max = (uint64_t) -1; + return 0; + } + + r = safe_atou64(rvalue, &u); + if (r < 0 || u < 1) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Maximum tasks value '%s' invalid. Ignoring.", rvalue); return 0; } - c->memory_limit = (uint64_t) bytes; return 0; } @@ -2784,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; } @@ -2822,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; @@ -2840,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; } @@ -2851,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(); @@ -2871,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; @@ -2893,7 +2900,7 @@ int config_parse_blockio_bandwidth( CGroupBlockIODeviceBandwidth *b; CGroupContext *c = data; const char *bandwidth; - off_t bytes; + uint64_t bytes; bool read; size_t n; int r; @@ -2947,7 +2954,7 @@ int config_parse_blockio_bandwidth( b->path = path; path = NULL; - b->bandwidth = (uint64_t) bytes; + b->bandwidth = bytes; b->read = read; LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b); @@ -2955,6 +2962,48 @@ int config_parse_blockio_bandwidth( return 0; } +int config_parse_netclass( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + unsigned v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (streq(rvalue, "auto")) { + c->netclass_type = CGROUP_NETCLASS_TYPE_AUTO; + return 0; + } + + r = safe_atou32(rvalue, &v); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Netclass '%s' invalid. Ignoring.", rvalue); + return 0; + } + + if (v > CGROUP_NETCLASS_FIXED_MAX) + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Fixed netclass %" PRIu32 " out of allowed range (0-%d). Applying anyway.", v, (uint32_t) CGROUP_NETCLASS_FIXED_MAX); + + c->netclass_id = v; + c->netclass_type = CGROUP_NETCLASS_TYPE_FIXED; + + return 0; +} + DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode"); int config_parse_job_mode_isolate( @@ -3011,8 +3060,7 @@ int config_parse_runtime_directory( if (isempty(rvalue)) { /* Empty assignment resets the list */ - strv_free(*rt); - *rt = NULL; + *rt = strv_free(*rt); return 0; } @@ -3140,8 +3188,7 @@ int config_parse_namespace_path_strv( if (isempty(rvalue)) { /* Empty assignment resets the list */ - strv_free(*sv); - *sv = NULL; + *sv = strv_free(*sv); return 0; } @@ -3622,7 +3669,7 @@ void unit_dump_config_items(FILE *f) { { config_parse_int, "INTEGER" }, { config_parse_unsigned, "UNSIGNED" }, { config_parse_iec_size, "SIZE" }, - { config_parse_iec_off, "SIZE" }, + { config_parse_iec_uint64, "SIZE" }, { config_parse_si_size, "SIZE" }, { config_parse_bool, "BOOLEAN" }, { config_parse_string, "STRING" }, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 1d128716c4..5d0a09249f 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -84,11 +84,13 @@ int config_parse_environ(const char *unit, const char *filename, unsigned line, int config_parse_unit_slice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_cpu_shares(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_blockio_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_blockio_bandwidth(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_netclass(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_job_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_job_mode_isolate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_selinux_context(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/core/main.c b/src/core/main.c index be95dc68b2..200fe740da 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -114,6 +114,7 @@ static FILE* arg_serialization = NULL; static bool arg_default_cpu_accounting = false; static bool arg_default_blockio_accounting = false; static bool arg_default_memory_accounting = false; +static bool arg_default_tasks_accounting = false; static void nop_handler(int sig) {} @@ -676,6 +677,7 @@ static int parse_config_file(void) { { "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting }, { "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting }, { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting }, + { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting }, {} }; @@ -704,6 +706,7 @@ static void manager_set_defaults(Manager *m) { m->default_cpu_accounting = arg_default_cpu_accounting; m->default_blockio_accounting = arg_default_blockio_accounting; m->default_memory_accounting = arg_default_memory_accounting; + m->default_tasks_accounting = arg_default_tasks_accounting; manager_set_default_rlimits(m, arg_default_rlimit); manager_environment_add(m, NULL, arg_default_environment); @@ -1846,8 +1849,7 @@ finish: arg_default_environment = strv_free(arg_default_environment); - set_free(arg_syscall_archs); - arg_syscall_archs = NULL; + arg_syscall_archs = set_free(arg_syscall_archs); mac_selinux_finish(); diff --git a/src/core/manager.c b/src/core/manager.c index d918007bb8..4e672a8c48 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); } @@ -577,6 +579,8 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) { m->have_ask_password = -EINVAL; /* we don't know */ m->first_boot = -1; + m->cgroup_netclass_registry_last = CGROUP_NETCLASS_FIXED_MAX; + m->test_run = test_run; /* Reboot immediately if the user hits C-A-D more often than 7x per 2s */ @@ -602,14 +606,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; @@ -944,7 +940,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); @@ -967,6 +962,8 @@ Manager* manager_free(Manager *m) { hashmap_free(m->cgroup_unit); set_free_free(m->unit_path_cache); + hashmap_free(m->cgroup_netclass_registry); + free(m->switch_root); free(m->switch_root_init); @@ -1962,7 +1959,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; @@ -2675,9 +2671,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) @@ -2690,11 +2683,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; } @@ -2702,7 +2693,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 */ @@ -2721,9 +2711,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) { @@ -3069,8 +3057,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 +3067,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 9956cb7700..b955982100 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -256,6 +256,7 @@ struct Manager { bool default_cpu_accounting; bool default_memory_accounting; bool default_blockio_accounting; + bool default_tasks_accounting; usec_t default_timer_accuracy_usec; @@ -302,6 +303,10 @@ struct Manager { const char *unit_log_format_string; int first_boot; + + /* Used for NetClass=auto units */ + Hashmap *cgroup_netclass_registry; + uint32_t cgroup_netclass_registry_last; }; int manager_new(ManagerRunningAs running_as, bool test_run, Manager **m); @@ -368,7 +373,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/service.c b/src/core/service.c index 248a9e8c62..fc28ba4d07 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2737,6 +2737,8 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us case SERVICE_RELOAD: log_unit_warning(UNIT(s), "Reload operation timed out. Stopping."); + service_unwatch_control_pid(s); + service_kill_control_processes(s); s->reload_result = SERVICE_FAILURE_TIMEOUT; service_enter_running(s, SERVICE_SUCCESS); break; diff --git a/src/core/swap.c b/src/core/swap.c index 311ce7ee04..bef457069f 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -1254,8 +1254,7 @@ static void swap_shutdown(Manager *m) { m->proc_swaps = safe_fclose(m->proc_swaps); - hashmap_free(m->swaps_by_devnode); - m->swaps_by_devnode = NULL; + m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode); } static int swap_enumerate(Manager *m) { 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); } } diff --git a/src/core/unit.c b/src/core/unit.c index 24a6747b10..3356b97522 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -125,6 +125,7 @@ static void unit_init(Unit *u) { cc->cpu_accounting = u->manager->default_cpu_accounting; cc->blockio_accounting = u->manager->default_blockio_accounting; cc->memory_accounting = u->manager->default_memory_accounting; + cc->tasks_accounting = u->manager->default_tasks_accounting; } ec = unit_get_exec_context(u); @@ -445,13 +446,13 @@ static void unit_free_requires_mounts_for(Unit *u) { } } - strv_free(u->requires_mounts_for); - u->requires_mounts_for = NULL; + u->requires_mounts_for = strv_free(u->requires_mounts_for); } static void unit_done(Unit *u) { ExecContext *ec; CGroupContext *cc; + int r; assert(u); @@ -468,6 +469,10 @@ static void unit_done(Unit *u) { cc = unit_get_cgroup_context(u); if (cc) cgroup_context_done(cc); + + r = unit_remove_from_netclass_cgroup(u); + if (r < 0) + log_warning_errno(r, "Unable to remove unit from netclass group: %m"); } void unit_free(Unit *u) { @@ -528,7 +533,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); @@ -674,8 +679,7 @@ static void merge_dependencies(Unit *u, Unit *other, const char *other_id, UnitD /* The move cannot fail. The caller must have performed a reservation. */ assert_se(complete_move(&u->dependencies[d], &other->dependencies[d]) == 0); - set_free(other->dependencies[d]); - other->dependencies[d] = NULL; + other->dependencies[d] = set_free(other->dependencies[d]); } int unit_merge(Unit *u, Unit *other) { @@ -1173,15 +1177,20 @@ 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) 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; + r = set_ensure_allocated(&u->manager->startup_units, NULL); + if (r < 0) + return r; + return set_put(u->manager->startup_units, u); } @@ -1237,6 +1246,14 @@ int unit_load(Unit *u) { } unit_update_cgroup_members_masks(u); + + /* If we are reloading, we need to wait for the deserializer + * to restore the net_cls ids that have been set previously */ + if (u->manager->n_reloading <= 0) { + r = unit_add_to_netclass_cgroup(u); + if (r < 0) + return r; + } } assert((u->load_state != UNIT_MERGED) == !u->merged_into); @@ -1808,7 +1825,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)) @@ -2587,6 +2604,9 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { unit_serialize_item(u, f, "cgroup", u->cgroup_path); unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized)); + if (u->cgroup_netclass_id) + unit_serialize_item_format(u, f, "netclass-id", "%" PRIu32, u->cgroup_netclass_id); + if (serialize_jobs) { if (u->job) { fprintf(f, "job\n"); @@ -2774,6 +2794,17 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { u->cgroup_realized = b; continue; + } else if (streq(l, "netclass-id")) { + r = safe_atou32(v, &u->cgroup_netclass_id); + if (r < 0) + log_unit_debug(u, "Failed to parse netclass ID %s, ignoring.", v); + else { + r = unit_add_to_netclass_cgroup(u); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to add unit to netclass cgroup, ignoring: %m"); + } + + continue; } if (unit_can_serialize(u)) { diff --git a/src/core/unit.h b/src/core/unit.h index 3c7684411b..c868d75c79 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -161,6 +161,9 @@ struct Unit { /* CGroup realize members queue */ LIST_FIELDS(Unit, cgroup_queue); + /* Units with the same CGroup netclass */ + LIST_FIELDS(Unit, cgroup_netclass); + /* PIDs we keep an eye on. Note that a unit might have many * more, but these are the ones we care enough about to * process SIGCHLD for */ @@ -189,6 +192,8 @@ struct Unit { CGroupMask cgroup_members_mask; int cgroup_inotify_wd; + uint32_t cgroup_netclass_id; + /* How to start OnFailure units */ JobMode on_failure_job_mode; |