From 25a1f04c682260bb9b96e25bdf33665d6172db98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= Date: Wed, 29 Apr 2020 17:40:22 +0200 Subject: [PATCH] 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. --- src/basic/cgroup-util.c | 13 ++++++++++--- src/basic/cgroup-util.h | 24 +++++++++++++++++++++++- src/test/test-cgroup-util.c | 20 ++++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 33575e65ef..da4bd33d18 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1684,12 +1684,13 @@ int cg_get_attribute_as_uint64(const char *controller, const char *path, const c return 0; } -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; @@ -1749,7 +1750,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++) @@ -1759,6 +1763,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 237139fad0..6e05a8a5a1 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -180,9 +180,31 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path); int cg_rmdir(const char *controller, const char *path); +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_get_attribute_as_uint64(const char *controller, const char *path, const char *attribute, uint64_t *ret); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index daaffb5a06..5826d6ec28 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -384,22 +384,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]);