Compare commits

..

6 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek 9389a3cdc8
Merge pull request #14093 from poettering/cgroups-delegate-xattr
mark delegated cgroups via xattr, and visualize the cut points in cgls
2019-11-20 23:53:03 +01:00
Lennart Poettering 7daa88ee5d update TODO 2019-11-20 17:51:28 +01:00
Lennart Poettering a2e361dc27 cgls: visually separate processes from cgroups
Let's show them in grey, since we generally want to focus on showing the
cgroups much less than the processes in them.
2019-11-20 17:51:28 +01:00
Lennart Poettering 74d8ccd451 cgls: show delegation boundaries by underlining the cgroup in the output
This should help visualize where one manager's territory begins and
another's starts. Do this by underlining (since it's a "cut" point an
underline made most sense to me). Since underlining is not visible on
the console let's also show an ellipses for all lines that are
delegation boundaries.

Unfortunately this all is not as useful as it appears. The
"trusted.delegate" xattr is only visible to roo, which means
"systemd-cgls" has be called as root to show the boundaries.
Unfortunately cgroupfs doesn't support unprivileged xattrs on cgroups.
2019-11-20 17:50:12 +01:00
Lennart Poettering 3288ea8f32 core: set "trusted.delegate" xattr on cgroups that are delegation boundaries
Let's mark cgroups that are delegation boundaries to us. This can then
be used by tools such as "systemd-cgls" to show where the next manager
takes over.
2019-11-20 17:50:12 +01:00
Lennart Poettering bf25f1657f cgroup-util: add new cg_remove_xattr() for removing xattr from cgroup 2019-11-20 17:50:12 +01:00
5 changed files with 86 additions and 16 deletions

4
TODO
View File

@ -166,10 +166,6 @@ Features:
* sd-boot: optionally, show boot menu when previous default boot item has
non-zero "tries done" count
* maybe set a special xattr on cgroups that have delegate=yes set, to make it
easy to mark cut points, then use this information in "systemd-cgls" to show
them (e.g. color delegated subtrees in a different color)
* introduce an option (or replacement) for "systemctl show" that outputs all
properties as JSON, similar to busctl's new JSON output. In contrast to that
it should skip the variant type string though.

View File

@ -605,6 +605,23 @@ int cg_get_xattr(const char *controller, const char *path, const char *name, voi
return (int) n;
}
int cg_remove_xattr(const char *controller, const char *path, const char *name) {
_cleanup_free_ char *fs = NULL;
int r;
assert(path);
assert(name);
r = cg_get_path(controller, path, NULL, &fs);
if (r < 0)
return r;
if (removexattr(fs, name) < 0)
return -errno;
return 0;
}
int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
_cleanup_fclose_ FILE *f = NULL;
const char *fs, *controller_str;

View File

@ -188,6 +188,7 @@ int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid
int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size);
int cg_remove_xattr(const char *controller, const char *path, const char *name);
int cg_install_release_agent(const char *controller, const char *agent);
int cg_uninstall_release_agent(const char *controller);

View File

@ -617,15 +617,27 @@ static void cgroup_xattr_apply(Unit *u) {
if (!MANAGER_IS_SYSTEM(u->manager))
return;
if (sd_id128_is_null(u->invocation_id))
return;
if (!sd_id128_is_null(u->invocation_id)) {
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
"trusted.invocation_id",
sd_id128_to_string(u->invocation_id, ids), 32,
0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path);
}
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
"trusted.invocation_id",
sd_id128_to_string(u->invocation_id, ids), 32,
0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path);
if (unit_cgroup_delegate(u)) {
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
"trusted.delegate",
"1", 1,
0);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set delegate flag on control group %s, ignoring: %m", u->cgroup_path);
} else {
r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "trusted.delegate");
if (r != -ENODATA)
log_unit_debug_errno(u, r, "Failed to remove delegate flag on control group %s, ignoring: %m", u->cgroup_path);
}
}
static int lookup_block_device(const char *p, dev_t *ret) {

View File

@ -17,12 +17,14 @@
#include "locale-util.h"
#include "macro.h"
#include "output-mode.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "sort-util.h"
#include "string-util.h"
#include "terminal-util.h"
#include "unit-name.h"
#include "xattr-util.h"
static void show_pid_array(
pid_t pids[],
@ -69,7 +71,7 @@ static void show_pid_array(
else
printf("%s%s", prefix, special_glyph(((more || i < n_pids-1) ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT)));
printf("%*"PID_PRI" %s\n", pid_width, pids[i], strna(t));
printf("%s%*"PID_PRI" %s%s\n", ansi_grey(), pid_width, pids[i], strna(t), ansi_normal());
}
}
@ -117,6 +119,44 @@ static int show_cgroup_one_by_path(
return 0;
}
static int show_cgroup_name(
const char *path,
const char *prefix,
const char *glyph) {
_cleanup_free_ char *b = NULL;
bool delegate = false;
int r;
r = getxattr_malloc(path, "trusted.delegate", &b, false);
if (r < 0) {
if (r != -ENODATA)
log_debug_errno(r, "Failed to read trusted.delegate extended attribute: %m");
} else {
r = parse_boolean(b);
if (r < 0)
log_debug_errno(r, "Failed to parse trusted.delegate extended attribute boolean value: %m");
else
delegate = r > 0;
b = mfree(b);
}
b = strdup(basename(path));
if (!b)
return -ENOMEM;
printf("%s%s%s%s%s %s%s%s\n",
prefix, glyph,
delegate ? ansi_underline() : "",
cg_unescape(b),
delegate ? ansi_normal() : "",
delegate ? ansi_highlight() : "",
delegate ? special_glyph(SPECIAL_GLYPH_ELLIPSIS) : "",
delegate ? ansi_normal() : "");
return 0;
}
int show_cgroup_by_path(
const char *path,
const char *prefix,
@ -125,8 +165,8 @@ int show_cgroup_by_path(
_cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
_cleanup_closedir_ DIR *d = NULL;
char *gn = NULL;
bool shown_pids = false;
char *gn = NULL;
int r;
assert(path);
@ -161,7 +201,9 @@ int show_cgroup_by_path(
}
if (last) {
printf("%s%s%s\n", prefix, special_glyph(SPECIAL_GLYPH_TREE_BRANCH), cg_unescape(basename(last)));
r = show_cgroup_name(last, prefix, special_glyph(SPECIAL_GLYPH_TREE_BRANCH));
if (r < 0)
return r;
if (!p1) {
p1 = strjoin(prefix, special_glyph(SPECIAL_GLYPH_TREE_VERTICAL));
@ -183,7 +225,9 @@ int show_cgroup_by_path(
show_cgroup_one_by_path(path, prefix, n_columns, !!last, flags);
if (last) {
printf("%s%s%s\n", prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT), cg_unescape(basename(last)));
r = show_cgroup_name(last, prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
if (r < 0)
return r;
if (!p2) {
p2 = strjoin(prefix, " ");