Files
cgroup2-unraid/cgroup2-unraid.c
Christoph Hummer 1b237cb8a8 Bugfix for directories
Fixed handling of cgroup directories with various names by ensuring correct generation of the `cgroup.events` file path
2024-09-14 10:21:03 +02:00

126 lines
2.9 KiB
C

#include <sys/inotify.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#define BUFFER_LEN (1024 * (sizeof(struct inotify_event) + 16))
void handle_cgroup_event(const char *event_file) {
char buffer[256];
int fd = open(event_file, O_RDONLY);
if(fd < 0) {
return;
}
ssize_t bytesRead = read(fd, buffer, sizeof(buffer) - 1);
close(fd);
if(bytesRead < 0) {
return;
}
buffer[bytesRead] = '\0';
if(strstr(buffer, "populated 0")) {
char dir[1024];
strcpy(dir, event_file);
*strrchr(dir, '/') = '\0';
rmdir(dir);
}
}
void scan_and_clean_cgroup_directory(const char *dir) {
DIR *d = opendir(dir);
if (!d) {
return;
}
struct dirent *entry;
while ((entry = readdir(d)) != NULL) {
if (entry->d_type == DT_DIR) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char subdir[1024];
snprintf(subdir, sizeof(subdir), "%s/%s/cgroup.events", dir, entry->d_name);
handle_cgroup_event(subdir);
}
}
closedir(d);
}
void monitor_directory(const char *dir) {
int inotify_fd = inotify_init();
if(inotify_fd < 0) {
exit(EXIT_FAILURE);
}
int wd = inotify_add_watch(inotify_fd, dir, IN_CREATE);
if(wd < 0) {
close(inotify_fd);
exit(EXIT_FAILURE);
}
char buffer[BUFFER_LEN];
while(1) {
ssize_t length = read(inotify_fd, buffer, BUFFER_LEN);
if(length < 0) {
close(inotify_fd);
exit(EXIT_FAILURE);
}
char *ptr;
for(ptr = buffer; ptr < buffer + length; ptr += sizeof(struct inotify_event) + ((struct inotify_event *)ptr)->len) {
struct inotify_event *event = (struct inotify_event *)ptr;
if(event->mask & IN_CREATE && event->mask & IN_ISDIR) {
char cgroup_event_path[1024];
snprintf(cgroup_event_path, sizeof(cgroup_event_path), "%s/%s/cgroup.events", dir, event->name);
sleep(1);
int cgroup_event_wd = inotify_add_watch(inotify_fd, cgroup_event_path, IN_MODIFY);
if(cgroup_event_wd >= 0) {
handle_cgroup_event(cgroup_event_path);
}
} else if(event->mask & IN_MODIFY) {
char cgroup_event_path[1024];
snprintf(cgroup_event_path, sizeof(cgroup_event_path), "%s/%s/cgroup.events", dir, event->name);
handle_cgroup_event(cgroup_event_path);
}
}
}
close(inotify_fd);
}
int main(int argc, char *argv[]) {
const char *cgroup_dir = "/sys/fs/cgroup";
int run_as_daemon = (argc > 1 && strcmp(argv[1], "--daemon") == 0);
scan_and_clean_cgroup_directory(cgroup_dir);
if(run_as_daemon) {
if(fork() > 0) exit(EXIT_SUCCESS);
if(setsid() < 0) exit(EXIT_FAILURE);
if(fork() > 0) exit(EXIT_SUCCESS);
chdir("/");
for(int x = sysconf(_SC_OPEN_MAX); x >= 0; x--) {
close(x);
}
open("/dev/null", O_RDWR);
dup(0);
dup(0);
monitor_directory(cgroup_dir);
}
return 0;
}