]> git.ipfire.org Git - pakfire.git/commitdiff
cgroups: Recursively delete cgroups
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 14 Dec 2024 17:07:54 +0000 (17:07 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 14 Dec 2024 17:07:54 +0000 (17:07 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/build.c
src/libpakfire/cgroup.c
src/libpakfire/include/pakfire/cgroup.h
src/libpakfire/jail.c
tests/libpakfire/cgroup.c
tests/libpakfire/jail.c

index 2eb3050cbfcec89e2e43b52bd7092ea924b90941..d231b6cff25468995f86da8c136b738cc722dc55 100644 (file)
@@ -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);
index 296e75a8820c58d86a2c8b3b3e19f17eb553d595..a498c55410a4a04b2d40b29e0a07d6e1d5d6e9d0 100644 (file)
@@ -18,6 +18,7 @@
 #                                                                             #
 #############################################################################*/
 
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <linux/bpf.h>
@@ -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
index 1e169706fc8da0674a0eabeb9f8b842ed707e0cc..493acae0a2ec6c227441a5619f42e354a41d71a1 100644 (file)
@@ -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);
 
index 4ffa504a817fb16293e0be150fc2d466c040b575..f6b6a729b1a952b6c658b1a2ab04f61807017278 100644 (file)
@@ -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);
        }
 
index efe661220b8cd24f561ecc5cdde3084091d2f2b9..8e958131601750aed37ecc80bc359061e4bbdbfc 100644 (file)
 
 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)
index 19aa428d08ba95ae48d34eb2643235369827e6d9..819794ffc0ba08a08854206b3a47ebf03afcb374 100644 (file)
@@ -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);
        }