1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-21 02:50:18 +03:00

Merge pull request #12074 from poettering/io-acct

expose IO stats on the bus and in "systemctl status" and "systemd-run --wait"
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-04-25 11:59:37 +02:00 committed by GitHub
commit c5b7ae0edb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 365 additions and 33 deletions

View File

@ -3233,21 +3233,140 @@ int unit_get_ip_accounting(
return r;
}
static int unit_get_io_accounting_raw(Unit *u, uint64_t ret[static _CGROUP_IO_ACCOUNTING_METRIC_MAX]) {
static const char *const field_names[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
[CGROUP_IO_READ_BYTES] = "rbytes=",
[CGROUP_IO_WRITE_BYTES] = "wbytes=",
[CGROUP_IO_READ_OPERATIONS] = "rios=",
[CGROUP_IO_WRITE_OPERATIONS] = "wios=",
};
uint64_t acc[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {};
_cleanup_free_ char *path = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(u);
if (!u->cgroup_path)
return -ENODATA;
if (unit_has_host_root_cgroup(u))
return -ENODATA; /* TODO: return useful data for the top-level cgroup */
r = cg_all_unified();
if (r < 0)
return r;
if (r == 0) /* TODO: support cgroupv1 */
return -ENODATA;
if (!FLAGS_SET(u->cgroup_realized_mask, CGROUP_MASK_IO))
return -ENODATA;
r = cg_get_path("io", u->cgroup_path, "io.stat", &path);
if (r < 0)
return r;
f = fopen(path, "re");
if (!f)
return -errno;
for (;;) {
_cleanup_free_ char *line = NULL;
const char *p;
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return r;
if (r == 0)
break;
p = line;
p += strcspn(p, WHITESPACE); /* Skip over device major/minor */
p += strspn(p, WHITESPACE); /* Skip over following whitespace */
for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE);
if (r < 0)
return r;
if (r == 0)
break;
for (CGroupIOAccountingMetric i = 0; i < _CGROUP_IO_ACCOUNTING_METRIC_MAX; i++) {
const char *x;
x = startswith(word, field_names[i]);
if (x) {
uint64_t w;
r = safe_atou64(x, &w);
if (r < 0)
return r;
/* Sum up the stats of all devices */
acc[i] += w;
break;
}
}
}
}
memcpy(ret, acc, sizeof(acc));
return 0;
}
int unit_get_io_accounting(
Unit *u,
CGroupIOAccountingMetric metric,
bool allow_cache,
uint64_t *ret) {
uint64_t raw[_CGROUP_IO_ACCOUNTING_METRIC_MAX];
int r;
/* Retrieve an IO account parameter. This will subtract the counter when the unit was started. */
if (!UNIT_CGROUP_BOOL(u, io_accounting))
return -ENODATA;
if (allow_cache && u->io_accounting_last[metric] != UINT64_MAX)
goto done;
r = unit_get_io_accounting_raw(u, raw);
if (r == -ENODATA && u->io_accounting_last[metric] != UINT64_MAX)
goto done;
if (r < 0)
return r;
for (CGroupIOAccountingMetric i = 0; i < _CGROUP_IO_ACCOUNTING_METRIC_MAX; i++) {
/* Saturated subtraction */
if (raw[i] > u->io_accounting_base[i])
u->io_accounting_last[i] = raw[i] - u->io_accounting_base[i];
else
u->io_accounting_last[i] = 0;
}
done:
if (ret)
*ret = u->io_accounting_last[metric];
return 0;
}
int unit_reset_cpu_accounting(Unit *u) {
nsec_t ns;
int r;
assert(u);
u->cpu_usage_last = NSEC_INFINITY;
r = unit_get_cpu_usage_raw(u, &ns);
r = unit_get_cpu_usage_raw(u, &u->cpu_usage_base);
if (r < 0) {
u->cpu_usage_base = 0;
return r;
}
u->cpu_usage_base = ns;
return 0;
}
@ -3267,6 +3386,35 @@ int unit_reset_ip_accounting(Unit *u) {
return r < 0 ? r : q;
}
int unit_reset_io_accounting(Unit *u) {
int r;
assert(u);
for (CGroupIOAccountingMetric i = 0; i < _CGROUP_IO_ACCOUNTING_METRIC_MAX; i++)
u->io_accounting_last[i] = UINT64_MAX;
r = unit_get_io_accounting_raw(u, u->io_accounting_base);
if (r < 0) {
zero(u->io_accounting_base);
return r;
}
return 0;
}
int unit_reset_accounting(Unit *u) {
int r, q, v;
assert(u);
r = unit_reset_cpu_accounting(u);
q = unit_reset_io_accounting(u);
v = unit_reset_ip_accounting(u);
return r < 0 ? r : q < 0 ? q : v;
}
void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
assert(u);

View File

@ -142,6 +142,16 @@ typedef enum CGroupIPAccountingMetric {
_CGROUP_IP_ACCOUNTING_METRIC_INVALID = -1,
} CGroupIPAccountingMetric;
/* Used when querying IO accounting data */
typedef enum CGroupIOAccountingMetric {
CGROUP_IO_READ_BYTES,
CGROUP_IO_WRITE_BYTES,
CGROUP_IO_READ_OPERATIONS,
CGROUP_IO_WRITE_OPERATIONS,
_CGROUP_IO_ACCOUNTING_METRIC_MAX,
_CGROUP_IO_ACCOUNTING_METRIC_INVALID = -1,
} CGroupIOAccountingMetric;
typedef struct Unit Unit;
typedef struct Manager Manager;
@ -210,10 +220,13 @@ int unit_synthesize_cgroup_empty_event(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_get_io_accounting(Unit *u, CGroupIOAccountingMetric metric, bool allow_cache, uint64_t *ret);
int unit_get_ip_accounting(Unit *u, CGroupIPAccountingMetric metric, uint64_t *ret);
int unit_reset_cpu_accounting(Unit *u);
int unit_reset_ip_accounting(Unit *u);
int unit_reset_io_accounting(Unit *u);
int unit_reset_accounting(Unit *u);
#define UNIT_CGROUP_BOOL(u, name) \
({ \

View File

@ -19,6 +19,7 @@
#include "selinux-access.h"
#include "signal-util.h"
#include "special.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
@ -1029,30 +1030,57 @@ static int property_get_ip_counter(
void *userdata,
sd_bus_error *error) {
CGroupIPAccountingMetric metric;
uint64_t value = (uint64_t) -1;
static const char *const table[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = {
[CGROUP_IP_INGRESS_BYTES] = "IPIngressBytes",
[CGROUP_IP_EGRESS_BYTES] = "IPEgressBytes",
[CGROUP_IP_INGRESS_PACKETS] = "IPIngressPackets",
[CGROUP_IP_EGRESS_PACKETS] = "IPEgressPackets",
};
uint64_t value = UINT64_MAX;
Unit *u = userdata;
ssize_t metric;
assert(bus);
assert(reply);
assert(property);
assert(u);
if (streq(property, "IPIngressBytes"))
metric = CGROUP_IP_INGRESS_BYTES;
else if (streq(property, "IPIngressPackets"))
metric = CGROUP_IP_INGRESS_PACKETS;
else if (streq(property, "IPEgressBytes"))
metric = CGROUP_IP_EGRESS_BYTES;
else {
assert(streq(property, "IPEgressPackets"));
metric = CGROUP_IP_EGRESS_PACKETS;
}
assert_se((metric = string_table_lookup(table, ELEMENTSOF(table), property)) >= 0);
(void) unit_get_ip_accounting(u, metric, &value);
return sd_bus_message_append(reply, "t", value);
}
static int property_get_io_counter(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
static const char *const table[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
[CGROUP_IO_READ_BYTES] = "IOReadBytes",
[CGROUP_IO_WRITE_BYTES] = "IOWriteBytes",
[CGROUP_IO_READ_OPERATIONS] = "IOReadOperations",
[CGROUP_IO_WRITE_OPERATIONS] = "IOWriteOperations",
};
uint64_t value = UINT64_MAX;
Unit *u = userdata;
ssize_t metric;
assert(bus);
assert(reply);
assert(property);
assert(u);
assert_se((metric = string_table_lookup(table, ELEMENTSOF(table), property)) >= 0);
(void) unit_get_io_accounting(u, metric, false, &value);
return sd_bus_message_append(reply, "t", value);
}
int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
@ -1176,6 +1204,10 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = {
SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0),
SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter, 0, 0),
SD_BUS_PROPERTY("IPEgressPackets", "t", property_get_ip_counter, 0, 0),
SD_BUS_PROPERTY("IOReadBytes", "t", property_get_io_counter, 0, 0),
SD_BUS_PROPERTY("IOReadOperations", "t", property_get_io_counter, 0, 0),
SD_BUS_PROPERTY("IOWriteBytes", "t", property_get_io_counter, 0, 0),
SD_BUS_PROPERTY("IOWriteOperations", "t", property_get_io_counter, 0, 0),
SD_BUS_METHOD("GetProcesses", NULL, "a(sus)", bus_unit_method_get_processes, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("AttachProcesses", "sau", NULL, bus_unit_method_attach_processes, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END

View File

@ -330,8 +330,7 @@ static int scope_start(Unit *u) {
return r;
(void) unit_realize_cgroup(u);
(void) unit_reset_cpu_accounting(u);
(void) unit_reset_ip_accounting(u);
(void) unit_reset_accounting(u);
unit_export_state_files(u);

View File

@ -230,8 +230,7 @@ static int slice_start(Unit *u) {
return r;
(void) unit_realize_cgroup(u);
(void) unit_reset_cpu_accounting(u);
(void) unit_reset_ip_accounting(u);
(void) unit_reset_accounting(u);
slice_set_state(t, SLICE_ACTIVE);
return 1;

View File

@ -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;
}

View File

@ -252,6 +252,10 @@ typedef struct Unit {
/* The current counter of the oom_kill field in the memory.events cgroup attribute */
uint64_t oom_kill_last;
/* Where the io.stat data was at the time the unit was started */
uint64_t io_accounting_base[_CGROUP_IO_ACCOUNTING_METRIC_MAX];
uint64_t io_accounting_last[_CGROUP_IO_ACCOUNTING_METRIC_MAX]; /* the most recently read value */
/* Counterparts in the cgroup filesystem */
char *cgroup_path;
CGroupMask cgroup_realized_mask; /* In which hierarchies does this unit's cgroup exist? (only relevant on cgroup v1) */

View File

@ -948,6 +948,8 @@ typedef struct RunContext {
uint64_t cpu_usage_nsec;
uint64_t ip_ingress_bytes;
uint64_t ip_egress_bytes;
uint64_t io_read_bytes;
uint64_t io_write_bytes;
uint32_t exit_code;
uint32_t exit_status;
} RunContext;
@ -993,6 +995,8 @@ static int run_context_update(RunContext *c, const char *path) {
{ "CPUUsageNSec", "t", NULL, offsetof(RunContext, cpu_usage_nsec) },
{ "IPIngressBytes", "t", NULL, offsetof(RunContext, ip_ingress_bytes) },
{ "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) },
{ "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) },
{ "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) },
{}
};
@ -1181,6 +1185,8 @@ static int start_transient_service(
.cpu_usage_nsec = NSEC_INFINITY,
.ip_ingress_bytes = UINT64_MAX,
.ip_egress_bytes = UINT64_MAX,
.io_read_bytes = UINT64_MAX,
.io_write_bytes = UINT64_MAX,
.inactive_exit_usec = USEC_INFINITY,
.inactive_enter_usec = USEC_INFINITY,
};
@ -1280,6 +1286,14 @@ static int start_transient_service(
char bytes[FORMAT_BYTES_MAX];
log_info("IP traffic sent: %s", format_bytes(bytes, sizeof(bytes), c.ip_egress_bytes));
}
if (c.io_read_bytes != UINT64_MAX) {
char bytes[FORMAT_BYTES_MAX];
log_info("IO bytes read: %s", format_bytes(bytes, sizeof(bytes), c.io_read_bytes));
}
if (c.io_write_bytes != UINT64_MAX) {
char bytes[FORMAT_BYTES_MAX];
log_info("IO bytes written: %s", format_bytes(bytes, sizeof(bytes), c.io_write_bytes));
}
}
/* Try to propagate the service's return value */

View File

@ -4125,9 +4125,10 @@ typedef struct UnitStatusInfo {
uint64_t cpu_usage_nsec;
uint64_t tasks_current;
uint64_t tasks_max;
uint64_t ip_ingress_bytes;
uint64_t ip_egress_bytes;
uint64_t io_read_bytes;
uint64_t io_write_bytes;
uint64_t default_memory_min;
uint64_t default_memory_low;
@ -4485,6 +4486,14 @@ static void print_status_info(
format_bytes(buf_out, sizeof(buf_out), i->ip_egress_bytes));
}
if (i->io_read_bytes != UINT64_MAX && i->io_write_bytes != UINT64_MAX) {
char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX];
printf(" IO: %s read, %s written\n",
format_bytes(buf_in, sizeof(buf_in), i->io_read_bytes),
format_bytes(buf_out, sizeof(buf_out), i->io_write_bytes));
}
if (i->tasks_current != (uint64_t) -1) {
printf(" Tasks: %" PRIu64, i->tasks_current);
@ -5495,6 +5504,8 @@ static int show_one(
{ "TasksMax", "t", NULL, offsetof(UnitStatusInfo, tasks_max) },
{ "IPIngressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_ingress_bytes) },
{ "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) },
{ "IOReadBytes", "t", NULL, offsetof(UnitStatusInfo, io_read_bytes) },
{ "IOWriteBytes", "t", NULL, offsetof(UnitStatusInfo, io_write_bytes) },
{ "ExecStartPre", "a(sasbttttuii)", map_exec, 0 },
{ "ExecStart", "a(sasbttttuii)", map_exec, 0 },
{ "ExecStartPost", "a(sasbttttuii)", map_exec, 0 },
@ -5519,6 +5530,8 @@ static int show_one(
.tasks_max = (uint64_t) -1,
.ip_ingress_bytes = (uint64_t) -1,
.ip_egress_bytes = (uint64_t) -1,
.io_read_bytes = UINT64_MAX,
.io_write_bytes = UINT64_MAX,
};
char **pp;
int r;