]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cgroups-show: optionally show cgroup xattrs + cgroup id in cgroup tree output
authorLennart Poettering <lennart@poettering.net>
Wed, 6 Oct 2021 15:06:50 +0000 (17:06 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 7 Oct 2021 09:50:42 +0000 (11:50 +0200)
src/shared/cgroup-show.c
src/shared/output-mode.h

index 060c19c57c3f7ec87c9fd4d8f52972cae8f482e2..c3eaf5387feae6c9126480aaaf14a6398eaa8ef1 100644 (file)
 #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;
+
+                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);
+        }
 
-        printf("%s%s%s%s%s %s%s%s\n",
-               prefix, glyph,
+        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;
 
index ba067c9f9c8e00b757db7baca56e8b41afb90391..4b4abfe75fb09f895bdb8ba6b87d7552c4573257 100644 (file)
@@ -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);