Skip to main content

btrfs_cli/scrub/
resume.rs

1use crate::{Format, Runnable};
2use anyhow::{Context, Result};
3use btrfs_uapi::{
4    device::device_info_all, filesystem::filesystem_info, scrub::scrub_start,
5};
6use clap::Parser;
7use std::{fs::File, os::unix::io::AsFd, path::PathBuf};
8
9/// Resume a previously cancelled or interrupted scrub
10///
11/// Scrubs all devices sequentially. This command blocks until the scrub
12/// completes; use Ctrl-C to cancel.
13#[derive(Parser, Debug)]
14pub struct ScrubResumeCommand {
15    /// Read-only mode: check for errors but do not attempt repairs
16    #[clap(long, short)]
17    pub readonly: bool,
18
19    /// Path to a mounted btrfs filesystem or a device
20    pub path: PathBuf,
21}
22
23impl Runnable for ScrubResumeCommand {
24    fn run(&self, _format: Format, _dry_run: bool) -> Result<()> {
25        // Resume uses the same ioctl as start; the kernel tracks where it left
26        // off via the scrub state on disk.
27        let file = File::open(&self.path).with_context(|| {
28            format!("failed to open '{}'", self.path.display())
29        })?;
30        let fd = file.as_fd();
31
32        let fs = filesystem_info(fd).with_context(|| {
33            format!(
34                "failed to get filesystem info for '{}'",
35                self.path.display()
36            )
37        })?;
38        let devices = device_info_all(fd, &fs).with_context(|| {
39            format!("failed to get device info for '{}'", self.path.display())
40        })?;
41
42        println!("UUID: {}", fs.uuid.as_hyphenated());
43
44        for dev in &devices {
45            println!("resuming scrub on device {} ({})", dev.devid, dev.path);
46
47            match scrub_start(fd, dev.devid, self.readonly) {
48                Ok(progress) => {
49                    super::print_progress_summary(
50                        &progress, dev.devid, &dev.path,
51                    );
52                }
53                Err(e) => {
54                    eprintln!(
55                        "error resuming scrub on device {}: {e}",
56                        dev.devid
57                    );
58                }
59            }
60        }
61
62        Ok(())
63    }
64}