diff options
author | Brian Chen <brianc118@meta.com> | 2023-06-22 14:13:01 -0700 |
---|---|---|
committer | Facebook GitHub Bot <facebook-github-bot@users.noreply.github.com> | 2023-06-22 14:13:01 -0700 |
commit | e7aded45b387614aa97d695ef0a61f1934a31595 (patch) | |
tree | 3674f805e99b52161e31da7f169ba4e4b838cf76 | |
parent | e96c4280b872b03fc5c159d2acf885023989af61 (diff) |
Support for offlined CPUs in /proc/stat (#8193)
Summary:
Pull Request resolved: https://github.com/facebookincubator/below/pull/8193
Currently procfs assumes that no CPUs are offlined. That is not always
the case.
Addresses #8190.
Reviewed By: antonis-m
Differential Revision: D46937378
fbshipit-source-id: 3f21fbd283fb43e4f6c64c4a28e6e756ca23a93e
-rw-r--r-- | below/procfs/src/lib.rs | 20 | ||||
-rw-r--r-- | below/procfs/src/test.rs | 8 | ||||
-rw-r--r-- | below/procfs/src/types.rs | 2 |
3 files changed, 21 insertions, 9 deletions
diff --git a/below/procfs/src/lib.rs b/below/procfs/src/lib.rs index bee9d294..667d04af 100644 --- a/below/procfs/src/lib.rs +++ b/below/procfs/src/lib.rs @@ -181,7 +181,7 @@ impl ProcReader { } fn process_cpu_stat(path: &PathBuf, line: &String) -> Result<CpuStat> { - //Format is like "cpu9 6124418 452468 3062529 230073290 216237 0 45647 0 0 0" + // Format is like "cpu9 6124418 452468 3062529 230073290 216237 0 45647 0 0 0" let mut items = line.split_whitespace(); let mut cpu: CpuStat = Default::default(); @@ -215,7 +215,7 @@ impl ProcReader { let file = File::open(&path).map_err(|e| Error::IoError(path.clone(), e))?; let buf_reader = BufReader::new(file); let mut stat: Stat = Default::default(); - let mut cpus = Vec::new(); + let mut cpus_map = BTreeMap::new(); for line in buf_reader.lines() { let line = line.map_err(|e| Error::IoError(path.clone(), e))?; @@ -241,15 +241,23 @@ impl ProcReader { x => { if x == "cpu" { stat.total_cpu = Some(Self::process_cpu_stat(&path, &line)?); - } else if x.starts_with("cpu") { - cpus.push(Self::process_cpu_stat(&path, &line)?); + } else if let Some(cpu_suffix) = x.strip_prefix("cpu") { + let cpu_id = + parse_item!(&path, Some(cpu_suffix.to_owned()), u32, line)? + .unwrap(); + let existing = + cpus_map.insert(cpu_id, Self::process_cpu_stat(&path, &line)?); + if existing.is_some() { + return Err(Error::UnexpectedLine(path, line)); + } } } } } } - if !cpus.is_empty() { - stat.cpus = Some(cpus); + if !cpus_map.is_empty() { + stat.cpus = Some(cpus_map.values().cloned().collect()); + stat.cpus_map = Some(cpus_map); } if stat == Default::default() { diff --git a/below/procfs/src/test.rs b/below/procfs/src/test.rs index 94e2c703..3d554cd4 100644 --- a/below/procfs/src/test.rs +++ b/below/procfs/src/test.rs @@ -160,7 +160,6 @@ cpu18 5917745 448756 3050060 230279037 215704 0 45064 0 0 0 cpu19 6042834 433710 3058862 230151162 214883 0 45179 0 0 0 cpu20 5804757 444950 3057184 230372774 224962 0 46132 0 0 0 cpu21 5935027 455253 3052007 230250433 209736 0 45325 0 0 0 -cpu22 5874699 446579 3061270 230279298 235842 0 45808 0 0 0 cpu23 5937943 460201 3057286 230166670 230819 0 42628 0 0 0 intr 29638874355 54 9 0 0 14325 0 0 0 1 0 19 0 5 0 0 0 0 0 0 0 0 0 0 0 0 14 0 109094370 0 464199486 9840 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ctxt 48203489122 @@ -189,8 +188,11 @@ softirq 15518280031 0 3506477306 138437 1090758178 117192437 0 24543 800441241 9 assert_eq!(total_cpu.guest_nice_usec, Some(0)); - let cpu23 = &stat.cpus.expect("Failed to read cpus")[23]; - assert_eq!(cpu23.user_usec, Some(59379430000)); + let cpu23_from_vec = &stat.cpus.expect("Failed to read cpus")[22]; + assert_eq!(cpu23_from_vec.user_usec, Some(59379430000)); + + let cpu23_from_map = &stat.cpus_map.expect("Failed to read cpus_map")[&23]; + assert_eq!(cpu23_from_map.user_usec, Some(59379430000)); assert_eq!(stat.total_interrupt_count, Some(29638874355)); assert_eq!(stat.context_switches, Some(48203489122)); diff --git a/below/procfs/src/types.rs b/below/procfs/src/types.rs index 665b4c19..ae97e267 100644 --- a/below/procfs/src/types.rs +++ b/below/procfs/src/types.rs @@ -35,7 +35,9 @@ pub struct CpuStat { #[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)] pub struct Stat { pub total_cpu: Option<CpuStat>, + // TODO: deprecate in favor of cpus_map pub cpus: Option<Vec<CpuStat>>, + pub cpus_map: Option<BTreeMap<u32, CpuStat>>, pub total_interrupt_count: Option<u64>, pub context_switches: Option<u64>, pub boot_time_epoch_secs: Option<u64>, |