@@ -206,7 +206,7 @@ def __init__(self):
206
206
207
207
def new_cgroup (self , cgname ):
208
208
"""Create a new cgroup"""
209
- self .root .joinpath (cgname ).mkdir (parents = True )
209
+ self .root .joinpath (cgname ).mkdir (parents = True , exist_ok = True )
210
210
211
211
def move_pid (self , cgname , pid ):
212
212
"""Move a PID to a cgroup"""
@@ -612,3 +612,61 @@ def test_firecracker_kill_by_pid(uvm_plain, daemonize, new_pid_ns):
612
612
and microvm .jailer .new_pid_ns == new_pid_ns
613
613
)
614
614
microvm .kill ()
615
+
616
+
617
+ def test_cgroupsv2_written_only_once (uvm_plain , cgroups_info ):
618
+ """
619
+ Test that we only write to cgroup.procs once when using CgroupsV2
620
+
621
+ Assert that the jailer doesn't perform unneccessary create_dir_all
622
+ and attach_pid calls. This is a regression test for #2856
623
+ """
624
+ if cgroups_info .version != 2 :
625
+ pytest .skip (reason = "Requires system with cgroup-v2 enabled." )
626
+
627
+ uvm = uvm_plain
628
+ strace_output_path = Path (uvm .path , "strace.out" )
629
+ strace_cmd = [
630
+ "strace" ,
631
+ "-tt" ,
632
+ "--syscall-times=ns" ,
633
+ "-y" ,
634
+ "-e" ,
635
+ "write,mkdir,mkdirat" ,
636
+ "-o" ,
637
+ strace_output_path ,
638
+ ]
639
+ uvm .add_pre_cmd (strace_cmd )
640
+
641
+ parent_cgroup = "custom_cgroup/group2"
642
+ uvm .jailer .cgroup_ver = cgroups_info .version
643
+ uvm .jailer .parent_cgroup = parent_cgroup
644
+ # create the parent so that mkdirs doesn't need to
645
+ cgroups_info .new_cgroup (parent_cgroup )
646
+
647
+ cgroups = {
648
+ "cpuset.cpus" : get_cpus (0 ),
649
+ "cpu.weight" : 2 ,
650
+ "memory.max" : 256 * 2 ** 20 ,
651
+ "memory.min" : 1 * 2 ** 20 ,
652
+ }
653
+ uvm .jailer .cgroups = [f"{ k } ={ v } " for k , v in cgroups .items ()]
654
+ uvm .spawn ()
655
+ uvm .basic_config ()
656
+ uvm .add_net_iface ()
657
+ uvm .start ()
658
+ strace_out = strace_output_path .read_text (encoding = "utf-8" ).splitlines ()
659
+ write_lines = [
660
+ line
661
+ for line in strace_out
662
+ if "write" in line and f"{ uvm .id } /cgroup.procs" in line
663
+ ]
664
+ mkdir_lines = [
665
+ line
666
+ for line in strace_out
667
+ if "mkdir" in line and f"{ parent_cgroup } /{ uvm .id } " in line
668
+ ]
669
+ assert len (write_lines ) != len (cgroups ), "writes equal to number of cgroups"
670
+ assert len (write_lines ) == 1
671
+ assert len (mkdir_lines ) != len (cgroups ), "mkdir equal to number of cgroups"
672
+ assert len (mkdir_lines ) == 1
0 commit comments