From: Michael Tremer Date: Mon, 9 Dec 2024 16:29:06 +0000 (+0000) Subject: cgroups: Implement recursively enabling controllers X-Git-Tag: 0.9.30~739 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d81b74edae492f732354b11507f5cd01f788a6e1;p=pakfire.git cgroups: Implement recursively enabling controllers Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/cgroup.c b/src/libpakfire/cgroup.c index 1550c93a5..8b3848981 100644 --- a/src/libpakfire/cgroup.c +++ b/src/libpakfire/cgroup.c @@ -114,34 +114,25 @@ static const char* pakfire_cgroup_name(struct pakfire_cgroup* cgroup) { return cgroup->path; } -static struct pakfire_cgroup* pakfire_cgroup_parent(struct pakfire_cgroup* cgroup) { - struct pakfire_cgroup* parent = NULL; +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)) - return NULL; + if (pakfire_cgroup_is_root(cgroup)) { + *parent = NULL; + return 0; + } // Determine the path of the parent r = pakfire_path_dirname(path, cgroup->path); - if (r) { - ERROR(cgroup->ctx, "Could not determine path for parent cgroup: %m\n"); - return NULL; + if (r < 0) { + ERROR(cgroup->ctx, "Could not determine path for parent cgroup: %s\n", strerror(-r)); + return r; } - // dirname() returns . if no directory component could be found - if (strcmp(path, ".") == 0) - *path = '\0'; - // Open the cgroup - r = pakfire_cgroup_open(&parent, cgroup->ctx, path, 0); - if (r) { - ERROR(cgroup->ctx, "Could not open parent cgroup: %m\n"); - parent = NULL; - } - - return parent; + return pakfire_cgroup_open(parent, cgroup->ctx, path, 0); } static int pakfire_cgroup_setup_devices(struct pakfire_cgroup* cgroup) { @@ -296,27 +287,29 @@ static int pakfire_cgroup_write(struct pakfire_cgroup* cgroup, static int pakfire_cgroup_write(struct pakfire_cgroup* cgroup, const char* path, const char* format, ...) { + ssize_t bytes_written = 0; va_list args; + int fd = -EBADF; int r = 0; // Check if this cgroup has been destroyed already if (cgroup->fd < 0) { ERROR(cgroup->ctx, "Trying to write to destroyed cgroup\n"); - errno = EPERM; - return 1; + return -EPERM; } // Open the file - int fd = openat(cgroup->fd, path, O_WRONLY|O_CLOEXEC); + fd = openat(cgroup->fd, path, O_WRONLY|O_CLOEXEC); if (fd < 0) { DEBUG(cgroup->ctx, "Could not open %s/%s for writing: %m\n", pakfire_cgroup_name(cgroup), path); - return -errno; + r = -errno; + goto ERROR; } // Write buffer va_start(args, format); - ssize_t bytes_written = vdprintf(fd, format, args); + bytes_written = vdprintf(fd, format, args); va_end(args); // Check if content was written okay @@ -324,10 +317,12 @@ static int pakfire_cgroup_write(struct pakfire_cgroup* cgroup, DEBUG(cgroup->ctx, "Could not write to %s/%s: %m\n", pakfire_cgroup_name(cgroup), path); r = -errno; + goto ERROR; } - // Close fd - close(fd); +ERROR: + if (fd > 0) + close(fd); return r; } @@ -336,12 +331,37 @@ static int pakfire_cgroup_write(struct pakfire_cgroup* cgroup, Enables a cgroup controller. */ static int pakfire_cgroup_enable_controller(struct pakfire_cgroup* cgroup, const char* name) { + struct pakfire_cgroup* parent = NULL; int r; // Try to enable the controller r = pakfire_cgroup_write(cgroup, "cgroup.subtree_control", "+%s", name); - if (r < 0) - ERROR(cgroup->ctx, "Could not enable controller '%s': %s\n", name, strerror(-r)); + if (r < 0) { + switch (-r) { + case ENOENT: + // Fetch the parent group + r = pakfire_cgroup_parent(cgroup, &parent); + if (r < 0) + return r; + + // When we have reached root, we cannot continue + if (!parent) + return -ENOTSUP; + + // Ensure it is enabled there + r = pakfire_cgroup_enable_controller(parent, name); + if (r < 0) + return 0; + + // Once that was successful, try again + return pakfire_cgroup_enable_controller(cgroup, name); + + default: + ERROR(cgroup->ctx, "Could not enable controller '%s': %s\n", + name, strerror(-r)); + break; + } + } return r; }