summaryrefslogtreecommitdiff
path: root/src/core/unit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/unit.c')
-rw-r--r--src/core/unit.c134
1 files changed, 122 insertions, 12 deletions
diff --git a/src/core/unit.c b/src/core/unit.c
index 608a33530c..35c4c12575 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -113,6 +113,9 @@ Unit *unit_new(Manager *m, size_t size) {
RATELIMIT_INIT(u->start_limit, m->default_start_limit_interval, m->default_start_limit_burst);
RATELIMIT_INIT(u->auto_stop_ratelimit, 10 * USEC_PER_SEC, 16);
+ for (CGroupIOAccountingMetric i = 0; i < _CGROUP_IO_ACCOUNTING_METRIC_MAX; i++)
+ u->io_accounting_last[i] = UINT64_MAX;
+
return u;
}
@@ -159,7 +162,6 @@ static void unit_init(Unit *u) {
cc->cpu_accounting = u->manager->default_cpu_accounting;
cc->io_accounting = u->manager->default_io_accounting;
- cc->ip_accounting = u->manager->default_ip_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;
@@ -2122,11 +2124,11 @@ void unit_trigger_notify(Unit *u) {
}
static int unit_log_resources(Unit *u) {
- struct iovec iovec[1 + _CGROUP_IP_ACCOUNTING_METRIC_MAX + 4];
- bool any_traffic = false, have_ip_accounting = false;
- _cleanup_free_ char *igress = NULL, *egress = NULL;
+ struct iovec iovec[1 + _CGROUP_IP_ACCOUNTING_METRIC_MAX + _CGROUP_IO_ACCOUNTING_METRIC_MAX + 4];
+ bool any_traffic = false, have_ip_accounting = false, any_io = false, have_io_accounting = false;
+ _cleanup_free_ char *igress = NULL, *egress = NULL, *rr = NULL, *wr = NULL;
size_t n_message_parts = 0, n_iovec = 0;
- char* message_parts[3 + 1], *t;
+ char* message_parts[1 + 2 + 2 + 1], *t;
nsec_t nsec = NSEC_INFINITY;
CGroupIPAccountingMetric m;
size_t i;
@@ -2137,6 +2139,12 @@ static int unit_log_resources(Unit *u) {
[CGROUP_IP_EGRESS_BYTES] = "IP_METRIC_EGRESS_BYTES",
[CGROUP_IP_EGRESS_PACKETS] = "IP_METRIC_EGRESS_PACKETS",
};
+ const char* const io_fields[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
+ [CGROUP_IO_READ_BYTES] = "IO_METRIC_READ_BYTES",
+ [CGROUP_IO_WRITE_BYTES] = "IO_METRIC_WRITE_BYTES",
+ [CGROUP_IO_READ_OPERATIONS] = "IO_METRIC_READ_OPERATIONS",
+ [CGROUP_IO_WRITE_OPERATIONS] = "IO_METRIC_WRITE_OPERATIONS",
+ };
assert(u);
@@ -2166,6 +2174,66 @@ static int unit_log_resources(Unit *u) {
message_parts[n_message_parts++] = t;
}
+ for (CGroupIOAccountingMetric k = 0; k < _CGROUP_IO_ACCOUNTING_METRIC_MAX; k++) {
+ char buf[FORMAT_BYTES_MAX] = "";
+ uint64_t value = UINT64_MAX;
+
+ assert(io_fields[k]);
+
+ (void) unit_get_io_accounting(u, k, k > 0, &value);
+ if (value == UINT64_MAX)
+ continue;
+
+ have_io_accounting = true;
+ if (value > 0)
+ any_io = true;
+
+ /* Format IO accounting data for inclusion in the structured log message */
+ if (asprintf(&t, "%s=%" PRIu64, io_fields[k], value) < 0) {
+ r = log_oom();
+ goto finish;
+ }
+ iovec[n_iovec++] = IOVEC_MAKE_STRING(t);
+
+ /* Format the IO accounting data for inclusion in the human language message string, but only
+ * for the bytes counters (and not for the operations counters) */
+ if (k == CGROUP_IO_READ_BYTES) {
+ assert(!rr);
+ rr = strjoin("read ", format_bytes(buf, sizeof(buf), value), " from disk");
+ if (!rr) {
+ r = log_oom();
+ goto finish;
+ }
+ } else if (k == CGROUP_IO_WRITE_BYTES) {
+ assert(!wr);
+ wr = strjoin("written ", format_bytes(buf, sizeof(buf), value), " to disk");
+ if (!wr) {
+ r = log_oom();
+ goto finish;
+ }
+ }
+ }
+
+ if (have_io_accounting) {
+ if (any_io) {
+ if (rr)
+ message_parts[n_message_parts++] = TAKE_PTR(rr);
+ if (wr)
+ message_parts[n_message_parts++] = TAKE_PTR(wr);
+
+ } else {
+ char *k;
+
+ k = strdup("no IO");
+ if (!k) {
+ r = log_oom();
+ goto finish;
+ }
+
+ message_parts[n_message_parts++] = k;
+ }
+ }
+
for (m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) {
char buf[FORMAT_BYTES_MAX] = "";
uint64_t value = UINT64_MAX;
@@ -3203,6 +3271,20 @@ static const char *const ip_accounting_metric_field[_CGROUP_IP_ACCOUNTING_METRIC
[CGROUP_IP_EGRESS_PACKETS] = "ip-accounting-egress-packets",
};
+static const char *const io_accounting_metric_field_base[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
+ [CGROUP_IO_READ_BYTES] = "io-accounting-read-bytes-base",
+ [CGROUP_IO_WRITE_BYTES] = "io-accounting-write-bytes-base",
+ [CGROUP_IO_READ_OPERATIONS] = "io-accounting-read-operations-base",
+ [CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-base",
+};
+
+static const char *const io_accounting_metric_field_last[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
+ [CGROUP_IO_READ_BYTES] = "io-accounting-read-bytes-last",
+ [CGROUP_IO_WRITE_BYTES] = "io-accounting-write-bytes-last",
+ [CGROUP_IO_READ_OPERATIONS] = "io-accounting-read-operations-last",
+ [CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-last",
+};
+
int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
CGroupIPAccountingMetric m;
int r;
@@ -3249,6 +3331,13 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
if (u->oom_kill_last > 0)
(void) serialize_item_format(f, "oom-kill-last", "%" PRIu64, u->oom_kill_last);
+ for (CGroupIOAccountingMetric im = 0; im < _CGROUP_IO_ACCOUNTING_METRIC_MAX; im++) {
+ (void) serialize_item_format(f, io_accounting_metric_field_base[im], "%" PRIu64, u->io_accounting_base[im]);
+
+ if (u->io_accounting_last[im] != UINT64_MAX)
+ (void) serialize_item_format(f, io_accounting_metric_field_last[im], "%" PRIu64, u->io_accounting_last[im]);
+ }
+
if (u->cgroup_path)
(void) serialize_item(f, "cgroup", u->cgroup_path);
@@ -3324,8 +3413,8 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
for (;;) {
_cleanup_free_ char *line = NULL;
- CGroupIPAccountingMetric m;
char *l, *v;
+ ssize_t m;
size_t k;
r = read_line(f, LONG_LINE_MAX, &line);
@@ -3577,10 +3666,8 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
}
/* Check if this is an IP accounting metric serialization field */
- for (m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++)
- if (streq(l, ip_accounting_metric_field[m]))
- break;
- if (m < _CGROUP_IP_ACCOUNTING_METRIC_MAX) {
+ m = string_table_lookup(ip_accounting_metric_field, ELEMENTSOF(ip_accounting_metric_field), l);
+ if (m >= 0) {
uint64_t c;
r = safe_atou64(v, &c);
@@ -3591,6 +3678,30 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
continue;
}
+ m = string_table_lookup(io_accounting_metric_field_base, ELEMENTSOF(io_accounting_metric_field_base), l);
+ if (m >= 0) {
+ uint64_t c;
+
+ r = safe_atou64(v, &c);
+ if (r < 0)
+ log_unit_debug(u, "Failed to parse IO accounting base value %s, ignoring.", v);
+ else
+ u->io_accounting_base[m] = c;
+ continue;
+ }
+
+ m = string_table_lookup(io_accounting_metric_field_last, ELEMENTSOF(io_accounting_metric_field_last), l);
+ if (m >= 0) {
+ uint64_t c;
+
+ r = safe_atou64(v, &c);
+ if (r < 0)
+ log_unit_debug(u, "Failed to parse IO accounting last value %s, ignoring.", v);
+ else
+ u->io_accounting_last[m] = c;
+ continue;
+ }
+
if (unit_can_serialize(u)) {
r = exec_runtime_deserialize_compat(u, l, v, fds);
if (r < 0) {
@@ -5394,8 +5505,7 @@ int unit_prepare_exec(Unit *u) {
(void) unit_realize_cgroup(u);
if (u->reset_accounting) {
- (void) unit_reset_cpu_accounting(u);
- (void) unit_reset_ip_accounting(u);
+ (void) unit_reset_accounting(u);
u->reset_accounting = false;
}