cgroup: analyze: Report memory configurations that deviate from systemd

This is the most basic consumer of the new systemd-vs-kernel checker,
both acting as a reasonable standalone exerciser of the code, and also
as a way for easy inspection of deviations from systemd internal state.
This commit is contained in:
Chris Down 2019-10-03 13:21:29 +01:00
parent 6dfb92823f
commit bc0623df16
8 changed files with 63 additions and 22 deletions

View File

@ -328,7 +328,38 @@ static int unit_compare_memory_limit(Unit *u, const char *property_name, uint64_
return *ret_kernel_value == *ret_unit_value;
}
void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
#define FORMAT_CGROUP_DIFF_MAX 128
static char *format_cgroup_memory_limit_comparison(char *buf, size_t l, Unit *u, const char *property_name) {
uint64_t kval, sval;
int r;
assert(u);
assert(buf);
assert(l > 0);
r = unit_compare_memory_limit(u, property_name, &sval, &kval);
/* memory.swap.max is special in that it relies on CONFIG_MEMCG_SWAP (and the default swapaccount=1).
* In the absence of reliably being able to detect whether memcg swap support is available or not,
* only complain if the error is not ENOENT. */
if (r > 0 || IN_SET(r, -ENODATA, -EOWNERDEAD) ||
(r == -ENOENT && streq(property_name, "MemorySwapMax"))) {
buf[0] = 0;
return buf;
}
if (r < 0) {
snprintf(buf, l, " (error getting kernel value: %s)", strerror_safe(r));
return buf;
}
snprintf(buf, l, " (different value in kernel: %" PRIu64 ")", kval);
return buf;
}
void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
_cleanup_free_ char *disable_controllers_str = NULL;
_cleanup_free_ char *cpuset_cpus = NULL;
_cleanup_free_ char *cpuset_mems = NULL;
@ -338,14 +369,24 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
CGroupBlockIODeviceBandwidth *b;
CGroupBlockIODeviceWeight *w;
CGroupDeviceAllow *a;
CGroupContext *c;
IPAddressAccessItem *iaai;
char **path;
char u[FORMAT_TIMESPAN_MAX];
char q[FORMAT_TIMESPAN_MAX];
char v[FORMAT_TIMESPAN_MAX];
assert(c);
char cda[FORMAT_CGROUP_DIFF_MAX];
char cdb[FORMAT_CGROUP_DIFF_MAX];
char cdc[FORMAT_CGROUP_DIFF_MAX];
char cdd[FORMAT_CGROUP_DIFF_MAX];
char cde[FORMAT_CGROUP_DIFF_MAX];
assert(u);
assert(f);
c = unit_get_cgroup_context(u);
assert(c);
prefix = strempty(prefix);
(void) cg_mask_to_string(c->disable_controllers, &disable_controllers_str);
@ -374,11 +415,11 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
"%sStartupBlockIOWeight: %" PRIu64 "\n"
"%sDefaultMemoryMin: %" PRIu64 "\n"
"%sDefaultMemoryLow: %" PRIu64 "\n"
"%sMemoryMin: %" PRIu64 "\n"
"%sMemoryLow: %" PRIu64 "\n"
"%sMemoryHigh: %" PRIu64 "\n"
"%sMemoryMax: %" PRIu64 "\n"
"%sMemorySwapMax: %" PRIu64 "\n"
"%sMemoryMin: %" PRIu64 "%s\n"
"%sMemoryLow: %" PRIu64 "%s\n"
"%sMemoryHigh: %" PRIu64 "%s\n"
"%sMemoryMax: %" PRIu64 "%s\n"
"%sMemorySwapMax: %" PRIu64 "%s\n"
"%sMemoryLimit: %" PRIu64 "\n"
"%sTasksMax: %" PRIu64 "\n"
"%sDevicePolicy: %s\n"
@ -394,7 +435,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
prefix, c->startup_cpu_weight,
prefix, c->cpu_shares,
prefix, c->startup_cpu_shares,
prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
prefix, format_timespan(q, sizeof(q), c->cpu_quota_per_sec_usec, 1),
prefix, format_timespan(v, sizeof(v), c->cpu_quota_period_usec, 1),
prefix, cpuset_cpus,
prefix, cpuset_mems,
@ -404,11 +445,11 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
prefix, c->startup_blockio_weight,
prefix, c->default_memory_min,
prefix, c->default_memory_low,
prefix, c->memory_min,
prefix, c->memory_low,
prefix, c->memory_high,
prefix, c->memory_max,
prefix, c->memory_swap_max,
prefix, c->memory_min, format_cgroup_memory_limit_comparison(cda, sizeof(cda), u, "MemoryMin"),
prefix, c->memory_low, format_cgroup_memory_limit_comparison(cdb, sizeof(cdb), u, "MemoryLow"),
prefix, c->memory_high, format_cgroup_memory_limit_comparison(cdc, sizeof(cdc), u, "MemoryHigh"),
prefix, c->memory_max, format_cgroup_memory_limit_comparison(cdd, sizeof(cdd), u, "MemoryMax"),
prefix, c->memory_swap_max, format_cgroup_memory_limit_comparison(cde, sizeof(cde), u, "MemorySwapMax"),
prefix, c->memory_limit,
prefix, c->tasks_max,
prefix, cgroup_device_policy_to_string(c->device_policy),
@ -444,7 +485,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
"%sIODeviceLatencyTargetSec: %s %s\n",
prefix,
l->path,
format_timespan(u, sizeof(u), l->target_usec, 1));
format_timespan(q, sizeof(q), l->target_usec, 1));
LIST_FOREACH(device_limits, il, c->io_device_limits) {
char buf[FORMAT_BYTES_MAX];

View File

@ -166,7 +166,7 @@ usec_t cgroup_cpu_adjust_period(usec_t period, usec_t quota, usec_t resolution,
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_dump(Unit *u, FILE* f, const char *prefix);
void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a);
void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w);

View File

@ -769,7 +769,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
exec_context_dump(&m->exec_context, f, prefix);
kill_context_dump(&m->kill_context, f, prefix);
cgroup_context_dump(&m->cgroup_context, f, prefix);
cgroup_context_dump(UNIT(m), f, prefix);
}
static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {

View File

@ -234,7 +234,7 @@ static void scope_dump(Unit *u, FILE *f, const char *prefix) {
prefix, scope_state_to_string(s->state),
prefix, scope_result_to_string(s->result));
cgroup_context_dump(&s->cgroup_context, f, prefix);
cgroup_context_dump(UNIT(s), f, prefix);
kill_context_dump(&s->kill_context, f, prefix);
}

View File

@ -905,7 +905,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
prefix, s->n_fd_store_max,
prefix, s->n_fd_store);
cgroup_context_dump(&s->cgroup_context, f, prefix);
cgroup_context_dump(UNIT(s), f, prefix);
}
static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) {

View File

@ -215,7 +215,7 @@ static void slice_dump(Unit *u, FILE *f, const char *prefix) {
"%sSlice State: %s\n",
prefix, slice_state_to_string(t->state));
cgroup_context_dump(&t->cgroup_context, f, prefix);
cgroup_context_dump(UNIT(t), f, prefix);
}
static int slice_start(Unit *u) {

View File

@ -843,7 +843,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
exec_command_dump_list(s->exec_command[c], f, prefix2);
}
cgroup_context_dump(&s->cgroup_context, f, prefix);
cgroup_context_dump(UNIT(s), f, prefix);
}
static int instance_from_socket(int fd, unsigned nr, char **instance) {

View File

@ -621,7 +621,7 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
exec_context_dump(&s->exec_context, f, prefix);
kill_context_dump(&s->kill_context, f, prefix);
cgroup_context_dump(&s->cgroup_context, f, prefix);
cgroup_context_dump(UNIT(s), f, prefix);
}
static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {