Skip to content

Commit

Permalink
Fix io.stat parsing
Browse files Browse the repository at this point in the history
Summary:
Don't fail `io.stat` parsing due to lines without kv pairs.
Example:
```
$ cat /sys/fs/cgroup/io.stat
7:7
7:6
7:5
7:4
7:3
7:2
7:1
7:0
253:0 rbytes=40137493143552 wbytes=11685175186432 rios=172066882 wios=73548256 dbytes=17052408471552 dios=36700731
```
Kernel logic: https://github.com/torvalds/linux/blob/075dbe9f6e3c21596c5245826a4ee1f1c1676eb8/block/blk-cgroup.c#L1171

Reviewed By: dschatzberg

Differential Revision: D63488396

fbshipit-source-id: a5421e1105ef984c6f4a88cf79773d4f01af7bde
  • Loading branch information
Andrew Onyshchuk authored and facebook-github-bot committed Sep 27, 2024
1 parent 636bb2a commit bf3814c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 20 deletions.
42 changes: 23 additions & 19 deletions below/cgroupfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,28 +777,32 @@ macro_rules! name_key_equal_value_format {
r.io_error(file_name.clone(), e)
})?;
// as an example, io.stat looks like:
// 7:0
// 253:0 rbytes=531745786880 wbytes=1623798909952 ...
let mut items = line.split_ascii_whitespace();
let mut items = line.split_terminator(' ').peekable();
let Some(first_item) = items.next() else {
continue
};
// Skip lines with no kv pairs
if items.peek().is_none() {
continue
}
let mut s = $struct::default();
if let Some(first_item) = items.next() {
for item in items {
let mut kv = item.splitn(2, "=");
let key = kv.next().ok_or_else(|| r.invalid_file_format(file_name.clone()))?;
let value = kv.next().ok_or_else(|| r.invalid_file_format(file_name.clone()))?;
// Certain keys such as cost.usage cannot be struct fields so must use cost_usage
let key = key.replace(".", "_");
parse_and_set_fields!(
s;
key.as_ref();
value.parse().map_err(|_| r.unexpected_line(file_name.clone(), line.clone()))?;
[ $($field,)* ]
)
}
if s == $struct::default() {
return Err(r.invalid_file_format(file_name));
}
map.insert(first_item.to_string(), s);
for item in items {
let (key, value) = item.split_once('=').ok_or_else(|| r.invalid_file_format(file_name.clone()))?;
// Certain keys such as cost.usage cannot be struct fields so must use cost_usage
let key = key.replace(".", "_");
parse_and_set_fields!(
s;
key.as_ref();
value.parse().map_err(|_| r.unexpected_line(file_name.clone(), line.clone()))?;
[ $($field,)* ]
)
}
if s == $struct::default() {
return Err(r.invalid_file_format(file_name));
}
map.insert(first_item.to_string(), s);
}
if !$allows_empty.0 && map.is_empty() {
Err(r.invalid_file_format(file_name))
Expand Down
2 changes: 1 addition & 1 deletion below/cgroupfs/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ fn test_cpu_stat_invalid_format() {
#[test]
fn test_io_stat_success() {
let cgroup = TestCgroup::new();
cgroup.create_file_with_content("io.stat", b"253:0 rbytes=531 wbytes=162379 rios=61 wios=81 dbytes=0 dios=0\n13:0 rbytes=135 wbytes=162379 rios=61 wios=81 dbytes=0 dios=0 cost.usage=25 cost.wait=38 cost.indebt=64 cost.indelay=0\n");
cgroup.create_file_with_content("io.stat", b"7:0 \n253:0 rbytes=531 wbytes=162379 rios=61 wios=81 dbytes=0 dios=0\n13:0 rbytes=135 wbytes=162379 rios=61 wios=81 dbytes=0 dios=0 cost.usage=25 cost.wait=38 cost.indebt=64 cost.indelay=0\n");

let cgroup_reader = cgroup.get_reader();
let val = cgroup_reader
Expand Down

0 comments on commit bf3814c

Please sign in to comment.