Skip to main content

btrfs_cli/quota/
status.rs

1use crate::{Format, Runnable, util::open_path};
2use anyhow::{Context, Result};
3use btrfs_uapi::sysfs::SysfsBtrfs;
4use clap::Parser;
5use std::{os::unix::io::AsFd, path::PathBuf};
6
7/// Show status information about quota on the filesystem
8#[derive(Parser, Debug)]
9pub struct QuotaStatusCommand {
10    /// Path to a mounted btrfs filesystem
11    pub path: PathBuf,
12
13    /// Only check if quotas are enabled, without printing full status
14    #[clap(long)]
15    pub is_enabled: bool,
16}
17
18fn describe_mode(mode: &str) -> &str {
19    match mode {
20        "qgroup" => "full accounting",
21        "squota" => "simplified accounting",
22        other => other,
23    }
24}
25
26impl Runnable for QuotaStatusCommand {
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        let fs =
32            btrfs_uapi::filesystem::filesystem_info(fd).with_context(|| {
33                format!(
34                    "failed to get filesystem info for '{}'",
35                    self.path.display()
36                )
37            })?;
38
39        let status =
40            SysfsBtrfs::new(&fs.uuid).quota_status().with_context(|| {
41                format!(
42                    "failed to read quota status for '{}'",
43                    self.path.display()
44                )
45            })?;
46
47        if self.is_enabled {
48            if !status.enabled {
49                // Exit with a non-zero code the way the C tool does, without
50                // printing anything.
51                std::process::exit(1);
52            }
53            return Ok(());
54        }
55
56        println!("Quotas on {}:", self.path.display());
57
58        if !status.enabled {
59            println!("  Enabled:                 no");
60            return Ok(());
61        }
62
63        println!("  Enabled:                 yes");
64
65        if let Some(ref mode) = status.mode {
66            println!(
67                "  Mode:                    {} ({})",
68                mode,
69                describe_mode(mode)
70            );
71        }
72
73        if let Some(inconsistent) = status.inconsistent {
74            println!(
75                "  Inconsistent:            {}{}",
76                if inconsistent { "yes" } else { "no" },
77                if inconsistent { " (rescan needed)" } else { "" }
78            );
79        }
80
81        if let Some(override_limits) = status.override_limits {
82            println!(
83                "  Override limits:         {}",
84                if override_limits { "yes" } else { "no" }
85            );
86        }
87
88        if let Some(threshold) = status.drop_subtree_threshold {
89            println!("  Drop subtree threshold:  {}", threshold);
90        }
91
92        if let Some(total) = status.total_count {
93            println!("  Total count:             {}", total);
94        }
95
96        if let Some(level0) = status.level0_count {
97            println!("  Level 0:                 {}", level0);
98        }
99
100        Ok(())
101    }
102}