btrfs_cli/scrub/
status.rs1use crate::{Format, Runnable, util::human_bytes};
2use anyhow::{Context, Result};
3use btrfs_uapi::{
4 device::device_info_all, filesystem::filesystem_info, scrub::scrub_progress,
5};
6use clap::Parser;
7use std::{fs::File, os::unix::io::AsFd, path::PathBuf};
8
9#[derive(Parser, Debug)]
11pub struct ScrubStatusCommand {
12 #[clap(long, short)]
14 pub device: bool,
15
16 pub path: PathBuf,
18}
19
20impl Runnable for ScrubStatusCommand {
21 fn run(&self, _format: Format, _dry_run: bool) -> Result<()> {
22 let file = File::open(&self.path).with_context(|| {
23 format!("failed to open '{}'", self.path.display())
24 })?;
25 let fd = file.as_fd();
26
27 let fs = filesystem_info(fd).with_context(|| {
28 format!(
29 "failed to get filesystem info for '{}'",
30 self.path.display()
31 )
32 })?;
33 let devices = device_info_all(fd, &fs).with_context(|| {
34 format!("failed to get device info for '{}'", self.path.display())
35 })?;
36
37 println!("UUID: {}", fs.uuid.as_hyphenated());
38
39 let mut any_running = false;
40 let mut fs_totals = btrfs_uapi::scrub::ScrubProgress::default();
41
42 for dev in &devices {
43 match scrub_progress(fd, dev.devid).with_context(|| {
44 format!("failed to get scrub progress for device {}", dev.devid)
45 })? {
46 None => {
47 if self.device {
48 println!(
49 "device {} ({}): no scrub in progress",
50 dev.devid, dev.path
51 );
52 }
53 }
54 Some(progress) => {
55 any_running = true;
56 super::accumulate(&mut fs_totals, &progress);
57 if self.device {
58 super::print_progress_summary(
59 &progress, dev.devid, &dev.path,
60 );
61 }
62 }
63 }
64 }
65
66 if !any_running {
67 println!("\tno scrub in progress");
68 } else if !self.device {
69 println!(
71 "Bytes scrubbed: {}",
72 human_bytes(fs_totals.bytes_scrubbed())
73 );
74 super::print_error_summary(&fs_totals);
75 }
76
77 Ok(())
78 }
79}