tikv_util: fix panic when there are multiple cgroup2 mountinfos
close tikv/tikv#13660
fix panic when there are multiple cgroup2 mountinfos
@@ -255,11 +255,18 @@ fn cgroup_mountinfos_v2() -> HashMap<String, (String, PathBuf)> {
}
fn parse_mountinfos_v2(infos: Vec<MountInfo>) -> HashMap<String, (String, PathBuf)> {
- let mut ret = HashMap::new();
- let mut cg_infos = infos.into_iter().filter(|x| x.fs_type == "cgroup2");
- if let Some(cg_info) = cg_infos.next() {
- assert!(cg_infos.next().is_none()); // Only one item for cgroup-2.
- ret.insert("".to_string(), (cg_info.root, cg_info.mount_point));
+ let mut ret: HashMap<String, (String, PathBuf)> = HashMap::new();
+ let cg_infos = infos.into_iter().filter(|x| x.fs_type == "cgroup2");
+ for info in cg_infos {
+ // Should only be one item for cgroup-2.
+ if let Some((root, mount_point)) = ret.insert("".to_string(), (info.root, info.mount_point))
+ {
+ warn!(
+ "Found multiple cgroup2 mountinfos, dropping {} {}",
+ root,
+ mount_point.display()
+ );
+ }
}
ret
}
@@ -450,6 +457,36 @@ mod tests {
assert_eq!(cgroup_sys.memory_limit_in_bytes(), None);
}
+ #[test]
+ fn test_conflicting_mountinfo() {
+ let temp = tempfile::TempDir::new().unwrap();
+ let dir = temp.path().to_str().unwrap();
+ std::fs::copy("/proc/self/stat", &format!("{}/stat", dir)).unwrap();
+
+ let mut f = OpenOptions::new()
+ .create(true)
+ .write(true)
+ .open(&format!("{}/mountinfo", dir))
+ .unwrap();
+ f.write_all(b"1663 1661 0:27 /../../../../../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup2 rw
+ 1663 1661 0:27 /../../../../../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup2 rw").unwrap();
+
+ let cgroups = parse_proc_cgroup_v2("0::/\n");
+ let mount_points = {
+ let infos = Process::new_with_root(PathBuf::from(dir))
+ .and_then(|x| x.mountinfo())
+ .unwrap();
+ parse_mountinfos_v2(infos)
+ };
+ let cgroup_sys = CGroupSys {
+ cgroups,
+ mount_points,
+ is_v2: true,
+ };
+
+ assert_eq!(cgroup_sys.memory_limit_in_bytes(), None);
+ }
+
#[test]
fn test_cgroup_without_mountinfo() {
let temp = tempfile::TempDir::new().unwrap();
