btrfs_cli/scrub/
resume.rs1use crate::{
2 RunContext, 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)]
17#[allow(clippy::struct_excessive_bools)]
18pub struct ScrubResumeCommand {
19 #[clap(short = 'B')]
21 pub no_background: bool,
22
23 #[clap(long, short)]
25 pub device: bool,
26
27 #[clap(long, short)]
29 pub readonly: bool,
30
31 #[clap(short = 'R')]
33 pub raw: bool,
34
35 #[clap(short = 'c', value_name = "CLASS")]
37 pub ioprio_class: Option<i32>,
38
39 #[clap(short = 'n', value_name = "CDATA")]
41 pub ioprio_classdata: Option<i32>,
42
43 pub path: PathBuf,
45}
46
47impl Runnable for ScrubResumeCommand {
48 fn run(&self, _ctx: &RunContext) -> Result<()> {
49 let file = open_path(&self.path)?;
52 let fd = file.as_fd();
53
54 let fs = filesystem_info(fd).with_context(|| {
55 format!(
56 "failed to get filesystem info for '{}'",
57 self.path.display()
58 )
59 })?;
60 let devices = device_info_all(fd, &fs).with_context(|| {
61 format!("failed to get device info for '{}'", self.path.display())
62 })?;
63
64 if self.ioprio_class.is_some() || self.ioprio_classdata.is_some() {
65 super::set_ioprio(
66 self.ioprio_class.unwrap_or(3), self.ioprio_classdata.unwrap_or(0),
68 );
69 }
70
71 println!("UUID: {}", fs.uuid.as_hyphenated());
72
73 let mode = SizeFormat::HumanIec;
74 let mut fs_totals = btrfs_uapi::scrub::ScrubProgress::default();
75
76 for dev in &devices {
77 println!("resuming scrub on device {} ({})", dev.devid, dev.path);
78
79 match scrub_start(fd, dev.devid, self.readonly) {
80 Ok(progress) => {
81 super::accumulate(&mut fs_totals, &progress);
82 if self.device {
83 super::print_device_progress(
84 &progress, dev.devid, &dev.path, self.raw, &mode,
85 );
86 }
87 }
88 Err(e) => {
89 eprintln!(
90 "error resuming scrub on device {}: {e}",
91 dev.devid
92 );
93 }
94 }
95 }
96
97 if !self.device {
98 if self.raw {
99 super::print_raw_progress(&fs_totals, 0, "filesystem totals");
100 } else {
101 super::print_error_summary(&fs_totals);
102 }
103 } else if devices.len() > 1 {
104 println!("\nFilesystem totals:");
105 if self.raw {
106 super::print_raw_progress(&fs_totals, 0, "filesystem totals");
107 } else {
108 super::print_error_summary(&fs_totals);
109 }
110 }
111
112 Ok(())
113 }
114}