blob: 957dd8475869cba0d27e9a7ac7c25dd35c87376b [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Implementation of `cgroup.freeze` file.
//!
//! This file only exists on non-root cgroups. Writing "1" freezes this cgroup all of its
//! descendants, writing "0" unfreezes the cgroup, but it can still be in a frozen state if any of
//! its ancestors are frozen. Reading cgroup.freeze produces the previously written value, or 0 by
//! default. cgroup.events should be used to check the effective freezer state of the cgroup.
//!
//! Full details at https://docs.kernel.org/admin-guide/cgroup-v2.html#core-interface-files
use std::borrow::Cow;
use std::sync::{Arc, Weak};
use starnix_core::task::{CgroupOps, CurrentTask};
use starnix_core::vfs::{BytesFile, BytesFileOps, FsNodeOps};
use starnix_uapi::errors::Errno;
use starnix_uapi::{errno, error};
pub struct FreezeFile {
cgroup: Weak<dyn CgroupOps>,
}
impl FreezeFile {
pub fn new_node(cgroup: Weak<dyn CgroupOps>) -> impl FsNodeOps {
BytesFile::new_node(Self { cgroup })
}
fn cgroup(&self) -> Result<Arc<dyn CgroupOps>, Errno> {
self.cgroup.upgrade().ok_or_else(|| errno!(ENODEV))
}
}
impl BytesFileOps for FreezeFile {
fn write(&self, _current_task: &CurrentTask, data: Vec<u8>) -> Result<(), Errno> {
let state_str = std::str::from_utf8(&data).map_err(|_| errno!(EINVAL))?;
let cgroup = self.cgroup()?;
match state_str.trim() {
"1" => Ok(cgroup.freeze()),
"0" => Ok(cgroup.thaw()),
_ => error!(EINVAL),
}
}
fn read(&self, _current_task: &CurrentTask) -> Result<Cow<'_, [u8]>, Errno> {
let state_str = format!("{}\n", self.cgroup()?.get_freezer_state().self_freezer_state);
Ok(state_str.as_bytes().to_owned().into())
}
}