@@ -206,7 +206,7 @@ def __init__(self):
206206
207207 def new_cgroup (self , cgname ):
208208 """Create a new cgroup"""
209- self .root .joinpath (cgname ).mkdir (parents = True )
209+ self .root .joinpath (cgname ).mkdir (parents = True , exist_ok = True )
210210
211211 def move_pid (self , cgname , pid ):
212212 """Move a PID to a cgroup"""
@@ -612,3 +612,61 @@ def test_firecracker_kill_by_pid(uvm_plain, daemonize, new_pid_ns):
612612 and microvm .jailer .new_pid_ns == new_pid_ns
613613 )
614614 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