btrfs_cli/quota/
rescan.rs1use crate::{Format, Runnable};
2use anyhow::{Context, Result};
3use clap::Parser;
4use nix::errno::Errno;
5use std::{fs::File, os::unix::io::AsFd, path::PathBuf};
6
7#[derive(Parser, Debug)]
9pub struct QuotaRescanCommand {
10 #[clap(short = 's', long, conflicts_with = "wait")]
12 pub status: bool,
13
14 #[clap(short = 'w', long)]
16 pub wait: bool,
17
18 #[clap(short = 'W', long)]
20 pub wait_norescan: bool,
21
22 pub path: PathBuf,
24}
25
26impl Runnable for QuotaRescanCommand {
27 fn run(&self, _format: Format, _dry_run: bool) -> Result<()> {
28 let file = File::open(&self.path).with_context(|| {
29 format!("failed to open '{}'", self.path.display())
30 })?;
31 let fd = file.as_fd();
32
33 if self.status {
34 let st = btrfs_uapi::quota::quota_rescan_status(fd).with_context(
35 || {
36 format!(
37 "failed to get quota rescan status on '{}'",
38 self.path.display()
39 )
40 },
41 )?;
42
43 if st.running {
44 println!(
45 "rescan operation running (current key {})",
46 st.progress
47 );
48 } else {
49 println!("no rescan operation in progress");
50 }
51
52 return Ok(());
53 }
54
55 if self.wait_norescan {
56 btrfs_uapi::quota::quota_rescan_wait(fd).with_context(|| {
58 format!(
59 "failed to wait for quota rescan on '{}'",
60 self.path.display()
61 )
62 })?;
63 return Ok(());
64 }
65
66 match btrfs_uapi::quota::quota_rescan(fd) {
69 Ok(()) => {
70 println!("quota rescan started");
71 }
72 Err(Errno::EINPROGRESS) if self.wait => {
73 }
75 Err(e) => {
76 return Err(e).with_context(|| {
77 format!(
78 "failed to start quota rescan on '{}'",
79 self.path.display()
80 )
81 });
82 }
83 }
84
85 if self.wait {
86 btrfs_uapi::quota::quota_rescan_wait(fd).with_context(|| {
87 format!(
88 "failed to wait for quota rescan on '{}'",
89 self.path.display()
90 )
91 })?;
92 }
93
94 Ok(())
95 }
96}