btrfs_cli/scrub/
resume.rs1use crate::{
2 Format, Runnable,
3 util::{SizeFormat, open_path},
4};
5use anyhow::{Context, Result};
6use btrfs_uapi::{
7 device::device_info_all, filesystem::filesystem_info, scrub::scrub_start,
8};
9use clap::Parser;
10use std::{os::unix::io::AsFd, path::PathBuf};
11
12#[derive(Parser, Debug)]
17pub struct ScrubResumeCommand {
18 #[clap(short = 'B')]
20 pub no_background: bool,
21
22 #[clap(long, short)]
24 pub device: bool,
25
26 #[clap(long, short)]
28 pub readonly: bool,
29
30 #[clap(short = 'R')]
32 pub raw: bool,
33
34 #[clap(short = 'c', value_name = "CLASS")]
36 pub ioprio_class: Option<i32>,
37
38 #[clap(short = 'n', value_name = "CDATA")]
40 pub ioprio_classdata: Option<i32>,
41
42 pub path: PathBuf,
44}
45
46impl Runnable for ScrubResumeCommand {
47 fn run(&self, _format: Format, _dry_run: bool) -> Result<()> {
48 let file = open_path(&self.path)?;
51 let fd = file.as_fd();
52
53 let fs = filesystem_info(fd).with_context(|| {
54 format!(
55 "failed to get filesystem info for '{}'",
56 self.path.display()
57 )
58 })?;
59 let devices = device_info_all(fd, &fs).with_context(|| {
60 format!("failed to get device info for '{}'", self.path.display())
61 })?;
62
63 if self.ioprio_class.is_some() || self.ioprio_classdata.is_some() {
64 super::set_ioprio(
65 self.ioprio_class.unwrap_or(3), self.ioprio_classdata.unwrap_or(0),
67 );
68 }
69
70 println!("UUID: {}", fs.uuid.as_hyphenated());
71
72 let mode = SizeFormat::HumanIec;
73 let mut fs_totals = btrfs_uapi::scrub::ScrubProgress::default();
74
75 for dev in &devices {
76 println!("resuming scrub on device {} ({})", dev.devid, dev.path);
77
78 match scrub_start(fd, dev.devid, self.readonly) {
79 Ok(progress) => {
80 super::accumulate(&mut fs_totals, &progress);
81 if self.device {
82 super::print_device_progress(
83 &progress, dev.devid, &dev.path, self.raw, &mode,
84 );
85 }
86 }
87 Err(e) => {
88 eprintln!(
89 "error resuming scrub on device {}: {e}",
90 dev.devid
91 );
92 }
93 }
94 }
95
96 if !self.device {
97 if self.raw {
98 super::print_raw_progress(&fs_totals, 0, "filesystem totals");
99 } else {
100 super::print_error_summary(&fs_totals);
101 }
102 } else if devices.len() > 1 {
103 println!("\nFilesystem totals:");
104 if self.raw {
105 super::print_raw_progress(&fs_totals, 0, "filesystem totals");
106 } else {
107 super::print_error_summary(&fs_totals);
108 }
109 }
110
111 Ok(())
112 }
113}