summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/automount.c6
-rw-r--r--src/core/cgroup.c244
-rw-r--r--src/core/cgroup.h42
-rw-r--r--src/core/dbus-cgroup.c192
-rw-r--r--src/core/dbus-execute.c54
-rw-r--r--src/core/dbus-unit.c26
-rw-r--r--src/core/dbus.c9
-rw-r--r--src/core/device.c3
-rw-r--r--src/core/execute.c52
-rw-r--r--src/core/load-fragment-gperf.gperf.m45
-rw-r--r--src/core/load-fragment.c169
-rw-r--r--src/core/load-fragment.h2
-rw-r--r--src/core/main.c6
-rw-r--r--src/core/manager.c41
-rw-r--r--src/core/manager.h7
-rw-r--r--src/core/service.c2
-rw-r--r--src/core/swap.c3
-rw-r--r--src/core/transaction.c4
-rw-r--r--src/core/unit.c47
-rw-r--r--src/core/unit.h5
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;