From 5a5a5d29147f9e87f05e1b3a6124c64d2a53350e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Oct 2021 17:06:50 +0200 Subject: [PATCH] cgroups-show: optionally show cgroup xattrs + cgroup id in cgroup tree output --- src/shared/cgroup-show.c | 101 +++++++++++++++++++++++++++++++++------ src/shared/output-mode.h | 16 +++++-- 2 files changed, 98 insertions(+), 19 deletions(-) diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index 060c19c57c..c3eaf5387f 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -12,11 +12,13 @@ #include "cgroup-show.h" #include "cgroup-util.h" #include "env-file.h" +#include "escape.h" #include "fd-util.h" #include "format-util.h" #include "hostname-util.h" #include "locale-util.h" #include "macro.h" +#include "nulstr-util.h" #include "output-mode.h" #include "parse-util.h" #include "path-util.h" @@ -122,38 +124,109 @@ static int show_cgroup_one_by_path( static int show_cgroup_name( const char *path, const char *prefix, - const char *glyph) { + SpecialGlyph glyph, + OutputFlags flags) { + uint64_t cgroupid = UINT64_MAX; _cleanup_free_ char *b = NULL; + _cleanup_close_ int fd = -1; bool delegate = false; int r; - r = lgetxattr_malloc(path, "trusted.delegate", &b); + if (FLAGS_SET(flags, OUTPUT_CGROUP_XATTRS) || FLAGS_SET(flags, OUTPUT_CGROUP_ID)) { + fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW|O_DIRECTORY, 0); + if (fd < 0) + log_debug_errno(errno, "Failed to open cgroup '%s', ignoring: %m", path); + } + + r = getxattr_malloc(fd < 0 ? path : FORMAT_PROC_FD_PATH(fd), "trusted.delegate", &b); if (r < 0) { if (r != -ENODATA) - log_debug_errno(r, "Failed to read trusted.delegate extended attribute: %m"); + log_debug_errno(r, "Failed to read trusted.delegate extended attribute, ignoring: %m"); } else { r = parse_boolean(b); if (r < 0) - log_debug_errno(r, "Failed to parse trusted.delegate extended attribute boolean value: %m"); + log_debug_errno(r, "Failed to parse trusted.delegate extended attribute boolean value, ignoring: %m"); else delegate = r > 0; b = mfree(b); } - b = strdup(basename(path)); - if (!b) - return -ENOMEM; + if (FLAGS_SET(flags, OUTPUT_CGROUP_ID)) { + cg_file_handle fh = CG_FILE_HANDLE_INIT; + int mnt_id = -1; - printf("%s%s%s%s%s %s%s%s\n", - prefix, glyph, + if (name_to_handle_at( + fd < 0 ? AT_FDCWD : fd, + fd < 0 ? path : "", + &fh.file_handle, + &mnt_id, + fd < 0 ? 0 : AT_EMPTY_PATH) < 0) + log_debug_errno(errno, "Failed to determine cgroup ID of %s, ignoring: %m", path); + else + cgroupid = CG_FILE_HANDLE_CGROUPID(fh); + } + + r = path_extract_filename(path, &b); + if (r < 0) + return log_error_errno(r, "Failed to extract filename from cgroup path: %m"); + + printf("%s%s%s%s%s", + prefix, special_glyph(glyph), delegate ? ansi_underline() : "", cg_unescape(b), - delegate ? ansi_normal() : "", - delegate ? ansi_highlight() : "", - delegate ? special_glyph(SPECIAL_GLYPH_ELLIPSIS) : "", delegate ? ansi_normal() : ""); + + if (delegate) + printf(" %s%s%s", + ansi_highlight(), + special_glyph(SPECIAL_GLYPH_ELLIPSIS), + ansi_normal()); + + if (cgroupid != UINT64_MAX) + printf(" %s(#%" PRIu64 ")%s", ansi_grey(), cgroupid, ansi_normal()); + + printf("\n"); + + if (FLAGS_SET(flags, OUTPUT_CGROUP_XATTRS) && fd >= 0) { + _cleanup_free_ char *nl = NULL; + char *xa; + + r = flistxattr_malloc(fd, &nl); + if (r < 0) + log_debug_errno(r, "Failed to enumerate xattrs on '%s', ignoring: %m", path); + + NULSTR_FOREACH(xa, nl) { + _cleanup_free_ char *x = NULL, *y = NULL, *buf = NULL; + int n; + + if (!STARTSWITH_SET(xa, "user.", "trusted.")) + continue; + + n = fgetxattr_malloc(fd, xa, &buf); + if (n < 0) { + log_debug_errno(r, "Failed to read xattr '%s' off '%s', ignoring: %m", xa, path); + continue; + } + + x = cescape(xa); + if (!x) + return -ENOMEM; + + y = cescape_length(buf, n); + if (!y) + return -ENOMEM; + + printf("%s%s%s %s%s%s: %s\n", + prefix, + glyph == SPECIAL_GLYPH_TREE_BRANCH ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " ", + special_glyph(SPECIAL_GLYPH_ARROW), + ansi_blue(), x, ansi_normal(), + y); + } + } + return 0; } @@ -201,7 +274,7 @@ int show_cgroup_by_path( } if (last) { - r = show_cgroup_name(last, prefix, special_glyph(SPECIAL_GLYPH_TREE_BRANCH)); + r = show_cgroup_name(last, prefix, SPECIAL_GLYPH_TREE_BRANCH, flags); if (r < 0) return r; @@ -225,7 +298,7 @@ int show_cgroup_by_path( show_cgroup_one_by_path(path, prefix, n_columns, !!last, flags); if (last) { - r = show_cgroup_name(last, prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT)); + r = show_cgroup_name(last, prefix, SPECIAL_GLYPH_TREE_RIGHT, flags); if (r < 0) return r; diff --git a/src/shared/output-mode.h b/src/shared/output-mode.h index ba067c9f9c..4b4abfe75f 100644 --- a/src/shared/output-mode.h +++ b/src/shared/output-mode.h @@ -33,14 +33,20 @@ static inline bool OUTPUT_MODE_IS_JSON(OutputMode m) { typedef enum OutputFlags { OUTPUT_SHOW_ALL = 1 << 0, - OUTPUT_WARN_CUTOFF = 1 << 1, - OUTPUT_FULL_WIDTH = 1 << 2, - OUTPUT_COLOR = 1 << 3, + OUTPUT_FULL_WIDTH = 1 << 1, + OUTPUT_COLOR = 1 << 2, + + /* Specific to log output */ + OUTPUT_WARN_CUTOFF = 1 << 3, OUTPUT_CATALOG = 1 << 4, OUTPUT_BEGIN_NEWLINE = 1 << 5, OUTPUT_UTC = 1 << 6, - OUTPUT_KERNEL_THREADS = 1 << 7, - OUTPUT_NO_HOSTNAME = 1 << 8, + OUTPUT_NO_HOSTNAME = 1 << 7, + + /* Specific to process tree output */ + OUTPUT_KERNEL_THREADS = 1 << 8, + OUTPUT_CGROUP_XATTRS = 1 << 9, + OUTPUT_CGROUP_ID = 1 << 10, } OutputFlags; JsonFormatFlags output_mode_to_json_format_flags(OutputMode m);