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);
# #
#############################################################################*/
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/bpf.h>
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;
}
// 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;
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
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);
// 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);
}
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;
FAIL:
if (cgroup)
pakfire_cgroup_unref(cgroup);
+ if (child)
+ pakfire_cgroup_unref(child);
return r;
}
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;
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;
FAIL:
if (cgroup) {
- pakfire_cgroup_destroy(cgroup);
+ pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE);
pakfire_cgroup_unref(cgroup);
}
if (jail)
FAIL:
if (cgroup) {
- pakfire_cgroup_destroy(cgroup);
+ pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE);
pakfire_cgroup_unref(cgroup);
}
if (jail)
if (jail)
pakfire_jail_unref(jail);
if (cgroup) {
- pakfire_cgroup_destroy(cgroup);
+ pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE);
pakfire_cgroup_unref(cgroup);
}
if (jail)
pakfire_jail_unref(jail);
if (cgroup) {
- pakfire_cgroup_destroy(cgroup);
+ pakfire_cgroup_destroy(cgroup, PAKFIRE_CGROUP_DESTROY_RECURSIVE);
pakfire_cgroup_unref(cgroup);
}