struct pakfire_ctx* ctx;
int nrefs;
+ // The parent group
+ struct pakfire_cgroup* parent;
+
// Store the root path
char root[PATH_MAX];
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;
}
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);
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.
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;
}
// 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);
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);
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));