diff --git a/src/thin/dump.rs b/src/thin/dump.rs index 7127c16..2cbb019 100644 --- a/src/thin/dump.rs +++ b/src/thin/dump.rs @@ -316,7 +316,12 @@ pub fn dump(opts: ThinDumpOptions) -> Result<()> { let ctx = mk_context(&opts)?; let sb; if opts.repair { - sb = read_or_rebuild_superblock(ctx.engine.clone(), SUPERBLOCK_LOCATION, &opts.overrides)?; + sb = read_or_rebuild_superblock( + ctx.engine.clone(), + ctx.report.clone(), + SUPERBLOCK_LOCATION, + &opts.overrides, + )?; } else { sb = read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION)?; } diff --git a/src/thin/metadata_repair.rs b/src/thin/metadata_repair.rs index 43f095c..d96bafe 100644 --- a/src/thin/metadata_repair.rs +++ b/src/thin/metadata_repair.rs @@ -11,6 +11,7 @@ use crate::pdata::btree::*; use crate::pdata::btree_walker::*; use crate::pdata::space_map_common::*; use crate::pdata::unpack::Unpack; +use crate::report::Report; use crate::thin::block_time::*; use crate::thin::device_detail::*; use crate::thin::superblock::*; @@ -188,10 +189,11 @@ struct NodeCollector { examined: FixedBitSet, referenced: FixedBitSet, infos: BTreeMap, + report: Arc, } impl NodeCollector { - pub fn new(engine: Arc) -> NodeCollector { + pub fn new(engine: Arc, report: Arc) -> NodeCollector { let nr_blocks = engine.get_nr_blocks(); NodeCollector { engine, @@ -199,6 +201,7 @@ impl NodeCollector { examined: FixedBitSet::with_capacity(nr_blocks as usize), referenced: FixedBitSet::with_capacity(nr_blocks as usize), infos: BTreeMap::::new(), + report, } } @@ -663,10 +666,39 @@ impl NodeCollector { }) } + fn log_results(&self, dev_roots: &[u64], details_roots: &[u64], pairs: &[(u64, u64)]) { + self.report + .info(&format!("mapping candidates ({}):", dev_roots.len())); + for dev_root in dev_roots { + if let Ok(NodeInfo::Dev(info)) = self.read_info(*dev_root) { + self.report.info(&format!("b={}, nr_devices={}, nr_mappings={}, highest_mapped={}, age={}, time_counts={:?}", + info.b, info.nr_devices, info.nr_mappings, info.highest_mapped_data_block, info.age, info.time_counts)); + } + } + + self.report + .info(&format!("\ndevice candidates ({}):", details_roots.len())); + for details_root in details_roots { + if let Ok(NodeInfo::Details(info)) = self.read_info(*details_root) { + self.report.info(&format!( + "b={}, nr_devices={}, nr_mappings={}, max_tid={}, age={}", + info._b, info.nr_devices, info.nr_mappings, info.max_tid, info.age + )); + } + } + + self.report + .info(&format!("\ncompatible roots ({}):", pairs.len())); + for pair in pairs { + self.report.info(&format!("({}, {})", pair.0, pair.1)); + } + } + pub fn find_roots(mut self) -> Result { self.collect_infos()?; let (dev_roots, details_roots) = self.gather_roots()?; let pairs = self.find_root_pairs(&dev_roots, &details_roots)?; + self.log_results(&dev_roots, &details_roots, &pairs); if pairs.is_empty() { return Err(anyhow!("no compatible roots found")); @@ -720,6 +752,7 @@ pub fn is_superblock_consistent( pub fn rebuild_superblock( engine: Arc, + report: Arc, ref_sb: Option, opts: &SuperblockOverrides, ) -> Result { @@ -735,7 +768,7 @@ pub fn rebuild_superblock( }) .and_then(check_data_block_size)?; - let c = NodeCollector::new(engine.clone()); + let c = NodeCollector::new(engine.clone(), report); let roots = c.find_roots()?; let transaction_id = opts @@ -782,6 +815,7 @@ pub fn rebuild_superblock( pub fn read_or_rebuild_superblock( engine: Arc, + report: Arc, loc: u64, opts: &SuperblockOverrides, ) -> Result { @@ -791,7 +825,7 @@ pub fn read_or_rebuild_superblock( let ref_sb = e .downcast_ref::() .and_then(|err| err.failed_sb.clone()); - rebuild_superblock(engine, ref_sb, opts) + rebuild_superblock(engine, report, ref_sb, opts) }) } diff --git a/src/thin/repair.rs b/src/thin/repair.rs index dd5b996..c7ba02b 100644 --- a/src/thin/repair.rs +++ b/src/thin/repair.rs @@ -55,8 +55,12 @@ fn new_context(opts: &ThinRepairOptions) -> Result { pub fn repair(opts: ThinRepairOptions) -> Result<()> { let ctx = new_context(&opts)?; - let sb = - read_or_rebuild_superblock(ctx.engine_in.clone(), SUPERBLOCK_LOCATION, &opts.overrides)?; + let sb = read_or_rebuild_superblock( + ctx.engine_in.clone(), + ctx.report.clone(), + SUPERBLOCK_LOCATION, + &opts.overrides, + )?; let md = build_metadata(ctx.engine_in.clone(), &sb)?; let md = optimise_metadata(md)?;