From 8bf42597d736bc357ca55842dd4a8102fe3c28d8 Mon Sep 17 00:00:00 2001 From: Michal Sekletár Date: Dec 15 2020 09:45:53 +0000 Subject: basic/cgroup-util: introduce cg_get_keyed_attribute_full() Callers of cg_get_keyed_attribute_full() can now specify via the flag whether the missing keyes in cgroup attribute file are OK or not. Also the wrappers for both strict and graceful version are provided. (cherry picked from commit 25a1f04c682260bb9b96e25bdf33665d6172db98) Related: #1830861 patch_name: 0419-basic-cgroup-util-introduce-cg_get_keyed_attribute_f.patch present_in_specfile: true location_in_specfile: 419 squash_commits: true --- diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 92bc1f2..4c0b738 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -2021,12 +2021,13 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri return read_one_line_file(p, ret); } -int cg_get_keyed_attribute( +int cg_get_keyed_attribute_full( const char *controller, const char *path, const char *attribute, char **keys, - char **ret_values) { + char **ret_values, + CGroupKeyMode mode) { _cleanup_free_ char *filename = NULL, *contents = NULL; const char *p; @@ -2086,7 +2087,10 @@ int cg_get_keyed_attribute( p += strspn(p, NEWLINE); } - r = -ENXIO; + if (mode & CG_KEY_MODE_GRACEFUL) + goto done; + else + r = -ENXIO; fail: for (i = 0; i < n; i++) @@ -2096,6 +2100,9 @@ fail: done: memcpy(ret_values, v, sizeof(char*) * n); + if (mode & CG_KEY_MODE_GRACEFUL) + return n_done; + return 0; } diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index b414600..0673f4b 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -167,9 +167,31 @@ int cg_attach(const char *controller, const char *path, pid_t pid); int cg_attach_fallback(const char *controller, const char *path, pid_t pid); int cg_create_and_attach(const char *controller, const char *path, pid_t pid); +typedef enum { + CG_KEY_MODE_GRACEFUL = 1 << 0, +} CGroupKeyMode; + int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value); int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret); -int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, char **keys, char **values); +int cg_get_keyed_attribute_full(const char *controller, const char *path, const char *attribute, char **keys, char **values, CGroupKeyMode mode); + +static inline int cg_get_keyed_attribute( + const char *controller, + const char *path, + const char *attribute, + char **keys, + char **ret_values) { + return cg_get_keyed_attribute_full(controller, path, attribute, keys, ret_values, 0); +} + +static inline int cg_get_keyed_attribute_graceful( + const char *controller, + const char *path, + const char *attribute, + char **keys, + char **ret_values) { + return cg_get_keyed_attribute_full(controller, path, attribute, keys, ret_values, CG_KEY_MODE_GRACEFUL); +} int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index d493563..60d7bb1 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -421,22 +421,42 @@ static void test_cg_get_keyed_attribute(void) { } assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("no_such_attr"), &val) == -ENXIO); + assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", STRV_MAKE("no_such_attr"), &val) == 0); assert_se(val == NULL); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec"), &val) == 0); + free(val); + + assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec"), &val) == 1); log_info("cpu /init.scope cpu.stat [usage_usec] → \"%s\"", val); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "no_such_attr"), vals3) == -ENXIO); + assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "no_such_attr"), vals3) == 1); + assert(vals3[0] && !vals3[1]); + free(vals3[0]); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "usage_usec"), vals3) == -ENXIO); + assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "usage_usec"), vals3) == 1); + assert(vals3[0] && !vals3[1]); + free(vals3[0]); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "user_usec", "system_usec"), vals3) == 0); + for (i = 0; i < 3; i++) + free(vals3[i]); + + assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", + STRV_MAKE("usage_usec", "user_usec", "system_usec"), vals3) == 3); log_info("cpu /init.scope cpu.stat [usage_usec user_usec system_usec] → \"%s\", \"%s\", \"%s\"", vals3[0], vals3[1], vals3[2]); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("system_usec", "user_usec", "usage_usec"), vals3a) == 0); + for (i = 0; i < 3; i++) + free(vals3a[i]); + + assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat", + STRV_MAKE("system_usec", "user_usec", "usage_usec"), vals3a) == 3); log_info("cpu /init.scope cpu.stat [system_usec user_usec usage_usec] → \"%s\", \"%s\", \"%s\"", vals3a[0], vals3a[1], vals3a[2]);