cgroup: support to set threaded mode in cgroup v2

Support to set threaded mode in cgroup v2. The premise of switching to threaded mode is that only the cgroup of cpuset, cpu and pids is supported.

Fixes: #90

Signed-off-by: yaoyinnan <yaoyinnan@foxmail.com>
This commit is contained in:
yaoyinnan
2022-12-30 12:46:50 +08:00
parent 0348f0a95e
commit c9d02afe33
14 changed files with 421 additions and 82 deletions
+14 -7
View File
@@ -22,7 +22,8 @@ pub fn test_cpu_res_build() {
.cpu()
.shares(85)
.done()
.build(h);
.build(h)
.unwrap();
{
let cpu: &CpuController = cg.controller_of().unwrap();
@@ -42,7 +43,8 @@ pub fn test_memory_res_build() {
.swappiness(70)
.memory_hard_limit(1024 * 1024 * 1024)
.done()
.build(h);
.build(h)
.unwrap();
{
let c: &MemController = cg.controller_of().unwrap();
@@ -64,7 +66,8 @@ pub fn test_pid_res_build() {
.pid()
.maximum_number_of_processes(MaxValue::Value(123))
.done()
.build(h);
.build(h)
.unwrap();
{
let c: &PidController = cg.controller_of().unwrap();
@@ -83,7 +86,8 @@ pub fn test_devices_res_build() {
.devices()
.device(1, 6, DeviceType::Char, true, vec![DevicePermissions::Read])
.done()
.build(h);
.build(h)
.unwrap();
{
let c: &DevicesController = cg.controller_of().unwrap();
@@ -113,7 +117,8 @@ pub fn test_network_res_build() {
.network()
.class_id(1337)
.done()
.build(h);
.build(h)
.unwrap();
{
let c: &NetClsController = cg.controller_of().unwrap();
@@ -134,7 +139,8 @@ pub fn test_hugepages_res_build() {
.hugepages()
.limit("2MB".to_string(), 4 * 2 * 1024 * 1024)
.done()
.build(h);
.build(h)
.unwrap();
{
let c: &HugeTlbController = cg.controller_of().unwrap();
@@ -152,7 +158,8 @@ pub fn test_blkio_res_build() {
.blkio()
.weight(100)
.done()
.build(h);
.build(h)
.unwrap();
{
let c: &BlkIoController = cg.controller_of().unwrap();
+65 -14
View File
@@ -10,28 +10,25 @@ use cgroups_rs::Controller;
use cgroups_rs::{Cgroup, CgroupPid, Subsystem};
#[test]
fn test_tasks_iterator() {
fn test_procs_iterator_cgroup() {
let h = cgroups_rs::hierarchies::auto();
let pid = libc::pid_t::from(nix::unistd::getpid()) as u64;
let cg = Cgroup::new(h, String::from("test_tasks_iterator"));
let cg = Cgroup::new(h, String::from("test_procs_iterator_cgroup")).unwrap();
{
// Add a task to the control group.
cg.add_task(CgroupPid::from(pid)).unwrap();
cg.add_task_by_tgid(CgroupPid::from(pid)).unwrap();
use std::{thread, time};
thread::sleep(time::Duration::from_millis(100));
let mut tasks = cg.tasks().into_iter();
// Verify that the task is indeed in the control group
assert_eq!(tasks.next(), Some(CgroupPid::from(pid)));
assert_eq!(tasks.next(), None);
let mut procs = cg.procs().into_iter();
// Verify that the task is indeed in the xcontrol group
assert_eq!(procs.next(), Some(CgroupPid::from(pid)));
assert_eq!(procs.next(), None);
// Now, try removing it.
cg.remove_task(CgroupPid::from(pid));
tasks = cg.tasks().into_iter();
cg.remove_task_by_tgid(CgroupPid::from(pid)).unwrap();
procs = cg.procs().into_iter();
// Verify that it was indeed removed.
assert_eq!(tasks.next(), None);
assert_eq!(procs.next(), None);
}
cg.delete().unwrap();
}
@@ -83,7 +80,7 @@ fn test_cgroup_v2() {
return;
}
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_v2"));
let cg = Cgroup::new(h, String::from("test_v2")).unwrap();
let mem_controller: &MemController = cg.controller_of().unwrap();
let (mem, swp, rev) = (4 * 1024 * 1000, 2 * 1024 * 1000, 1024 * 1000);
@@ -103,3 +100,57 @@ fn test_cgroup_v2() {
cg.delete().unwrap();
}
#[test]
fn test_tasks_iterator_cgroup_threaded_mode() {
if !cgroups_rs::hierarchies::is_cgroup2_unified_mode() {
return;
}
let h = cgroups_rs::hierarchies::auto();
let pid = libc::pid_t::from(nix::unistd::getpid()) as u64;
let cg = Cgroup::new(h, String::from("test_tasks_iterator_cgroup_threaded_mode")).unwrap();
let h = cgroups_rs::hierarchies::auto();
let specified_controllers = vec![String::from("cpuset"), String::from("cpu")];
let cg_threaded = Cgroup::new_with_specified_controllers(
h,
String::from("test_tasks_iterator_cgroup_threaded_mode/threaded"),
Some(specified_controllers),
)
.unwrap();
cg_threaded.set_cgroup_type("threaded").unwrap();
{
// Add a task to the control group.
cg.add_task_by_tgid(CgroupPid::from(pid)).unwrap();
let mut procs = cg.procs().into_iter();
// Verify that the task is indeed in the xcontrol group
assert_eq!(procs.next(), Some(CgroupPid::from(pid)));
assert_eq!(procs.next(), None);
// Add a task to the sub control group.
cg_threaded.add_task(CgroupPid::from(pid)).unwrap();
let mut tasks = cg_threaded.tasks().into_iter();
// Verify that the task is indeed in the xcontrol group
assert_eq!(tasks.next(), Some(CgroupPid::from(pid)));
assert_eq!(tasks.next(), None);
// Now, try move it to parent.
cg_threaded
.move_task_to_parent(CgroupPid::from(pid))
.unwrap();
tasks = cg_threaded.tasks().into_iter();
// Verify that it was indeed removed.
assert_eq!(tasks.next(), None);
// Now, try removing it.
cg.remove_task_by_tgid(CgroupPid::from(pid)).unwrap();
procs = cg.procs().into_iter();
// Verify that it was indeed removed.
assert_eq!(procs.next(), None);
}
cg_threaded.delete().unwrap();
cg.delete().unwrap();
}
+1 -1
View File
@@ -10,7 +10,7 @@ use cgroups_rs::Cgroup;
#[test]
fn test_cfs_quota_and_periods() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_cfs_quota_and_periods"));
let cg = Cgroup::new(h, String::from("test_cfs_quota_and_periods")).unwrap();
let cpu_controller: &CpuController = cg.controller_of().unwrap();
+5 -5
View File
@@ -13,7 +13,7 @@ use std::fs;
#[test]
fn test_cpuset_memory_pressure_root_cg() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_cpuset_memory_pressure_root_cg"));
let cg = Cgroup::new(h, String::from("test_cpuset_memory_pressure_root_cg")).unwrap();
{
let cpuset: &CpuSetController = cg.controller_of().unwrap();
@@ -27,7 +27,7 @@ fn test_cpuset_memory_pressure_root_cg() {
#[test]
fn test_cpuset_set_cpus() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_cpuset_set_cpus"));
let cg = Cgroup::new(h, String::from("test_cpuset_set_cpus")).unwrap();
{
let cpuset: &CpuSetController = cg.controller_of().unwrap();
@@ -64,7 +64,7 @@ fn test_cpuset_set_cpus() {
#[test]
fn test_cpuset_set_cpus_add_task() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_cpuset_set_cpus_add_task/sub-dir"));
let cg = Cgroup::new(h, String::from("test_cpuset_set_cpus_add_task/sub-dir")).unwrap();
let cpuset: &CpuSetController = cg.controller_of().unwrap();
let set = cpuset.cpuset();
@@ -77,13 +77,13 @@ fn test_cpuset_set_cpus_add_task() {
// Add a task to the control group.
let pid_i = libc::pid_t::from(nix::unistd::getpid()) as u64;
let _ = cg.add_task(CgroupPid::from(pid_i));
let _ = cg.add_task_by_tgid(CgroupPid::from(pid_i));
let tasks = cg.tasks();
assert!(!tasks.is_empty());
println!("tasks after added: {:?}", tasks);
// remove task
cg.remove_task(CgroupPid::from(pid_i));
cg.remove_task_by_tgid(CgroupPid::from(pid_i)).unwrap();
let tasks = cg.tasks();
println!("tasks after deleted: {:?}", tasks);
assert_eq!(0, tasks.len());
+1 -1
View File
@@ -17,7 +17,7 @@ fn test_devices_parsing() {
}
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_devices_parsing"));
let cg = Cgroup::new(h, String::from("test_devices_parsing")).unwrap();
{
let devices: &DevicesController = cg.controller_of().unwrap();
+1 -1
View File
@@ -17,7 +17,7 @@ fn test_hugetlb_sizes() {
}
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_hugetlb_sizes"));
let cg = Cgroup::new(h, String::from("test_hugetlb_sizes")).unwrap();
{
let hugetlb_controller: &HugeTlbController = cg.controller_of().unwrap();
let _ = hugetlb_controller.get_sizes();
+3 -3
View File
@@ -11,7 +11,7 @@ use cgroups_rs::{Cgroup, MaxValue};
#[test]
fn test_disable_oom_killer() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_disable_oom_killer"));
let cg = Cgroup::new(h, String::from("test_disable_oom_killer")).unwrap();
{
let mem_controller: &MemController = cg.controller_of().unwrap();
@@ -40,7 +40,7 @@ fn set_kmem_limit_v1() {
return;
}
let cg = Cgroup::new(h, String::from("set_kmem_limit_v1"));
let cg = Cgroup::new(h, String::from("set_kmem_limit_v1")).unwrap();
{
let mem_controller: &MemController = cg.controller_of().unwrap();
mem_controller.set_kmem_limit(1).unwrap();
@@ -55,7 +55,7 @@ fn set_mem_v2() {
return;
}
let cg = Cgroup::new(h, String::from("set_mem_v2"));
let cg = Cgroup::new(h, String::from("set_mem_v2")).unwrap();
{
let mem_controller: &MemController = cg.controller_of().unwrap();
+5 -5
View File
@@ -17,7 +17,7 @@ use libc::pid_t;
#[test]
fn create_and_delete_cgroup() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("create_and_delete_cgroup"));
let cg = Cgroup::new(h, String::from("create_and_delete_cgroup")).unwrap();
{
let pidcontroller: &PidController = cg.controller_of().unwrap();
pidcontroller.set_pid_max(MaxValue::Value(1337)).unwrap();
@@ -31,7 +31,7 @@ fn create_and_delete_cgroup() {
#[test]
fn test_pids_current_is_zero() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_pids_current_is_zero"));
let cg = Cgroup::new(h, String::from("test_pids_current_is_zero")).unwrap();
{
let pidcontroller: &PidController = cg.controller_of().unwrap();
let current = pidcontroller.get_pid_current();
@@ -43,7 +43,7 @@ fn test_pids_current_is_zero() {
#[test]
fn test_pids_events_is_zero() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_pids_events_is_zero"));
let cg = Cgroup::new(h, String::from("test_pids_events_is_zero")).unwrap();
{
let pidcontroller: &PidController = cg.controller_of().unwrap();
let events = pidcontroller.get_pid_events();
@@ -56,7 +56,7 @@ fn test_pids_events_is_zero() {
#[test]
fn test_pid_events_is_not_zero() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("test_pid_events_is_not_zero"));
let cg = Cgroup::new(h, String::from("test_pid_events_is_not_zero")).unwrap();
{
let pids: &PidController = cg.controller_of().unwrap();
let before = pids.get_pid_events();
@@ -65,7 +65,7 @@ fn test_pid_events_is_not_zero() {
match unsafe { fork() } {
Ok(ForkResult::Parent { child, .. }) => {
// move the process into the control group
let _ = pids.add_task(&(pid_t::from(child) as u64).into());
let _ = pids.add_task_by_tgid(&(pid_t::from(child) as u64).into());
println!("added task to cg: {:?}", child);
+1 -1
View File
@@ -11,7 +11,7 @@ use cgroups_rs::{Cgroup, MaxValue, PidResources, Resources};
#[test]
fn pid_resources() {
let h = cgroups_rs::hierarchies::auto();
let cg = Cgroup::new(h, String::from("pid_resources"));
let cg = Cgroup::new(h, String::from("pid_resources")).unwrap();
{
let res = Resources {
pid: PidResources {