52b84b
From 5aefc153b25b42a80942e5c367ce143817551870 Mon Sep 17 00:00:00 2001
52b84b
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
52b84b
Date: Wed, 29 Apr 2020 17:40:22 +0200
52b84b
Subject: [PATCH] basic/cgroup-util: introduce cg_get_keyed_attribute_full()
52b84b
52b84b
Callers of cg_get_keyed_attribute_full() can now specify via the flag whether the
52b84b
missing keyes in cgroup attribute file are OK or not. Also the wrappers for both
52b84b
strict and graceful version are provided.
52b84b
52b84b
(cherry picked from commit 25a1f04c682260bb9b96e25bdf33665d6172db98)
52b84b
52b84b
Related: #1830861
52b84b
---
52b84b
 src/basic/cgroup-util.c     | 13 ++++++++++---
52b84b
 src/basic/cgroup-util.h     | 24 +++++++++++++++++++++++-
52b84b
 src/test/test-cgroup-util.c | 20 ++++++++++++++++++++
52b84b
 3 files changed, 53 insertions(+), 4 deletions(-)
52b84b
52b84b
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
52b84b
index 92bc1f2543..4c0b73850d 100644
52b84b
--- a/src/basic/cgroup-util.c
52b84b
+++ b/src/basic/cgroup-util.c
52b84b
@@ -2021,12 +2021,13 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri
52b84b
         return read_one_line_file(p, ret);
52b84b
 }
52b84b
 
52b84b
-int cg_get_keyed_attribute(
52b84b
+int cg_get_keyed_attribute_full(
52b84b
                 const char *controller,
52b84b
                 const char *path,
52b84b
                 const char *attribute,
52b84b
                 char **keys,
52b84b
-                char **ret_values) {
52b84b
+                char **ret_values,
52b84b
+                CGroupKeyMode mode) {
52b84b
 
52b84b
         _cleanup_free_ char *filename = NULL, *contents = NULL;
52b84b
         const char *p;
52b84b
@@ -2086,7 +2087,10 @@ int cg_get_keyed_attribute(
52b84b
                 p += strspn(p, NEWLINE);
52b84b
         }
52b84b
 
52b84b
-        r = -ENXIO;
52b84b
+        if (mode & CG_KEY_MODE_GRACEFUL)
52b84b
+                goto done;
52b84b
+        else
52b84b
+                r = -ENXIO;
52b84b
 
52b84b
 fail:
52b84b
         for (i = 0; i < n; i++)
52b84b
@@ -2096,6 +2100,9 @@ fail:
52b84b
 
52b84b
 done:
52b84b
         memcpy(ret_values, v, sizeof(char*) * n);
52b84b
+        if (mode & CG_KEY_MODE_GRACEFUL)
52b84b
+                return n_done;
52b84b
+
52b84b
         return 0;
52b84b
 
52b84b
 }
52b84b
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
52b84b
index b414600dca..0673f4b4ce 100644
52b84b
--- a/src/basic/cgroup-util.h
52b84b
+++ b/src/basic/cgroup-util.h
52b84b
@@ -167,9 +167,31 @@ int cg_attach(const char *controller, const char *path, pid_t pid);
52b84b
 int cg_attach_fallback(const char *controller, const char *path, pid_t pid);
52b84b
 int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
52b84b
 
52b84b
+typedef enum  {
52b84b
+        CG_KEY_MODE_GRACEFUL = 1 << 0,
52b84b
+} CGroupKeyMode;
52b84b
+
52b84b
 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value);
52b84b
 int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret);
52b84b
-int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, char **keys, char **values);
52b84b
+int cg_get_keyed_attribute_full(const char *controller, const char *path, const char *attribute, char **keys, char **values, CGroupKeyMode mode);
52b84b
+
52b84b
+static inline int cg_get_keyed_attribute(
52b84b
+                const char *controller,
52b84b
+                const char *path,
52b84b
+                const char *attribute,
52b84b
+                char **keys,
52b84b
+                char **ret_values) {
52b84b
+        return cg_get_keyed_attribute_full(controller, path, attribute, keys, ret_values, 0);
52b84b
+}
52b84b
+
52b84b
+static inline int cg_get_keyed_attribute_graceful(
52b84b
+                const char *controller,
52b84b
+                const char *path,
52b84b
+                const char *attribute,
52b84b
+                char **keys,
52b84b
+                char **ret_values) {
52b84b
+        return cg_get_keyed_attribute_full(controller, path, attribute, keys, ret_values, CG_KEY_MODE_GRACEFUL);
52b84b
+}
52b84b
 
52b84b
 int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid);
52b84b
 
52b84b
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
52b84b
index d49356315e..60d7bb19cb 100644
52b84b
--- a/src/test/test-cgroup-util.c
52b84b
+++ b/src/test/test-cgroup-util.c
52b84b
@@ -421,22 +421,42 @@ static void test_cg_get_keyed_attribute(void) {
52b84b
         }
52b84b
 
52b84b
         assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("no_such_attr"), &val) == -ENXIO);
52b84b
+        assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", STRV_MAKE("no_such_attr"), &val) == 0);
52b84b
         assert_se(val == NULL);
52b84b
 
52b84b
         assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec"), &val) == 0);
52b84b
+        free(val);
52b84b
+
52b84b
+        assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec"), &val) == 1);
52b84b
         log_info("cpu /init.scope cpu.stat [usage_usec] → \"%s\"", val);
52b84b
 
52b84b
         assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "no_such_attr"), vals3) == -ENXIO);
52b84b
+        assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "no_such_attr"), vals3) == 1);
52b84b
+        assert(vals3[0] && !vals3[1]);
52b84b
+        free(vals3[0]);
52b84b
 
52b84b
         assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "usage_usec"), vals3) == -ENXIO);
52b84b
+        assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "usage_usec"), vals3) == 1);
52b84b
+        assert(vals3[0] && !vals3[1]);
52b84b
+        free(vals3[0]);
52b84b
 
52b84b
         assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat",
52b84b
                                          STRV_MAKE("usage_usec", "user_usec", "system_usec"), vals3) == 0);
52b84b
+        for (i = 0; i < 3; i++)
52b84b
+                free(vals3[i]);
52b84b
+
52b84b
+        assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat",
52b84b
+                                         STRV_MAKE("usage_usec", "user_usec", "system_usec"), vals3) == 3);
52b84b
         log_info("cpu /init.scope cpu.stat [usage_usec user_usec system_usec] → \"%s\", \"%s\", \"%s\"",
52b84b
                  vals3[0], vals3[1], vals3[2]);
52b84b
 
52b84b
         assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat",
52b84b
                                          STRV_MAKE("system_usec", "user_usec", "usage_usec"), vals3a) == 0);
52b84b
+        for (i = 0; i < 3; i++)
52b84b
+                free(vals3a[i]);
52b84b
+
52b84b
+        assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat",
52b84b
+                                         STRV_MAKE("system_usec", "user_usec", "usage_usec"), vals3a) == 3);
52b84b
         log_info("cpu /init.scope cpu.stat [system_usec user_usec usage_usec] → \"%s\", \"%s\", \"%s\"",
52b84b
                  vals3a[0], vals3a[1], vals3a[2]);
52b84b