1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// linux source:
// block/genhd.c >= v2.6.18
// https://elixir.bootlin.com/linux/v2.6.18/source/block/genhd.c#L550
use crate::diskstats::DiskStat;
use crate::diskstats::DiskStats;
use crate::scanner::ProcScanner;
use crate::ProcResult;
use cfg_iif::cfg_iif;
#[derive(Debug, Default, Clone)]
pub(crate) struct DiskStatsParser();
impl DiskStatsParser {
pub fn parse(&mut self, sl: &[u8]) -> ProcResult<DiskStats> {
let mut diskstats = DiskStats::default();
if sl.is_empty() {
return Ok(diskstats);
}
//
let mut sc = ProcScanner::new(sl);
let mut idx: usize = 0;
while !sc.is_empty() {
//
if idx >= diskstats.disks.len() {
diskstats.disks.resize(idx + 1, DiskStat::default());
}
let disk_ref: &mut DiskStat = match diskstats.disks.get_mut(idx) {
Some(disk) => disk,
None => return Err(crate::ProcError::InternalError),
};
{
// content of /proc/diskstats
// " 8 0 sda 808426 1058879 43196702 7472309 1536575 1841370 131099984 42740862 0 8137730 50228410\n"
// " 8 5 sda5 500283 837502 22925858 3932966 1183846 1552668 116130520 33073524 0 5715397 37007467\n"
// on linux:
// "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n"
//
// on linux 5.4.0
// " 252 0 vda 14907 5047 1609802 6814 37573 12037 1280416 107798 0 34264 78540 0 0 0 0\n"
//
cfg_iif!(feature = "has_diskstats_device_number" {
sc.skip_spaces();
disk_ref.major_num = sc.next(b' ')?;
sc.skip_spaces();
disk_ref.minor_num = sc.next(b' ')?;
} else {
// device major number
sc.skip_spaces();
sc.scan_until(b' ')?;
// device minor number
sc.skip_spaces();
sc.scan_until(b' ')?;
});
// device name
{
sc.skip_spaces();
let s = sc.scan_until(b' ')?;
disk_ref.name = String::from_utf8_lossy(s).into_owned();
}
// read & write
{
sc.skip_spaces();
disk_ref.rio = sc.next(b' ')?;
sc.skip_spaces();
disk_ref.rmerge = sc.next(b' ')?;
sc.skip_spaces();
disk_ref.rblk = sc.next(b' ')?;
sc.skip_spaces();
disk_ref.ruse = sc.next(b' ')?;
//
sc.skip_spaces();
disk_ref.wio = sc.next(b' ')?;
sc.skip_spaces();
disk_ref.wmerge = sc.next(b' ')?;
sc.skip_spaces();
disk_ref.wblk = sc.next(b' ')?;
sc.skip_spaces();
disk_ref.wuse = sc.next(b' ')?;
}
//
cfg_iif!(feature = "has_diskstats_running" {
sc.skip_spaces();
disk_ref.running = sc.next(b' ')?;
} else {
sc.skip_spaces();
sc.scan_until(b' ')?; // running
});
//
cfg_iif!(feature = "has_diskstats_use" {
sc.skip_spaces();
disk_ref.use_ = sc.next(b' ')?;
} else {
sc.skip_spaces();
sc.scan_until(b' ')?; // use
});
//
{
sc.skip_spaces();
disk_ref.aveq = sc.next_any(b" \n")?;
if sc.last_delimiter() != b'\n' {
sc.scan_until(b'\n')?;
}
}
}
//
idx += 1;
}
diskstats.disks.resize(idx, DiskStat::default());
//
Ok(diskstats)
}
}