Skip to content

Commit 71e96db

Browse files
Merge pull request #460 from Bluemangoo/feature/vmstat-slabs
vmstat: implement `--slabs`
2 parents 0f9011b + 8bd9a1f commit 71e96db

File tree

5 files changed

+71
-18
lines changed

5 files changed

+71
-18
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/uu/slabtop/src/parse.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,35 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
use std::{
7-
cmp::Ordering,
8-
fs,
9-
io::{Error, ErrorKind},
10-
};
6+
use std::io::Error;
7+
use std::{cmp::Ordering, fs, io::ErrorKind};
8+
use uucore::error::{UError, UResult, USimpleError};
119

1210
#[derive(Debug, Default)]
13-
pub(crate) struct SlabInfo {
14-
pub(crate) meta: Vec<String>,
15-
pub(crate) data: Vec<(String, Vec<u64>)>,
11+
pub struct SlabInfo {
12+
pub meta: Vec<String>,
13+
pub data: Vec<(String, Vec<u64>)>,
1614
}
1715

1816
impl SlabInfo {
1917
// parse slabinfo from /proc/slabinfo
2018
// need root permission
21-
pub fn new() -> Result<SlabInfo, Error> {
22-
let content = fs::read_to_string("/proc/slabinfo")?;
19+
pub fn new() -> UResult<SlabInfo> {
20+
let error_wrapper = |e: Error| {
21+
USimpleError::new(
22+
1,
23+
format!(
24+
"Unable to create slabinfo structure: {}",
25+
Box::<dyn UError>::from(e) // We need Display impl of UError
26+
),
27+
)
28+
};
29+
30+
let content = fs::read_to_string("/proc/slabinfo").map_err(error_wrapper)?;
2331

24-
Self::parse(&content).ok_or(ErrorKind::Unsupported.into())
32+
Self::parse(&content)
33+
.ok_or(ErrorKind::Unsupported.into())
34+
.map_err(error_wrapper)
2535
}
2636

2737
pub fn parse(content: &str) -> Option<SlabInfo> {

src/uu/slabtop/src/slabtop.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
use crate::parse::SlabInfo;
6+
pub use crate::parse::SlabInfo;
77
use clap::{arg, crate_version, ArgAction, Command};
88
use uucore::{error::UResult, format_usage, help_about, help_section, help_usage};
99

@@ -25,6 +25,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
2525

2626
let slabinfo = SlabInfo::new()?.sort(*sort_flag, false);
2727

28+
println!("{slabinfo:?}");
29+
2830
if matches.get_flag("once") {
2931
output_header(&slabinfo);
3032
println!();

src/uu/vmstat/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ clap = { workspace = true }
1717
terminal_size = { workspace = true }
1818
uucore = { workspace = true, features = ["custom-tz-fmt"] }
1919

20+
uu_slabtop = {path = "../slabtop"}
21+
2022
[lib]
2123
path = "src/vmstat.rs"
2224

src/uu/vmstat/src/vmstat.rs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
3838

3939
let one_header = matches.get_flag("one-header");
4040
let no_first = matches.get_flag("no-first");
41+
let term_height = terminal_size::terminal_size()
42+
.map(|size| size.1 .0)
43+
.unwrap_or(0);
44+
45+
if matches.get_flag("slabs") {
46+
return print_slabs(one_header, term_height);
47+
}
4148

4249
let delay = matches.get_one::<u64>("delay");
4350
let count = matches.get_one::<u64>("count");
@@ -57,14 +64,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
5764
line_count += 1;
5865
}
5966

60-
let term_height = terminal_size::terminal_size()
61-
.map(|size| size.1 .0)
62-
.unwrap_or(0);
63-
6467
while count.is_none() || line_count < count.unwrap() {
6568
std::thread::sleep(std::time::Duration::from_secs(delay));
6669
let proc_data_now = ProcData::new();
67-
if !one_header && term_height > 0 && ((line_count + 3) % term_height as u64 == 0) {
70+
if needs_header(one_header, term_height, line_count) {
6871
print_header(&pickers);
6972
}
7073
print_data(&pickers, &proc_data_now, Some(&proc_data), &matches);
@@ -76,6 +79,41 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
7679
Ok(())
7780
}
7881

82+
#[cfg(target_os = "linux")]
83+
fn print_slabs(one_header: bool, term_height: u16) -> UResult<()> {
84+
let mut slab_data = uu_slabtop::SlabInfo::new()?.data;
85+
86+
slab_data.sort_by_key(|k| k.0.to_lowercase());
87+
88+
print_slab_header();
89+
90+
for (line_count, slab_item) in slab_data.into_iter().enumerate() {
91+
if needs_header(one_header, term_height, line_count as u64) {
92+
print_slab_header();
93+
}
94+
95+
println!(
96+
"{:<24} {:>6} {:>6} {:>6} {:>6}",
97+
slab_item.0, slab_item.1[0], slab_item.1[1], slab_item.1[2], slab_item.1[3]
98+
);
99+
}
100+
101+
Ok(())
102+
}
103+
104+
#[cfg(target_os = "linux")]
105+
fn needs_header(one_header: bool, term_height: u16, line_count: u64) -> bool {
106+
!one_header && term_height > 0 && ((line_count + 3) % term_height as u64 == 0)
107+
}
108+
109+
#[cfg(target_os = "linux")]
110+
fn print_slab_header() {
111+
println!(
112+
"{:<24} {:>6} {:>6} {:>6} {:>6}",
113+
"Cache", "Num", "Total", "Size", "Pages"
114+
);
115+
}
116+
79117
#[cfg(target_os = "linux")]
80118
fn print_header(pickers: &[Picker]) {
81119
let mut section: Vec<&str> = vec![];
@@ -126,7 +164,7 @@ pub fn uu_app() -> Command {
126164
.value_parser(value_parser!(u64)),
127165
arg!(-a --active "Display active and inactive memory"),
128166
// arg!(-f --forks "switch displays the number of forks since boot"),
129-
// arg!(-m --slabs "Display slabinfo"),
167+
arg!(-m --slabs "Display slabinfo"),
130168
arg!(-n --"one-header" "Display the header only once rather than periodically"),
131169
// arg!(-s --stats "Displays a table of various event counters and memory statistics"),
132170
// arg!(-d --disk "Report disk statistics"),

0 commit comments

Comments
 (0)