use crate::{RunContext, Runnable, util::open_path};
use anyhow::{Context, Result};
use clap::Parser;
use nix::errno::Errno;
use std::{os::unix::io::AsFd, path::PathBuf};
#[derive(Parser, Debug)]
pub struct QuotaRescanCommand {
#[clap(short = 's', long, conflicts_with = "wait")]
pub status: bool,
#[clap(short = 'w', long)]
pub wait: bool,
#[clap(short = 'W', long)]
pub wait_norescan: bool,
pub path: PathBuf,
}
impl Runnable for QuotaRescanCommand {
fn run(&self, _ctx: &RunContext) -> Result<()> {
let file = open_path(&self.path)?;
let fd = file.as_fd();
if self.status {
let st = btrfs_uapi::quota::quota_rescan_status(fd).with_context(
|| {
format!(
"failed to get quota rescan status on '{}'",
self.path.display()
)
},
)?;
if st.running {
println!(
"rescan operation running (current key {})",
st.progress
);
} else {
println!("no rescan operation in progress");
}
return Ok(());
}
if self.wait_norescan {
btrfs_uapi::quota::quota_rescan_wait(fd).with_context(|| {
format!(
"failed to wait for quota rescan on '{}'",
self.path.display()
)
})?;
return Ok(());
}
match btrfs_uapi::quota::quota_rescan(fd) {
Ok(()) => {
println!("quota rescan started");
}
Err(Errno::EINPROGRESS) if self.wait => {
}
Err(e) => {
return Err(e).with_context(|| {
format!(
"failed to start quota rescan on '{}'",
self.path.display()
)
});
}
}
if self.wait {
btrfs_uapi::quota::quota_rescan_wait(fd).with_context(|| {
format!(
"failed to wait for quota rescan on '{}'",
self.path.display()
)
})?;
}
Ok(())
}
}