btrfs_cli/quota/
rescan.rs1use crate::{Format, Runnable, util::open_path};
2use anyhow::{Context, Result};
3use clap::Parser;
4use nix::errno::Errno;
5use std::{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 = open_path(&self.path)?;
29 let fd = file.as_fd();
30
31 if self.status {
32 let st = btrfs_uapi::quota::quota_rescan_status(fd).with_context(
33 || {
34 format!(
35 "failed to get quota rescan status on '{}'",
36 self.path.display()
37 )
38 },
39 )?;
40
41 if st.running {
42 println!(
43 "rescan operation running (current key {})",
44 st.progress
45 );
46 } else {
47 println!("no rescan operation in progress");
48 }
49
50 return Ok(());
51 }
52
53 if self.wait_norescan {
54 btrfs_uapi::quota::quota_rescan_wait(fd).with_context(|| {
56 format!(
57 "failed to wait for quota rescan on '{}'",
58 self.path.display()
59 )
60 })?;
61 return Ok(());
62 }
63
64 match btrfs_uapi::quota::quota_rescan(fd) {
67 Ok(()) => {
68 println!("quota rescan started");
69 }
70 Err(Errno::EINPROGRESS) if self.wait => {
71 }
73 Err(e) => {
74 return Err(e).with_context(|| {
75 format!(
76 "failed to start quota rescan on '{}'",
77 self.path.display()
78 )
79 });
80 }
81 }
82
83 if self.wait {
84 btrfs_uapi::quota::quota_rescan_wait(fd).with_context(|| {
85 format!(
86 "failed to wait for quota rescan on '{}'",
87 self.path.display()
88 )
89 })?;
90 }
91
92 Ok(())
93 }
94}