3 use bch_bindgen::bcachefs;
4 use bch_bindgen::opt_set;
5 use bch_bindgen::fs::Fs;
6 use bch_bindgen::bkey::BkeySC;
7 use bch_bindgen::btree::BtreeTrans;
8 use bch_bindgen::btree::BtreeIter;
9 use bch_bindgen::btree::BtreeNodeIter;
10 use bch_bindgen::btree::BtreeIterFlags;
13 fn list_keys(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
14 let trans = BtreeTrans::new(fs);
15 let mut iter = BtreeIter::new(&trans, opt.btree, opt.start,
16 BtreeIterFlags::ALL_SNAPSHOTS|
17 BtreeIterFlags::PREFETCH);
19 while let Some(k) = iter.peek_and_restart()? {
24 println!("{}", k.to_text(fs));
31 fn list_btree_formats(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
32 let trans = BtreeTrans::new(fs);
33 let mut iter = BtreeNodeIter::new(&trans, opt.btree, opt.start,
35 BtreeIterFlags::PREFETCH);
37 while let Some(b) = iter.peek_and_restart()? {
38 if b.key.k.p > opt.end {
42 println!("{}", b.to_text(fs));
49 fn list_btree_nodes(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
50 let trans = BtreeTrans::new(fs);
51 let mut iter = BtreeNodeIter::new(&trans, opt.btree, opt.start,
53 BtreeIterFlags::PREFETCH);
55 while let Some(b) = iter.peek_and_restart()? {
56 if b.key.k.p > opt.end {
60 println!("{}", BkeySC::from(&b.key).to_text(fs));
67 fn list_nodes_ondisk(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
68 let trans = BtreeTrans::new(fs);
69 let mut iter = BtreeNodeIter::new(&trans, opt.btree, opt.start,
71 BtreeIterFlags::PREFETCH);
73 while let Some(b) = iter.peek_and_restart()? {
74 if b.key.k.p > opt.end {
78 println!("{}", b.ondisk_to_text(fs));
85 #[derive(Clone, clap::ValueEnum, Debug)]
93 /// List filesystem metadata in textual form
94 #[derive(Parser, Debug)]
96 /// Btree to list from
97 #[arg(short, long, default_value_t=bcachefs::btree_id::BTREE_ID_extents)]
98 btree: bcachefs::btree_id,
100 /// Btree depth to descend to (0 == leaves)
101 #[arg(short, long, default_value_t=0)]
104 /// Start position to list from
105 #[arg(short, long, default_value="POS_MIN")]
106 start: bcachefs::bpos,
109 #[arg(short, long, default_value="SPOS_MAX")]
112 #[arg(short, long, default_value="keys")]
115 /// Check (fsck) the filesystem first
116 #[arg(short, long, default_value_t=false)]
119 /// Force color on/off. Default: autodetect tty
120 #[arg(short, long, action = clap::ArgAction::Set, default_value_t=atty::is(Stream::Stdout))]
127 #[arg(required(true))]
128 devices: Vec<std::path::PathBuf>,
131 fn cmd_list_inner(opt: Cli) -> anyhow::Result<()> {
132 let mut fs_opts: bcachefs::bch_opts = Default::default();
134 opt_set!(fs_opts, nochanges, 1);
135 opt_set!(fs_opts, read_only, 1);
136 opt_set!(fs_opts, norecovery, 1);
137 opt_set!(fs_opts, degraded, 1);
138 opt_set!(fs_opts, errors, bcachefs::bch_error_actions::BCH_ON_ERROR_continue as u8);
141 opt_set!(fs_opts, fix_errors, bcachefs::fsck_err_opts::FSCK_FIX_yes as u8);
142 opt_set!(fs_opts, norecovery, 0);
146 opt_set!(fs_opts, verbose, 1);
149 let fs = Fs::open(&opt.devices, fs_opts)?;
152 Mode::Keys => list_keys(&fs, opt),
153 Mode::Formats => list_btree_formats(&fs, opt),
154 Mode::Nodes => list_btree_nodes(&fs, opt),
155 Mode::NodesOndisk => list_nodes_ondisk(&fs, opt),
159 pub fn cmd_list(argv: Vec<String>) -> i32 {
160 let opt = Cli::parse_from(argv);
161 colored::control::set_override(opt.colorize);
162 if let Err(e) = cmd_list_inner(opt) {
163 error!("Fatal error: {}", e);