]> git.ipfire.org Git - pakfire.git/commitdiff
cgroups: Implement recursively enabling controllers
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 9 Dec 2024 16:29:06 +0000 (16:29 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 9 Dec 2024 16:29:06 +0000 (16:29 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/cgroup.c

index 1550c93a585e1c04ffde5a2fc1e1f286a55c5eac..8b384898199bb0c39e98cefc66e7cea1a79fcfcb 100644 (file)
@@ -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;
 }