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