{"id":18952953,"url":"https://github.com/initware/cgrpfs","last_synced_at":"2025-04-16T02:31:39.131Z","repository":{"id":199280148,"uuid":"405734897","full_name":"InitWare/CGrpFS","owner":"InitWare","description":"Tiny implementation of the GNU/Linux CGroupFS (sans resource controllers) as a PUFFS or FUSE filesystem for BSD platforms","archived":false,"fork":false,"pushed_at":"2021-10-07T01:01:07.000Z","size":65,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-29T05:22:06.460Z","etag":null,"topics":["bsd","cgroups","compatibility","dragonflybsd","filesystem","freebsd","fuse","fuse-filesystem","linux","netbsd","openbsd","puffs"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/InitWare.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-09-12T19:29:24.000Z","updated_at":"2024-06-07T21:33:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"dd983868-cdc0-43be-9a42-25b4fb795b44","html_url":"https://github.com/InitWare/CGrpFS","commit_stats":null,"previous_names":["initware/cgrpfs"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InitWare%2FCGrpFS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InitWare%2FCGrpFS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InitWare%2FCGrpFS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InitWare%2FCGrpFS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/InitWare","download_url":"https://codeload.github.com/InitWare/CGrpFS/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249184535,"owners_count":21226395,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bsd","cgroups","compatibility","dragonflybsd","filesystem","freebsd","fuse","fuse-filesystem","linux","netbsd","openbsd","puffs"],"created_at":"2024-11-08T13:35:25.558Z","updated_at":"2025-04-16T02:31:38.904Z","avatar_url":"https://github.com/InitWare.png","language":"C","readme":"CGrpFS\n======\n\nCGrpFS is a tiny implementation of the GNU/Linux CGroup filesystem for BSD\nplatforms. It takes the form of a either a PUFFS or FUSE filesystem, and\nimplements robust tracking of processes. Resource control, however, is not\npresent; the different BSD platforms each provide different mechanisms for this,\nnone of which are trivially adapted to CGroups semantics. The process tracking\nalone is sufficient for the main user of CGrpFS,\n[InitWare](https://github.com/InitWare/InitWare), a service manager derived from\nsystemd.\n\nCGrpFS is available under the Modified BSD Licence. It is not as-yet very well\ntested, but seems to work fine for InitWare's purposes.\n\nArchitecture\n------\n\nCGrpFS was implemented quickly and is not necessarily the most efficient in\ndesign.\n\nProcess tracking is implemented with the process filter for Kernel Queues. This\nprovides CGrpFS with notifications whenever a process forks or exits to which it\nhas attached a filter. On all BSD platforms except macOS, the filter is\nautomatically applied to all the transitive subprocesses spawned by a process\nafter the filter is attached. A filter is attached as soon as a PID is added to\na CGroup, so the Linux semantics are matched.\n\nFor simplicity, all the files and directories of the CGroup filesystem are\nbacked by node structures, which are akin to a combination of an `inode` and\n`dirent` structure. These nodes are hierarchically ordered and each stores a\nname, `stat` structure, a type (CGroup directory, `cgroup.procs` file, ...) and\ntype-specific data. A CGroup directory node, for example, stores a linked list\nof all PIDs within it. It might be better to take an approach that maintains\nless data, but bear in mind that at least permissions data must be stored\nfor nodes, as the GNU/Linux CGroup filesystem allows changing permissions, e.g.\nto facilitate delegation.\n\nTo try to ensure consistency of file contents over the course of multiple reads,\neach `open` operation in the FUSE version of CGrpFS allocates a buffer into\nwhich the contents of the associated file is generated in full, and this buffer\nis used for each read with that FUSE file handle. This may not work properly in\nevery case because the SunOS VFS (as imitated by BSD) enforces a distinction\nbetween the file and vnode levels absent from GNU/Linux. The likely result of\nthis distinction is that read operations may not be mapped to the right file\nhandle during read operations. The only viable fix (which would also work for\nPUFFS) would be the generation of a fresh vnode for every open.\n\nA mini-ProcFS is also provided with only a minimal `cgroup` file present in each\nPID's directory. The nodes for directories (and the contained `cgroup` file)\nwithin that hierarchy are generated dynamically in response to getattr() events\nto eliminate the need to preallocate the entire lot, and these might feasibly be\npruned if unused for some time. Their purpose is to allow InitWare to determine\nthe containing CGroup of a PID. If a PID is inquired about which does not\ncurrently belong to any CGroup, it is automatically added to the root CGroup,\nin line with the behaviour on Linux.\n\nBecause only NetBSD's PUFFS (and its FUSE emulation, PERFUSE) support poll()\n(but not the installation of Kernel Queues filters), while FUSE for other BSDs\ndoesn't, and because the `release_agent` mechanism is fundamentally fragile,\nCGrpFS listens on a sequenced-packet socket in the Unix domain at\n`/var/run/cgrpfs.notify`. On a process exiting, a `siginfo_t` structure is\nprepared and sent as a message to every peer connected to that socket. InitWare\nuses this to help track process lifecycle.\n\nSome effort is made to be resilient to out-of-memory conditions. This is\nuntested and may not work. Whether libfuse is similarly resilient is another\nquestion. There is also the problem that under OOM conditions, it is no longer\npossible to update the structures in CGrpFS which describe which processes\nbelong to what CGroup. This might be mitigated in part by keeping some spare\nmemory around to use under OOM conditions, and hoping that the number of tracked\nprocesses doesn't grow beyond its capacity while the OOM state persists.\nFinally, the process filter itself can fail in-kernel under OOM conditions, and\nreturn NOTE_TRACKERR. There is no easy way out of this without modifying the\nkernel itself.\n\nRoom for Improvement\n--------------------\n\nThere are several ways in which CGrpFS could be improved.\n\nThe mini-ProcFS is immutable by users and stateless, only providing information\nmaintained by the actual CGroups tree; it could therefore be implemented\nwithout backing nodes to save some memory use.\n\nMuch more data than necessary is stored in each node (a full struct `stat`);\nthis can be reduced. And proper nodes for each pseudo-file in a CGroup directory\ncould be abolished too.\n\nMuch unnecessary copying goes on due to CGrpFS using the high-level libfuse\ninterface. Lowering to the fuse_lowlevel interface (or even directly to the\n`/dev/fuse` device) could help reduce that, and hence reduce the risk of OOM\nconditions causing a crash. Needless lookups also occur with the high-level\ninterface because it's based on path strings; the archictecture of CGrpFS more\nreadily fits the lower-level inode-based interface. Path lookup would also\nbecome simpler since there would be one lookup request for each component of\nthe path; currently it has ugly special-cases for e.g. `mkdir`.\n\nOOM resilience could be improved in line with the notes in the Architecture\nsection above.\n\nRelease agent support should be implemented for compatibility, though it's not\na reliable mechanism.\n\nFreeBSD provides hierarchical resource control via the `rctl` system. It's not\nclear whether this usefully maps to CGroups semantics, but it certainly is\nworth exploring whether it could be used to provide some CGroup resource\ncontrollers.\n\nCGrpFS could be implemented as an in-kernel filesystem within the various BSD\nkernels. CGrpFS could be hooked up more directly with the kernel's process\nmanagement, and benefit from the kernel's capacity to to deal with OOM\nconditions more aggressively.\n\nFurthering an in-kernel implementation of CGrpFS, hierarchical resource control\nmechanisms could be implemented in those BSDs without them.\n\nContributing poll() and kevent() supprt to each BSD's FUSE/PUFFS implementation\nwould allow the CGroups 2.0 `cgroup.events` file to be implemented.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finitware%2Fcgrpfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finitware%2Fcgrpfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finitware%2Fcgrpfs/lists"}