From: Demi Marie Obenour <demiobenour@gmail.com>
To: Alyssa Ross <hi@alyssa.is>
Cc: Spectrum OS Development <devel@spectrum-os.org>
Subject: Re: [PATCH v7 02/19] tools: Add control group manager
Date: Sat, 29 Aug 2026 22:54:10 -0400 [thread overview]
Message-ID: <de99b14c-a587-47f7-819d-f9578f788f10@gmail.com> (raw)
In-Reply-To: <87y0dt7z7e.fsf@alyssa.is>
[-- Attachment #1.1: Type: text/plain, Size: 24062 bytes --]
On 8/26/26 10:07, Alyssa Ross wrote:
> Demi Marie Obenour <demiobenour@gmail.com> writes:
>
>> This program has two modes:
>>
>> 1. Create a control group if it doesn't exist, optionally wait for other
>> programs in it to exit, and exec another program in it.
>>
>> 2. Purge a control group: kill all programs in it, then delete it.
>>
>> Locking is used to ensure that concurrent invocations are safe.
>>
>> Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
>
> The structure of the program is looking really good now. All remaining
> comments are minor, except for making sure we're doing the right thing
> with enabling controllers. Pay attention to naming — good names are
> really important for making it clear to readers what a program does.
That it is!
>> diff --git a/tools/cgroup-setup/src/cgroup.rs b/tools/cgroup-setup/src/cgroup.rs
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..463d3fc87ee34ccfbf399a337e2f49d9031728ee
>> --- /dev/null
>> +++ b/tools/cgroup-setup/src/cgroup.rs
>> @@ -0,0 +1,289 @@
>> +// SPDX-FileCopyrightText: 2026 Demi Marie Obenour <demiobenour@gmail.com>
>> +// SPDX-License-Identifier: EUPL-1.2+
>> +
>> +use std::ffi::OsStr;
>> +use std::fs::File;
>> +use std::io::{Read as _, Seek as _, Write as _};
>> +use std::os::unix::prelude::*;
>> +
>> +use std::path::{Component, Path, PathBuf};
>> +
>> +use rustix::fs::{AtFlags, CWD, Dir, FlockOperation};
>> +use rustix::path;
>> +use rustix::{
>> + fs::{Mode, OFlags, ResolveFlags},
>> + io::Errno,
>> +};
>> +
>> +pub enum OpenFlags {
>> + Read,
>> + Write,
>> + Directory,
>> +}
>> +
>> +#[derive(Debug)]
>> +pub(crate) struct Cgroup {
>> + fd: Vec<OwnedFd>,
>> +}
>> +
>> +impl AsFd for Cgroup {
>> + fn as_fd(&self) -> BorrowedFd<'_> {
>> + self.fd.last().unwrap().as_fd()
>> + }
>> +}
>> +
>> +fn assert_single_component(component: &Path) {
>> + match component.as_os_str().as_bytes() {
>> + b"" | b"." | b".." => panic!("bad component"),
>> + c if c.contains(&b'\0') => panic!("NUL in component"),
>> + c if c.contains(&b'/') => panic!("/ in component"),
>> + _ => {}
>> + }
>> +}
>> +
>> +// Wrapper around openat2() with better defaults.
>> +pub fn openat2_simple(
>> + fd: impl AsFd,
>> + path: impl path::Arg,
>> + flags: OpenFlags,
>> +) -> Result<OwnedFd, Errno> {
>> + rustix::fs::openat2(
>> + fd.as_fd(),
>> + path,
>> + OFlags::CLOEXEC
>> + | match flags {
>> + OpenFlags::Read => OFlags::RDONLY | OFlags::NOCTTY,
>> + OpenFlags::Write => OFlags::WRONLY | OFlags::NOCTTY,
>> + OpenFlags::Directory => OFlags::RDONLY | OFlags::DIRECTORY,
>> + },
>> + Mode::empty(),
>> + ResolveFlags::NO_SYMLINKS | ResolveFlags::NO_MAGICLINKS | ResolveFlags::NO_XDEV,
>> + )
>> +}
>> +
>> +pub const DEFAULT_LEAF: &str = "$inner.service";
>> +
>> +pub fn check_path(path: &Path) -> Result<(), String> {
>> + let bytes = path.as_os_str().as_bytes();
>> + // Path::components() skips ., so use string manipulation instead.
>> + for component in bytes[path.is_absolute() as usize..].split(|&b| b == b'/') {
>> + if matches!(component, b"" | b"." | b"..") {
>> + return Err(format!("cgroup path {path:?} isn't canonical"));
>> + }
>> + }
>> + Ok(())
>> +}
>> +
>> +// Remove all subdirectories of the given directory recursively, but not the
>> +// directory itself. The directory file descriptor is closed.
>
> [nit] That's clear from the type signature, so probably doesn't need to
> be explicitly documented.
Will delete.
>> +//
>> +// This isn't the most efficient possible algorithm, but simplicity is more
>> +// important than performance in this case. Also, it keeps open more file
>> +// descriptors than strictly necessary, but Spectrum runs with a very high limit
>> +// for the number of open file descriptors, and it uses shallow control group
>> +// hierarchies.
>> +//
>> +// This uses a recursive algorithm, but so does std::fs::remove_dir_all(). Trying
>> +// to be more robust than the standard library is not worthwhile. In particular,
>> +// the standard library function must be safe on systems where untrusted users (or
>> +// even network endpoints!) can create deeply nested directory trees, whereas in
>> +// Spectrum cgroups are only writeable by root.
>> +fn remove_recursively(mut dirfd: Dir, remaining_depth: usize) -> Result<(), Errno> {
>> + if remaining_depth < 1 {
>> + panic!("control groups too deeply nested");
>> + }
>> + while let Some(element) = dirfd.next() {
>
> "element" is a bit of an odd name for a directory entry, no?
I will rename this to "entry".
>> + let parent_fd = dirfd.fd().unwrap();
>
> Could be lifted out of the loop, right?
That doesn't compile: dirfd.fd() takes an immutable borrow, while
dirfd.next() takes a mutable one.
>> + let element = element.expect("Iterating through a cgroup directory failed?");
>> + let path = element.file_name();
>
> "name" would probably be clearer than "path", since we know it's a
> single component (and it's consistent with the file_name method).
Will fix.
>> + if element.file_type() != rustix::fs::FileType::Directory || path == c"." || path == c".." {
>> + continue;
>> + }
>> + let fd = openat2_simple(parent_fd, path, OpenFlags::Directory)?;
>> + remove_recursively(Dir::new(fd).unwrap(), remaining_depth - 1)?;
>> + rustix::fs::unlinkat(parent_fd, path, AtFlags::REMOVEDIR)?;
>> + }
>> + Ok(())
>> +}
>> +
>> +fn assert_simple_path(current_cgroup: &Path) {
>> + let current_cgroup = current_cgroup.as_os_str().as_bytes();
>> + if !matches!(current_cgroup, b"" | b".") {
>> + for component in current_cgroup.split(|&b| b == b'/') {
>> + assert_single_component(Path::new(OsStr::from_bytes(component)));
>> + }
>> + }
>> +}
>
> Very non-obvious what this does — of course you'll get a lot of "single
> component"s if you split a path on /. What you actually want to do is
> just check for no null bytes or .. components, right? Given
> assert_single_component is doing a more specific check than just single
> components, it should be renamed accordingly. (Although I'd struggle to
> think of a name, because I still find what it's checking, and where we
> check it, to be a bit arbitrary, especially when it's a path that's come
> from the kernel…)
It's checking that a path component is “simple”, meaning no NUL
or / and not “.” or “..”. Those are the criteria for “the
path is valid and its lookup does not cross any directories”.
> With check_path as well we have a confusing collection of subtly
> different, inconsistently named path checking functions. These should
> be unified if possible, named systematically if not, and in either case
> it should be clear from the name what the function is for.
I will inline check_path into its single caller, and delete the
assert_* functions.
>> +// Convert the cgroup path to one relative to /sys/fs/cgroup.
>> +//
>> +// If the path starts with /, the leading / is removed and the result is returned
>> +// without further processing. Otherwise, the current cgroup is read from
>> +// /proc/thread-self/cgroup. If its last component is $inner.service, that is
>> +// removed. Finally, the current cgroup is prepended to the provided cgroup path,
>> +// with a single / as separator. The result of this operation is returned.
>> +fn prepend_current_cgroup_if_needed(path: &Path) -> Result<PathBuf, String> {
>> + if let Ok(suffix) = path.strip_prefix("/") {
>> + return Ok(suffix.to_owned());
>> + }
>> + assert_simple_path(path);
>> + // /proc/thread-self is the same as /proc/self, except for the current thread
>> + // instead of the initial thread. In this case, the two are identical, but
>> + // using /proc/thread-self is better practice as it is correct in more cases.
>> + // Reading /proc/thread-self/cgroup should never fail unless the system is
>> + // seriously broken.
>> + let current_cgroup =
>> + std::fs::read("/proc/thread-self/cgroup").expect("cannot read /proc/thread-self/cgroup");
>> + // Using this on a system without cgroups v2 mounted is user error
>> + // and not supported.
>> + let current_cgroup = current_cgroup
>> + .strip_prefix(b"0::/")
>> + .and_then(|e| e.strip_suffix(b"\n"))
>> + .ok_or_else(|| {
>> + "/proc/thread-self/cgroup doesn't start with 0::/ or doesn't end with a newline.\n\
>> + Either cgroups aren't in use at all, or you are using cgroups v1."
>> + .to_owned()
>> + })?;
>> + let mut current_cgroup = PathBuf::from(OsStr::from_bytes(current_cgroup));
>> + assert_simple_path(¤t_cgroup);
>> + // Strip the implied $inner.service suffix.
>> + // This is used to satisfy the "no internal processes" rule.
>> + if current_cgroup.ends_with(Path::new(DEFAULT_LEAF)) {
>> + assert!(current_cgroup.pop());
>> + }
>> + // "." refers to the current cgroup.
>> + if path != Path::new(".") {
>> + current_cgroup.push(path);
>> + }
>> + Ok(current_cgroup)
>> +}
>> +
>> +pub(crate) fn write_value(fd: &dyn AsFd, name: &Path, value: &[u8]) -> Result<(), String> {
>> + let fd = openat2_simple(fd, name, OpenFlags::Write)
>> + .map_err(|e| format!("Cannot open {name:?}: {e}"))?;
>> + File::from(fd).write_all(value).map_err(|e| {
>> + format!(
>> + "Cannot write {:?} to {name:?}: {e}",
>> + OsStr::from_bytes(value)
>> + )
>> + })
>> +}
>> +
>> +impl Cgroup {
>> + pub fn new(path: &Path) -> Result<Self, String> {
>> + let cgroup_root = rustix::fs::openat2(
>> + CWD,
>> + Path::new("/sys/fs/cgroup"),
>> + OFlags::CLOEXEC | OFlags::DIRECTORY | OFlags::RDONLY,
>> + Mode::empty(),
>> + ResolveFlags::NO_SYMLINKS | ResolveFlags::NO_MAGICLINKS,
>> + )
>> + .map_err(|e| format!("Cannot open /sys/fs/cgroup: {e}"))?;
>> + // It's simpler to always have the root cgroup at the bottom of the stack,
>> + // even though no lock needs to be taken on it. Otherwise, one would need
>> + // to special-case the cgroup root. One could remove the first element if
>> + // there is more than one element in the vector, but that's not worth it.
>> + // cgroup-setup doesn't operate in an environment where FDs are a limited
>> + // resource.
>> + let mut cgroup = Self {
>> + fd: vec![cgroup_root],
>> + };
>> +
>> + let path = prepend_current_cgroup_if_needed(path)?;
>> + for component in path.components() {
>> + let Component::Normal(component) = component else {
>> + unreachable!()
>> + };
>> + let sub_fd = openat2_simple(&cgroup, component, OpenFlags::Directory)
>> + .map_err(|e| format!("Cannot open sub-cgroup {component:?}: {e}"))?;
>> + // Take a shared lock on the cgroup.
>> + rustix::fs::flock(&sub_fd, FlockOperation::LockShared)
>> + .map_err(|e| format!("Cannot lock sub-cgroup {component:?}: {e}"))?;
>> + cgroup.fd.push(sub_fd);
>> + }
>> + Ok(cgroup)
>> + }
>> +
>> + pub fn wait_for_empty(fd: &dyn AsFd) -> std::io::Result<()> {
>> + let wait_file = openat2_simple(fd, c"cgroup.events", OpenFlags::Read)?;
>> + let mut wait_fd = File::from(wait_file);
>> + let mut v = vec![];
>> + loop {
>> + v.clear();
>> + wait_fd
>> + .seek(std::io::SeekFrom::Start(0))
>> + .expect("Seek on control group file should succeed");
>> + wait_fd
>> + .read_to_end(&mut v)
>> + .expect("reading from control group should work");
>> + // Check that the cgroup isn't already empty. If it was,
>> + // the kernel would not send an event and poll() would wait
>> + // forever.
>> + if v.split(|&c| c == b'\n').any(|line| line == b"populated 0") {
>> + break;
>> + }
>> + let mut fds = libc::pollfd {
>> + fd: wait_fd.as_raw_fd(),
>> + events: libc::POLLPRI | libc::POLLERR,
>> + revents: 0,
>> + };
>> + // SAFETY: FFI call, valid arguments, fds contains 1 element
>> + if unsafe { libc::poll(&raw mut fds, 1, -1) } != 1 {
>> + panic!("poll failed");
>> + }
>> + }
>> + Ok(())
>> + }
>> +
>> + pub fn purge_child(&mut self, path: &Path) -> Result<(), String> {
>> + assert_single_component(path);
>> + // See if we can just delete the child directly.
>> + match rustix::fs::unlinkat(&self, path, AtFlags::REMOVEDIR) {
>> + // If the cgroup was successfully deleted, or if it
>> + // has already been deleted, we are done.
>> + Ok(()) | Err(Errno::NOENT) => return Ok(()),
>> + // If this cgroup is in use, keep going.
>> + Err(Errno::BUSY) => {}
>> + Err(e) => return Err(format!("Cannot purge {path:?}: {e}")),
>> + }
>> +
>> + let sub_fd = match openat2_simple(&self, path, OpenFlags::Directory) {
>> + Ok(sub_fd) => sub_fd,
>> + Err(Errno::NOENT) => return Ok(()),
>> + Err(e) => {
>> + return Err(format!("Cannot open sub-cgroup {path:?}: {e}",));
>> + }
>> + };
>> +
>> + // Take an exclusive lock on the cgroup that is about to be removed. This
>> + // avoids concurrent executions of this program operating on deleted
>> + // sub-cgroups. Dir::new() doesn't expose a reference to its internal FD
>> + // so it must be delayed until later.
>
> Yes it does? It's Dir::fd. You used it elsewhere already. It's fine
> to delay Dir::new but this comment is not correct.
Will delete. I think I missed this because my IDE didn't include in
its completions.
>> + rustix::fs::flock(&sub_fd, FlockOperation::LockExclusive)
>> + .map_err(|e| format!("Cannot lock sub-cgroup: {e}"))?;
>> +
>> + // Kill all processes in the child cgroup.
>> + write_value(&sub_fd, Path::new("cgroup.kill"), b"1")?;
>> +
>> + // Wait for the child cgroup to become empty.
>> + Self::wait_for_empty(&sub_fd)
>> + .map_err(|e| format!("Cannot wait for cgroup to become empty: {e}"))
>> + .inspect_err(|_| {
>> + self.fd.pop().unwrap();
>
> Why do we need to do this? What's the matching push? Why should
> failing to wait for a child cgroup to be empty mean we unlock its
> parent?
We definitely do not need to do it. It's stale code from when this
function did a lot of pushes and pops.
>> + })?;
>> +
>> + // Remove the child cgroup and its contents recursively.
>> + remove_recursively(Dir::new(sub_fd).unwrap(), 1000)
>> + .map_err(|e| format!("Cannot remove: {e}"))?;
>> +
>> + // Delete the cgroup. If it's been re-created in the meantime and is
>> + // currently in use, this is not an error. Another process deleting the
>> + // cgroup is also not an error. Both of these can happen because of the
>> + // time period between remove_child_directories() closing the file
>> + // descriptor (releasing its lock) and the above call to flock().
>> + match rustix::fs::unlinkat(&self, path, AtFlags::REMOVEDIR) {
>> + Ok(()) | Err(Errno::BUSY) | Err(Errno::NOENT) => Ok(()),
>> + Err(e) => Err(format!("Cannot delete: {e}")),
>> + }
>> + }
>> +}
>> diff --git a/tools/cgroup-setup/src/main.rs b/tools/cgroup-setup/src/main.rs
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..c757a4ad37c812ef5ce5249dc1bc3104ec246eef
>> --- /dev/null
>> +++ b/tools/cgroup-setup/src/main.rs
>> @@ -0,0 +1,168 @@
>> +// SPDX-FileCopyrightText: 2026 Demi Marie Obenour <demiobenour@gmail.com>
>> +// SPDX-License-Identifier: EUPL-1.2+
>> +
>> +mod cgroup;
>> +
>> +use cgroup::{Cgroup, OpenFlags, openat2_simple, write_value};
>> +use rustix::{
>> + fs::{FlockOperation, Mode, XattrFlags},
>> + io::Errno,
>> +};
>> +use std::{
>> + env::ArgsOs,
>> + fs::File,
>> + io::Read as _,
>> + os::unix::prelude::*,
>> + path::{Path, PathBuf},
>> +};
>> +
>> +fn enable_subtree_control(fd: &dyn AsFd) -> Result<(), String> {
>> + rustix::fs::fsetxattr(fd, c"user.delegate", b"1", XattrFlags::empty())
>> + .map_err(|e| format!("Cannot enable cgroup delegation: {e}"))?;
>> + let mut buf = Vec::new();
>> + File::from(
>> + openat2_simple(fd, c"cgroup.controllers", OpenFlags::Read)
>> + .map_err(|e| format!("Cannot open cgroup.controllers: {e}"))?,
>> + )
>> + .read_to_end(&mut buf)
>> + .map_err(|e| format!("Cannot read cgroup.controllers: {e}"))?;
>> + let mut subtree = vec![];
>> + if buf.is_empty() {
>> + return Ok(());
>> + }
>> + for controller in buf.split(|&b| b == b' ') {
>> + if !subtree.is_empty() {
>> + subtree.push(b' ');
>> + }
>> + subtree.push(b'+');
>> + subtree.extend_from_slice(controller);
>> + }
>> + if !subtree.is_empty() {
>> + write_value(&fd, Path::new("cgroup.subtree_control"), &subtree)?;
>> + }
>> + Ok(())
>> +}
>
> My memory of our conversation on a call last week is that we found it
> undesirable to enable every controller, since that causes behaviour
> surprising action-at-a-distance behaviour changes. Rather specific
> requested controllers should be enabled when necessary, right?
Yup! I'll move this to the next patch series that enables limits.
>> +
>> +fn spawn_in_cgroup(
>> + mut args: std::iter::Peekable<ArgsOs>,
>> + cgroup: Option<&dyn AsFd>,
>> +) -> Result<(), String> {
>
> We're not spawning anything if all we're doing is an exec. It should be
> called exec_in_cgroup.
Will fix.
>> + let Some(program_name) = args.next() else {
>> + return Ok(());
>> + };
>> + if let Some(cgroup) = cgroup {
>> + let pid = std::process::id().to_string();
>> + write_value(
>> + cgroup,
>> + Path::new("$inner.service/cgroup.procs"),
>> + pid.as_bytes(),
>> + )
>> + .map_err(|e| format!("Cannot move process to child cgroup: {e}"))?;
>> + }
>> + let e = std::process::Command::new(&program_name).args(args).exec();
>> + Err(format!("Cannot spawn child {program_name:?}: {e}"))
>
> Cannot *exec*.
Will fix.
>> +}
>> +
>> +// Check that the path is canonical,
>> +// then split it into basename and filename.
>> +fn split_path(path: &Path) -> Result<(&Path, &Path), String> {
>> + cgroup::check_path(path)?;
>> + Ok((path.parent().unwrap(), Path::new(path.file_name().unwrap())))
>> +}
>> +
>> +fn cgroup_setup(args: ArgsOs) -> Result<(), String> {
>> + let mut wait = true;
>> + let mut args = args.peekable();
>> + while let Some(arg) = args.peek() {
>> + if !arg.as_bytes().starts_with(b"-") {
>> + break;
>> + }
>> + let arg = args.next().unwrap();
>
> I'd find let _ = args.next() slightly clearer, because then it's clear
> we're not interested in the value, since we already have it.
That fails to compile (args mutably borrowed more than once).
>> + let Some(option) = arg.as_bytes().strip_prefix(b"--") else {
>> + return Err("takes no short options".to_owned());
>> + };
>> + match option {
>> + b"" => break,
>> + b"no-wait" => wait = false,
>> + _ => return Err(format!("unknown long option {arg:?}")),
>> + }
>> + }
>> + let Some(cgroup_path) = args.next().map(PathBuf::from) else {
>> + return Err("have no positional arguments, expected at least 1".to_owned());
>> + };
>> +
>> + let (parent_cgroup_path, child_cgroup_path) = split_path(&cgroup_path)?;
>> + let cgroup = Cgroup::new(parent_cgroup_path)?;
>> + match rustix::fs::mkdirat(&cgroup, child_cgroup_path, Mode::from_raw_mode(0o755)) {
>> + Ok(()) | Err(Errno::EXIST) => {}
>> + Err(e) => {
>> + return Err(format!(
>> + "Cannot create child cgroup {child_cgroup_path:?}: {e}"
>> + ));
>> + }
>> + }
>> +
>> + let child = openat2_simple(&cgroup, child_cgroup_path, OpenFlags::Directory)
>> + .map_err(|e| format!("Cannot open child cgroup: {e}"))?;
>> +
>> + // While waiting, hold an exclusive lock on the child.
>> + // This avoids two processes both waiting for the same cgroup to become
>> + // empty, then spawning processes in the same cgroup.
>> + rustix::fs::flock(&child, FlockOperation::LockExclusive)
>> + .map_err(|e| format!("Cannot take an exclusive lock on child cgroup: {e}"))?;
>> + if wait {
>> + Cgroup::wait_for_empty(&child)
>> + .map_err(|e| format!("Cannot wait for {parent_cgroup_path:?} to be empty: {e}"))?;
>> + }
>> +
>> + // Spectrum's programs (such as this one) expect cgroup.subtree_control
>> + // to be set by the program that created the cgroup. systemd-aware
>> + // programs, like systemd-udevd, expect user.delegate=1 to be set.
>> + enable_subtree_control(&child)?;
>> +
>> + // If the child process will need to manage cgroups itself, it will need
>> + // to set up a sub-cgroup due to the "no internal processes" rule. It's
>> + // simplest to just do it automatically. If the cgroup already exists,
>> + // that isn't an error.
>> + match rustix::fs::mkdirat(&child, cgroup::DEFAULT_LEAF, Mode::from_raw_mode(0o755)) {
>> + Ok(()) | Err(Errno::EXIST) => {}
>> + Err(e) => return Err(format!("Cannot create $inner.service cgroup: {e}")),
>> + }
>> +
>> + spawn_in_cgroup(args, Some(&child))
>> +}
>> +
>> +fn cgroup_purge(mut args: ArgsOs) -> Result<(), String> {
>> + if args.len() != 1 {
>> + return Err("usage: cgroup-purge CGROUP_TO_PURGE".to_owned());
>> + }
>> + let arg = args.next().unwrap();
>> + let (parent, child) = split_path(Path::new(&arg))?;
>> + Cgroup::new(parent)?.purge_child(child)
>> +}
>> +
>> +fn run(prog_name: &Path, args: ArgsOs) -> Result<(), String> {
>> + match prog_name.file_name().map(|f| f.as_bytes()) {
>> + Some(b"cgroup-setup") => cgroup_setup(args),
>> + Some(b"cgroup-purge") => cgroup_purge(args),
>> + _ => Err(format!(
>> + "must be invoked as \"cgroup-setup\" or \
>> + \"cgroup-purge\", got {prog_name:?}",
>> + )),
>> + }
>> +}
>> +
>> +fn main() {
>> + let mut args = std::env::args_os();
>> + let Some(prog_name) = args.next() else {
>> + eprintln!("No command line arguments (argv[0] is NULL)");
>> + std::process::exit(1);
>> + };
>> + match run(Path::new(&prog_name), args) {
>> + Ok(()) => {}
>> + Err(e) => {
>> + eprintln!("{prog_name:?}: {}", e);
>> + std::process::exit(1);
>> + }
>> + }
>> +}
--
Sincerely,
Demi Marie Obenour (she/her/hers)
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2026-08-30 2:54 UTC|newest]
Thread overview: 173+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-20 14:23 [PATCH] Set up control groups for most services Demi Marie Obenour
2026-06-20 17:27 ` [PATCH v2] " Demi Marie Obenour
2026-06-24 12:13 ` Alyssa Ross
2026-06-24 12:36 ` Alyssa Ross
2026-06-25 2:03 ` Demi Marie Obenour
2026-06-25 3:03 ` Demi Marie Obenour
2026-06-25 9:55 ` Alyssa Ross
2026-06-25 9:49 ` Alyssa Ross
2026-07-11 20:12 ` [PATCH v3 00/22] Control group support Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 01/22] host/rootfs: Mount filesystems before s6-rc-init Demi Marie Obenour
2026-07-13 9:39 ` Alyssa Ross
2026-07-13 17:27 ` Demi Marie Obenour
2026-07-15 18:28 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 00/20] Control group support Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 01/20] host/rootfs: Mount filesystems before s6-rc-init Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 02/20] tools: Add control group manager Demi Marie Obenour
2026-07-22 16:01 ` Alyssa Ross
2026-07-23 23:07 ` Demi Marie Obenour
2026-07-27 12:10 ` Alyssa Ross
2026-07-30 0:40 ` Demi Marie Obenour
2026-07-30 14:53 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 03/20] Documentation: Mention control groups Demi Marie Obenour
2026-07-27 11:22 ` Alyssa Ross
2026-07-28 10:41 ` Valentin Gagarin
2026-07-22 1:59 ` [PATCH v4 04/20] Mount cgroup2 filesystem at /sys/fs/cgroup Demi Marie Obenour
2026-07-27 11:23 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 05/20] host/rootfs: Add helper program for per-VM services Demi Marie Obenour
2026-07-27 11:27 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 06/20] host/rootfs: Enable controllers in sub-cgroups Demi Marie Obenour
2026-07-27 12:11 ` Alyssa Ross
2026-07-28 2:19 ` Demi Marie Obenour
2026-07-29 14:13 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 07/20] host/rootfs: Add comments where cgroups are intentionally not used Demi Marie Obenour
2026-07-27 12:12 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 08/20] host/rootfs: serial-getty-generator: Use cgroups Demi Marie Obenour
2026-07-27 12:14 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 09/20] host/rootfs: Set up parent cgroup for all per-VM services Demi Marie Obenour
2026-07-27 12:16 ` Alyssa Ross
2026-07-28 3:01 ` Demi Marie Obenour
2026-07-29 14:29 ` Alyssa Ross
2026-07-29 20:20 ` Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 10/20] host/rootfs: Create per-VM cgroup for all of the VM's services Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 11/20] host/rootfs: run-vmm: Create per-VM cgroup Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 12/20] host/rootfs: run-appimage: Purge the " Demi Marie Obenour
2026-07-27 12:18 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 13/20] host/rootfs: run-flatpak: " Demi Marie Obenour
2026-07-27 12:19 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 14/20] host/rootfs: dbus: Run in cgroup Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 15/20] host/rootfs: vhost-user-fs: " Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 16/20] host/rootfs: vhost-user-gpu: " Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 17/20] host/rootfs: xdg-desktop-portal-spectrum-host: " Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 18/20] host/rootfs: systemd-udevd: " Demi Marie Obenour
2026-07-27 12:20 ` Alyssa Ross
2026-07-28 3:11 ` Demi Marie Obenour
2026-07-29 14:15 ` Alyssa Ross
2026-07-29 20:39 ` Demi Marie Obenour
2026-07-30 14:55 ` Alyssa Ross
2026-07-22 1:59 ` [PATCH v4 19/20] host/rootfs: weston: " Demi Marie Obenour
2026-07-27 12:23 ` Alyssa Ross
2026-07-28 3:14 ` Demi Marie Obenour
2026-07-22 1:59 ` [PATCH v4 20/20] host/rootfs: spectrum-router: " Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 00/19] Control group support Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 01/19] host/rootfs: Mount filesystems before s6-rc-init Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 02/19] tools: Add control group manager Demi Marie Obenour
2026-08-03 12:47 ` Alyssa Ross
2026-08-05 1:36 ` Demi Marie Obenour
2026-08-05 16:39 ` Alyssa Ross
2026-07-31 21:54 ` [PATCH v5 03/19] Documentation: Mention control groups Demi Marie Obenour
2026-08-03 13:22 ` Alyssa Ross
2026-07-31 21:54 ` [PATCH v5 04/19] Mount cgroup2 filesystem at /sys/fs/cgroup Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 05/19] host/rootfs: Enable controllers in non-root cgroups Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 06/19] host/rootfs: Add comments where cgroups are intentionally not used Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 07/19] host/rootfs: serial-getty-generator: Use cgroups Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 08/19] host/rootfs: systemd-udevd: Run in cgroup Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 09/19] host/rootfs: weston: " Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 10/19] host/rootfs: Set up parent cgroup for all per-VM services Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 11/19] host/rootfs: Create per-VM cgroup for all of the VM's services Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 12/19] host/rootfs: run-vmm: Create per-VM cgroup Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 13/19] host/rootfs: run-appimage: Purge the " Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 14/19] host/rootfs: run-flatpak: " Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 15/19] host/rootfs: dbus: Run in cgroup Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 16/19] host/rootfs: vhost-user-fs: " Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 17/19] host/rootfs: vhost-user-gpu: " Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 18/19] host/rootfs: xdg-desktop-portal-spectrum-host: " Demi Marie Obenour
2026-07-31 21:54 ` [PATCH v5 19/19] host/rootfs: spectrum-router: " Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 00/19] Control group support Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 01/19] host/rootfs: Mount filesystems before s6-rc-init Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 02/19] tools: Add control group manager Demi Marie Obenour
2026-08-06 6:58 ` Demi Marie Obenour
2026-08-12 21:10 ` Alyssa Ross
2026-08-06 1:16 ` [PATCH v6 03/19] Documentation: Mention control groups Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 04/19] Mount cgroup2 filesystem at /sys/fs/cgroup Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 05/19] host/rootfs: Enable controllers in non-root cgroups Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 06/19] host/rootfs: Add comments where cgroups are intentionally not used Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 07/19] host/rootfs: serial-getty-generator: Use cgroups Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 08/19] host/rootfs: systemd-udevd: Run in cgroup Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 09/19] host/rootfs: weston: " Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 10/19] host/rootfs: Set up parent cgroup for all per-VM services Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 11/19] host/rootfs: Create per-VM cgroup for all of the VM's services Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 12/19] host/rootfs: run-vmm: Create per-VM cgroup Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 13/19] host/rootfs: run-appimage: Purge the " Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 14/19] host/rootfs: run-flatpak: " Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 15/19] host/rootfs: dbus: Run in cgroup Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 16/19] host/rootfs: vhost-user-fs: " Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 17/19] host/rootfs: vhost-user-gpu: " Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 18/19] host/rootfs: xdg-desktop-portal-spectrum-host: " Demi Marie Obenour
2026-08-06 1:16 ` [PATCH v6 19/19] host/rootfs: spectrum-router: " Demi Marie Obenour
2026-08-12 21:06 ` [PATCH v6 00/19] Control group support Alyssa Ross
2026-08-21 6:51 ` [PATCH v7 " Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 01/19] host/rootfs: Mount filesystems before s6-rc-init Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 02/19] tools: Add control group manager Demi Marie Obenour
2026-08-26 14:07 ` Alyssa Ross
2026-08-30 2:54 ` Demi Marie Obenour [this message]
2026-08-21 6:51 ` [PATCH v7 03/19] Documentation: Mention control groups Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 04/19] Mount cgroup2 filesystem at /sys/fs/cgroup Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 05/19] host/rootfs: Enable controllers in non-root cgroups Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 06/19] host/rootfs: Add comments where cgroups are intentionally not used Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 07/19] host/rootfs: serial-getty-generator: Use cgroups Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 08/19] host/rootfs: systemd-udevd: Run in cgroup Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 09/19] host/rootfs: weston: " Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 10/19] host/rootfs: Set up parent cgroup for all per-VM services Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 11/19] host/rootfs: Create per-VM cgroup for all of the VM's services Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 12/19] host/rootfs: run-vmm: Create per-VM cgroup Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 13/19] host/rootfs: run-appimage: Purge the " Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 14/19] host/rootfs: run-flatpak: " Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 15/19] host/rootfs: dbus: Run in cgroup Demi Marie Obenour
2026-08-21 6:51 ` [PATCH v7 16/19] host/rootfs: vhost-user-fs: " Demi Marie Obenour
2026-08-21 6:52 ` [PATCH v7 17/19] host/rootfs: vhost-user-gpu: " Demi Marie Obenour
2026-08-21 6:52 ` [PATCH v7 18/19] host/rootfs: xdg-desktop-portal-spectrum-host: " Demi Marie Obenour
2026-08-21 6:52 ` [PATCH v7 19/19] host/rootfs: spectrum-router: " Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 00/18] Control group support Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 01/18] host/rootfs: Mount filesystems before s6-rc-init Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 02/18] tools: Add control group manager Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 03/18] Documentation: Mention control groups Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 04/18] Mount cgroup2 filesystem at /sys/fs/cgroup Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 05/18] host/rootfs: Add comments where cgroups are intentionally not used Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 06/18] host/rootfs: serial-getty-generator: Use cgroups Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 07/18] host/rootfs: systemd-udevd: Run in cgroup Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 08/18] host/rootfs: weston: " Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 09/18] host/rootfs: Set up parent cgroup for all per-VM services Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 10/18] host/rootfs: Create per-VM cgroup for all of the VM's services Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 11/18] host/rootfs: run-vmm: Create per-VM cgroup Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 12/18] host/rootfs: run-appimage: Purge the " Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 13/18] host/rootfs: run-flatpak: " Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 14/18] host/rootfs: dbus: Run in cgroup Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 15/18] host/rootfs: vhost-user-fs: " Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 16/18] host/rootfs: vhost-user-gpu: " Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 17/18] host/rootfs: xdg-desktop-portal-spectrum-host: " Demi Marie Obenour
2026-08-30 6:06 ` [PATCH v8 18/18] host/rootfs: spectrum-router: " Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 02/22] scripts: Support symlinks in s6-rc-compile inputs Demi Marie Obenour
2026-07-13 9:42 ` Alyssa Ross
2026-07-13 14:19 ` Demi Marie Obenour
2026-07-15 18:30 ` Alyssa Ross
2026-07-11 20:12 ` [PATCH v3 03/22] tools: Add control group manager Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 04/22] Documentation: Mention control groups Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 05/22] Mount cgroup2 filesystem at /sys/fs/cgroup Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 06/22] host/rootfs: Add helper program for per-VM services Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 07/22] host/rootfs: Enable controllers in sub-cgroups Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 08/22] host/rootfs: Add comments where cgroups are intentionally not used Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 09/22] host/rootfs: serial-getty-generator: Use cgroups Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 10/22] host/rootfs: Set up parent cgroup for all per-VM services Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 11/22] host/rootfs: Create per-VM cgroup for all of the VM's services Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 12/22] host/rootfs: run-vmm: Create per-VM cgroup Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 13/22] host/rootfs: run-appimage: Purge the " Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 14/22] host/rootfs: run-flatpak: " Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 15/22] host/rootfs: dbus: Run in cgroup Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 16/22] host/rootfs: vhost-user-fs: " Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 17/22] host/rootfs: vhost-user-gpu: " Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 18/22] host/rootfs: xdg-desktop-portal-spectrum-host: " Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 19/22] host/rootfs: systemd-udevd: " Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 20/22] host/rootfs: weston: " Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 21/22] host/rootfs: spectrum-router: " Demi Marie Obenour
2026-07-11 20:12 ` [PATCH v3 22/22] host/rootfs: vm-import: Use elglob -w Demi Marie Obenour
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=de99b14c-a587-47f7-819d-f9578f788f10@gmail.com \
--to=demiobenour@gmail.com \
--cc=devel@spectrum-os.org \
--cc=hi@alyssa.is \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://spectrum-os.org/git/doc
https://spectrum-os.org/git/mktuntap
https://spectrum-os.org/git/spectrum
https://spectrum-os.org/git/ucspi-vsock
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).