From: Michael Tremer Date: Sat, 14 Dec 2024 15:06:09 +0000 (+0000) Subject: cgroups: Implement recursion again X-Git-Tag: 0.9.30~709 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1eefc298e19c8ef9837bcbc062a43597a466dbf9;p=pakfire.git cgroups: Implement recursion again Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/cgroup.c b/src/libpakfire/cgroup.c index 5bef076d1..94a0f09b9 100644 --- a/src/libpakfire/cgroup.c +++ b/src/libpakfire/cgroup.c @@ -423,13 +423,59 @@ ERROR: return r; } +static int pakfire_cgroup_create_recursive(struct pakfire_cgroup** cgroup, + struct pakfire_ctx* ctx, struct pakfire_cgroup* parent, const char* name, int flags) { + struct pakfire_cgroup* child = NULL; + char buffer[NAME_MAX]; + char* p = NULL; + int r; + + // Name cannot be empty + if (!name || !*name) + return -EINVAL; + + // Does the name contain a /? + p = strchr(name, '/'); + + // We have reached the end of the recursion + if (!p) + return pakfire_cgroup_open(cgroup, ctx, parent, name, flags); + + // Copy the string to the buffer + r = pakfire_string_format(buffer, "%.*s", (int)(p - name), name); + if (r < 0) + return r; + + // Create the child cgroup + r = pakfire_cgroup_child(&child, parent, buffer, flags); + if (r < 0) + goto ERROR; + + // Continue processing name... + r = pakfire_cgroup_create_recursive(cgroup, ctx, child, ++p, flags); + if (r < 0) + goto ERROR; + + // Done + +ERROR: + if (child) + pakfire_cgroup_unref(child); + + return r; +} + int pakfire_cgroup_create(struct pakfire_cgroup** cgroup, struct pakfire_ctx* ctx, struct pakfire_cgroup* parent, const char* name, int flags) { struct pakfire_cgroup* root = NULL; int r; - // If parent is NULL, but name is set, we will create the root group and use it as parent - if (name && !parent) { + // Name must be set + if (!name) + return -EINVAL; + + // If parent is NULL, we open the root as parent + if (!parent) { r = pakfire_cgroup_open(&root, ctx, NULL, NULL, 0); if (r < 0) return r; @@ -438,7 +484,7 @@ int pakfire_cgroup_create(struct pakfire_cgroup** cgroup, } // Recursively create the new cgroup - r = pakfire_cgroup_open(cgroup, ctx, parent, name, flags); + r = pakfire_cgroup_create_recursive(cgroup, ctx, parent, name, flags); // Cleanup if (root) diff --git a/tests/libpakfire/cgroup.c b/tests/libpakfire/cgroup.c index 0970560b2..efe661220 100644 --- a/tests/libpakfire/cgroup.c +++ b/tests/libpakfire/cgroup.c @@ -45,6 +45,30 @@ FAIL: return r; } +static int test_recursive(const struct test* t) { + struct pakfire_cgroup* cgroup = NULL; + int r = EXIT_FAILURE; + + // Try to create some invalid cgroups + ASSERT(pakfire_cgroup_create(&cgroup, t->ctx, NULL, NULL, 0) == -EINVAL); + ASSERT(pakfire_cgroup_create(&cgroup, t->ctx, NULL, "pakfire-test/a/", 0) == -EINVAL); + + // Open a new cgroup + ASSERT_SUCCESS(pakfire_cgroup_create(&cgroup, t->ctx, NULL, "pakfire-test/a/b/c", 0)); + + // Destroy the cgroup again + ASSERT_SUCCESS(pakfire_cgroup_destroy(cgroup)); + + // Success + r = EXIT_SUCCESS; + +FAIL: + if (cgroup) + pakfire_cgroup_unref(cgroup); + + return r; +} + static int test_child(const struct test* t) { struct pakfire_cgroup* cgroup = NULL; struct pakfire_cgroup* child = NULL; @@ -122,6 +146,7 @@ FAIL: int main(int argc, const char* argv[]) { testsuite_add_test(test_create_and_destroy, 0); + testsuite_add_test(test_recursive, 0); testsuite_add_test(test_child, 0); testsuite_add_test(test_stats, TEST_WANTS_PAKFIRE);