From: Michael Tremer Date: Sat, 14 Dec 2024 17:07:54 +0000 (+0000) Subject: cgroups: Recursively delete cgroups X-Git-Tag: 0.9.30~696 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=49f653ff7e135993184f4437a3b6fbd586f9f726;p=pakfire.git cgroups: Recursively delete cgroups Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/build.c b/src/libpakfire/build.c index 2eb3050cb..d231b6cff 100644 --- a/src/libpakfire/build.c +++ b/src/libpakfire/build.c @@ -1297,7 +1297,7 @@ static void pakfire_build_free(struct pakfire_build* build) { if (build->cgroup) { // Destroy the cgroup - pakfire_cgroup_destroy(build->cgroup); + pakfire_cgroup_destroy(build->cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE); // Free it pakfire_cgroup_unref(build->cgroup); diff --git a/src/libpakfire/cgroup.c b/src/libpakfire/cgroup.c index 296e75a88..a498c5541 100644 --- a/src/libpakfire/cgroup.c +++ b/src/libpakfire/cgroup.c @@ -18,6 +18,7 @@ # # #############################################################################*/ +#include #include #include #include @@ -130,7 +131,7 @@ static int pakfire_cgroup_open_root(struct pakfire_cgroup* cgroup) { int fd; // Open the root path - fd = open(path, O_DIRECTORY|O_PATH|O_CLOEXEC); + fd = open(path, O_DIRECTORY|O_CLOEXEC); if (fd < 0) { ERROR(cgroup->ctx, "Could not open %s: %m\n", path); return -errno; @@ -168,7 +169,7 @@ static int __pakfire_cgroup_open(struct pakfire_cgroup* cgroup) { } // Try opening the cgroup - fd = openat(cgroup->parent->fd, cgroup->name, O_DIRECTORY|O_PATH|O_CLOEXEC); + fd = openat(cgroup->parent->fd, cgroup->name, O_DIRECTORY|O_CLOEXEC); if (fd < 0) { ERROR(cgroup->ctx, "Could not open cgroup %s: %m\n", pakfire_cgroup_path(cgroup)); return -errno; @@ -526,16 +527,81 @@ int pakfire_cgroup_child(struct pakfire_cgroup** child, return pakfire_cgroup_open(child, cgroup->ctx, cgroup, path, flags); } +static int pakfire_cgroup_destroy_children(struct pakfire_cgroup* cgroup, int flags) { + struct pakfire_cgroup* child = NULL; + struct dirent* entry = NULL; + DIR* dir = NULL; + int r; + + // Open the directory + dir = fdopendir(cgroup->fd); + if (!dir) { + ERROR(cgroup->ctx, "Could not walk through child cgroups of %s: %m\n", + pakfire_cgroup_path(cgroup)); + r = -errno; + goto ERROR; + } + + // Walk through everything in the directory + for (;;) { + entry = readdir(dir); + if (!entry) + break; + + // Skip . and .., and so on + if (*entry->d_name == '.') + continue; + + // We are only interested in sub-directories + switch (entry->d_type) { + case DT_DIR: + break; + + default: + continue; + } + + // Try to open the cgroup + r = pakfire_cgroup_child(&child, cgroup, entry->d_name, 0); + if (r < 0) + goto ERROR; + + // Destroy the cgroup + r = pakfire_cgroup_destroy(child, flags); + if (r < 0) + goto ERROR; + + // Free the child + pakfire_cgroup_unref(child); + child = NULL; + } + +ERROR: + if (child) + pakfire_cgroup_unref(child); + if (dir) + closedir(dir); + + return r; +} + /* Immediately destroys this cgroup */ -int pakfire_cgroup_destroy(struct pakfire_cgroup* cgroup) { +int pakfire_cgroup_destroy(struct pakfire_cgroup* cgroup, int flags) { int r; // Cannot call this for the root group if (!cgroup->parent) return -EPERM; + // Destroy recursively? + if (flags & PAKFIRE_CGROUP_DESTROY_RECURSIVE) { + r = pakfire_cgroup_destroy_children(cgroup, flags); + if (r < 0) + return r; + } + DEBUG(cgroup->ctx, "Destroying cgroup %s\n", pakfire_cgroup_path(cgroup)); // Delete the directory diff --git a/src/libpakfire/include/pakfire/cgroup.h b/src/libpakfire/include/pakfire/cgroup.h index 1e169706f..493acae0a 100644 --- a/src/libpakfire/include/pakfire/cgroup.h +++ b/src/libpakfire/include/pakfire/cgroup.h @@ -211,7 +211,11 @@ struct pakfire_cgroup* pakfire_cgroup_unref(struct pakfire_cgroup* cgroup); int pakfire_cgroup_child(struct pakfire_cgroup** child, struct pakfire_cgroup* cgroup, const char* path, int flags); -int pakfire_cgroup_destroy(struct pakfire_cgroup* cgroup); +enum pakfire_cgroup_destroy_flags { + PAKFIRE_CGROUP_DESTROY_RECURSIVE = (1 << 0), +}; + +int pakfire_cgroup_destroy(struct pakfire_cgroup* cgroup, int flags); int pakfire_cgroup_fd(struct pakfire_cgroup* cgroup); diff --git a/src/libpakfire/jail.c b/src/libpakfire/jail.c index 4ffa504a8..f6b6a729b 100644 --- a/src/libpakfire/jail.c +++ b/src/libpakfire/jail.c @@ -1568,7 +1568,7 @@ ERROR: // Read cgroup stats pakfire_cgroup_stat(ctx.cgroup, &ctx.cgroup_stats); pakfire_cgroup_stat_dump(ctx.cgroup, &ctx.cgroup_stats); - pakfire_cgroup_destroy(ctx.cgroup); + pakfire_cgroup_destroy(ctx.cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE); pakfire_cgroup_unref(ctx.cgroup); } diff --git a/tests/libpakfire/cgroup.c b/tests/libpakfire/cgroup.c index efe661220..8e9581316 100644 --- a/tests/libpakfire/cgroup.c +++ b/tests/libpakfire/cgroup.c @@ -27,13 +27,17 @@ static int test_create_and_destroy(const struct test* t) { struct pakfire_cgroup* cgroup = NULL; + struct pakfire_cgroup* child = NULL; int r = EXIT_FAILURE; // Open a new cgroup ASSERT_SUCCESS(pakfire_cgroup_create(&cgroup, t->ctx, NULL, "pakfire-test", 0)); + // Create a child cgroup + ASSERT_SUCCESS(pakfire_cgroup_child(&child, cgroup, "child-group", 0)); + // Destroy the cgroup again - ASSERT_SUCCESS(pakfire_cgroup_destroy(cgroup)); + ASSERT_SUCCESS(pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE)); // Success r = EXIT_SUCCESS; @@ -41,6 +45,8 @@ static int test_create_and_destroy(const struct test* t) { FAIL: if (cgroup) pakfire_cgroup_unref(cgroup); + if (child) + pakfire_cgroup_unref(child); return r; } @@ -57,7 +63,7 @@ static int test_recursive(const struct test* t) { 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)); + ASSERT_SUCCESS(pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE)); // Success r = EXIT_SUCCESS; @@ -81,8 +87,8 @@ static int test_child(const struct test* t) { ASSERT_SUCCESS(pakfire_cgroup_child(&child, cgroup, "child-group", 0)); // Destroy the cgroups again - ASSERT_SUCCESS(pakfire_cgroup_destroy(child)); - ASSERT_SUCCESS(pakfire_cgroup_destroy(cgroup)); + ASSERT_SUCCESS(pakfire_cgroup_destroy(child, PAKFIRE_CGROUP_DESTROY_RECURSIVE)); + ASSERT_SUCCESS(pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE)); // Success r = EXIT_SUCCESS; @@ -135,7 +141,7 @@ static int test_stats(const struct test* t) { FAIL: if (cgroup) { - pakfire_cgroup_destroy(cgroup); + pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE); pakfire_cgroup_unref(cgroup); } if (jail) diff --git a/tests/libpakfire/jail.c b/tests/libpakfire/jail.c index 19aa428d0..819794ffc 100644 --- a/tests/libpakfire/jail.c +++ b/tests/libpakfire/jail.c @@ -177,7 +177,7 @@ static int test_launch_into_cgroup(const struct test* t) { FAIL: if (cgroup) { - pakfire_cgroup_destroy(cgroup); + pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE); pakfire_cgroup_unref(cgroup); } if (jail) @@ -252,7 +252,7 @@ FAIL: if (jail) pakfire_jail_unref(jail); if (cgroup) { - pakfire_cgroup_destroy(cgroup); + pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE); pakfire_cgroup_unref(cgroup); } @@ -286,7 +286,7 @@ FAIL: if (jail) pakfire_jail_unref(jail); if (cgroup) { - pakfire_cgroup_destroy(cgroup); + pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE); pakfire_cgroup_unref(cgroup); }