btrfs_cli/qgroup/
remove.rs1use crate::{
2 RunContext, Runnable,
3 util::{open_path, parse_qgroupid},
4};
5use anyhow::{Context, Result, bail};
6use clap::Parser;
7use nix::errno::Errno;
8use std::{os::unix::io::AsFd, path::PathBuf};
9
10#[derive(Parser, Debug)]
12pub struct QgroupRemoveCommand {
13 pub src: String,
15
16 pub dst: String,
18
19 pub path: PathBuf,
21
22 #[clap(long, conflicts_with = "no_rescan")]
24 pub rescan: bool,
25
26 #[clap(long)]
28 pub no_rescan: bool,
29}
30
31impl Runnable for QgroupRemoveCommand {
32 fn run(&self, _ctx: &RunContext) -> Result<()> {
33 let src = parse_qgroupid(&self.src)?;
34 let dst = parse_qgroupid(&self.dst)?;
35
36 let file = open_path(&self.path)?;
37 let fd = file.as_fd();
38
39 let needs_rescan = match btrfs_uapi::quota::qgroup_remove(fd, src, dst)
40 {
41 Ok(needs_rescan) => needs_rescan,
42 Err(Errno::ENOTCONN) => {
43 bail!("quota not enabled on '{}'", self.path.display())
44 }
45 Err(e) => {
46 return Err(e).with_context(|| {
47 format!(
48 "failed to remove qgroup relation '{}' from '{}' on '{}'",
49 self.src,
50 self.dst,
51 self.path.display()
52 )
53 });
54 }
55 };
56
57 let do_rescan = !self.no_rescan;
59
60 if needs_rescan {
61 if do_rescan {
62 btrfs_uapi::quota::quota_rescan(fd).with_context(|| {
63 format!(
64 "failed to schedule quota rescan on '{}'",
65 self.path.display()
66 )
67 })?;
68 println!("Quota data changed, rescan scheduled");
69 } else {
70 eprintln!(
71 "WARNING: quotas may be inconsistent, rescan needed on '{}'",
72 self.path.display()
73 );
74 }
75 }
76
77 Ok(())
78 }
79}