From: Michael Tremer Date: Mon, 9 Dec 2024 17:20:07 +0000 (+0000) Subject: cgroups: Keep a reference to the parent group X-Git-Tag: 0.9.30~735 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4addfe61d9284007453c6e1766071c6b8e5d17a6;p=pakfire.git cgroups: Keep a reference to the parent group Since so many operations are recursive, this might be easier to handle. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/cgroup.c b/src/libpakfire/cgroup.c index e2679ecf3..75647be48 100644 --- a/src/libpakfire/cgroup.c +++ b/src/libpakfire/cgroup.c @@ -61,6 +61,9 @@ struct pakfire_cgroup { struct pakfire_ctx* ctx; int nrefs; + // The parent group + struct pakfire_cgroup* parent; + // Store the root path char root[PATH_MAX]; @@ -77,11 +80,6 @@ struct pakfire_cgroup { int devicesfd; }; -// Returns true if this is the root cgroup -static int pakfire_cgroup_is_root(struct pakfire_cgroup* cgroup) { - return !*cgroup->path; -} - static int pakfire_cgroup_set_root(struct pakfire_cgroup* cgroup) { int r; @@ -108,21 +106,19 @@ static int pakfire_cgroup_set_root(struct pakfire_cgroup* cgroup) { } static const char* pakfire_cgroup_name(struct pakfire_cgroup* cgroup) { - if (pakfire_cgroup_is_root(cgroup)) + if (!cgroup->parent) return "(root)"; return cgroup->path; } -static int pakfire_cgroup_parent(struct pakfire_cgroup* cgroup, struct pakfire_cgroup** parent) { +static int pakfire_cgroup_parent(struct pakfire_cgroup* cgroup, struct pakfire_cgroup** parent) { char path[PATH_MAX]; int r; - // Cannot return parent for root group - if (pakfire_cgroup_is_root(cgroup)) { - *parent = NULL; + // If there is no path left, we have reached the root + if (!*cgroup->path) return 0; - } // Determine the path of the parent r = pakfire_path_dirname(path, cgroup->path); @@ -176,27 +172,12 @@ static int pakfire_cgroup_open_root(struct pakfire_cgroup* cgroup) { int fd = open(cgroup->root, O_DIRECTORY|O_PATH|O_CLOEXEC); if (fd < 0) { ERROR(cgroup->ctx, "Could not open %s: %m\n", cgroup->root); - return -1; + return -errno; } return fd; } -static int __pakfire_cgroup_create(struct pakfire_cgroup* cgroup) { - char path[PATH_MAX]; - int r; - - DEBUG(cgroup->ctx, "Trying to create cgroup %s\n", pakfire_cgroup_name(cgroup)); - - // Compose the absolute path - r = pakfire_path_append(path, cgroup->root, cgroup->path); - if (r) - return 1; - - // Try creating the directory - return pakfire_mkdir(path, 0755); -} - /* Opens the cgroup and returns a file descriptor. @@ -204,44 +185,40 @@ static int __pakfire_cgroup_create(struct pakfire_cgroup* cgroup) { This function returns a negative value on error. */ -static int __pakfire_cgroup_open(struct pakfire_cgroup* cgroup) { +static int pakfire_cgroup_open(struct pakfire_cgroup* cgroup) { + char basename[NAME_MAX]; int fd = -EBADF; int r; - // Open file descriptor of the cgroup root - int rootfd = pakfire_cgroup_open_root(cgroup); - if (rootfd < 0) - return rootfd; + // Open the root cgroup + if (!cgroup->parent) + return pakfire_cgroup_open_root(cgroup); - // Return the rootfd for the root group - if (pakfire_cgroup_is_root(cgroup)) - return rootfd; + // Get the basename + r = pakfire_path_basename(basename, cgroup->path); + if (r < 0) + return r; -RETRY: - fd = openat(rootfd, cgroup->path, O_DIRECTORY|O_PATH|O_CLOEXEC); + // Try to open the cgroup + fd = openat(cgroup->parent->fd, basename, O_DIRECTORY|O_PATH|O_CLOEXEC); if (fd < 0) { switch (errno) { - // If the cgroup doesn't exist yet, try to create it case ENOENT: - r = __pakfire_cgroup_create(cgroup); - if (r) - goto ERROR; + r = mkdirat(cgroup->parent->fd, basename, 0755); + if (r < 0) { + ERROR(cgroup->ctx, "Could not create cgroup '%s': %m\n", basename); + return -errno; + } - // Retry open after successful creation - goto RETRY; + // Try opening it again + return pakfire_cgroup_open(cgroup); - // Exit on all other errors default: - ERROR(cgroup->ctx, "Could not open cgroup %s: %m\n", - pakfire_cgroup_name(cgroup)); - goto ERROR; + ERROR(cgroup->ctx, "Could not open cgroup '%s': %m\n", basename); + return -errno; } } -ERROR: - if (rootfd > 0) - close(rootfd); - return fd; } @@ -422,22 +399,27 @@ int pakfire_cgroup_create(struct pakfire_cgroup** cgroup, // Copy flags c->flags = flags; + // Find the parent cgroup + r = pakfire_cgroup_parent(c, &c->parent); + if (r < 0) + goto ERROR; + // Open a file descriptor - c->fd = __pakfire_cgroup_open(c); - if (c->fd < 0) { - r = 1; + c->fd = r = pakfire_cgroup_open(c); + if (r < 0) goto ERROR; - } // Enable all controllers r = pakfire_cgroup_enable_controllers(c); if (r < 0) goto ERROR; +#if 0 // Setup the devices filter r = pakfire_cgroup_setup_devices(c); if (r) goto ERROR; +#endif // Return the pointer *cgroup = pakfire_cgroup_ref(c); @@ -454,6 +436,8 @@ static void pakfire_cgroup_free(struct pakfire_cgroup* cgroup) { close(cgroup->fd); if (cgroup->devicesfd >= 0) close(cgroup->devicesfd); + if (cgroup->parent) + pakfire_cgroup_unref(cgroup->parent); if (cgroup->ctx) pakfire_ctx_unref(cgroup->ctx); free(cgroup); @@ -508,10 +492,8 @@ int pakfire_cgroup_destroy(struct pakfire_cgroup* cgroup) { int r; // Cannot call this for the root group - if (pakfire_cgroup_is_root(cgroup)) { - errno = EPERM; - return 1; - } + if (!cgroup->parent) + return -EPERM; DEBUG(cgroup->ctx, "Destroying cgroup %s\n", pakfire_cgroup_name(cgroup));