diff --git a/src/commands/thin_dump.rs b/src/commands/thin_dump.rs index 8380535fe..7d66b7f8c 100644 --- a/src/commands/thin_dump.rs +++ b/src/commands/thin_dump.rs @@ -8,6 +8,7 @@ use std::sync::Arc; use crate::commands::utils::*; use crate::commands::Command; +use crate::error::IoError; use crate::report::*; use crate::thin::dump::{dump, ThinDumpOptions}; use crate::thin::metadata_repair::SuperblockOverrides; @@ -128,13 +129,17 @@ impl<'a> Command<'a> for ThinDumpCommand { }, }; - dump(opts).map_err(|reason| { - report.fatal(&format!("{}", reason)); - report.fatal( - "metadata contains errors (run thin_check for details).\n\ - perhaps you wanted to run with --repair ?", - ); - std::io::Error::from_raw_os_error(libc::EPERM) - }) + if let Err(e) = dump(opts) { + if let IoError::Input(reason) = e { + report.fatal(&format!("{:?}", reason)); + report.fatal( + "metadata contains errors (run thin_check for details).\n\ + perhaps you wanted to run with --repair ?", + ); + } + return Err(std::io::Error::from_raw_os_error(libc::EPERM)); + } + + Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 8b6ef32cb..9239ff1ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ pub mod checksum; pub mod commands; pub mod copier; pub mod era; +pub mod error; pub mod file_utils; pub mod grid_layout; pub mod io_engine; diff --git a/src/shrink/toplevel.rs b/src/shrink/toplevel.rs index dfe280ed7..af059b1b3 100644 --- a/src/shrink/toplevel.rs +++ b/src/shrink/toplevel.rs @@ -543,7 +543,9 @@ fn rebuild_metadata(opts: ThinShrinkOptions) -> Result<()> { let mut w = WriteBatcher::new(output.clone(), sm, output.get_batch_size()); let mut restorer = Restorer::new(&mut w, opts.report); let mut remapper = DataRemapper::new(&mut restorer, opts.nr_blocks, remaps); - dump_metadata(input, &mut remapper, &sb, &md) + dump_metadata(input, &mut remapper, &sb, &md)?; + + Ok(()) } pub fn shrink(opts: ThinShrinkOptions) -> Result<()> { diff --git a/src/thin/dump.rs b/src/thin/dump.rs index 6a573d7db..29fbf25dc 100644 --- a/src/thin/dump.rs +++ b/src/thin/dump.rs @@ -6,6 +6,7 @@ use std::path::Path; use std::sync::{Arc, Mutex}; use crate::checksum; +use crate::error::*; use crate::io_engine::{AsyncIoEngine, Block, IoEngine, SyncIoEngine}; use crate::pdata::btree::{self, *}; use crate::pdata::btree_walker::*; @@ -205,16 +206,17 @@ fn emit_leaf(v: &mut MappingVisitor, b: &Block) -> Result<()> { Ok(()) } -fn read_for(engine: Arc, blocks: &[u64], mut t: T) -> Result<()> +fn read_for(engine: Arc, blocks: &[u64], mut t: T) -> Result<(), IoError> where T: FnMut(Block) -> Result<()>, { for cs in blocks.chunks(engine.get_batch_size()) { for b in engine .read_many(cs) - .map_err(|_e| anyhow!("read_many failed"))? + .map_err(|_e| IoError::Input(anyhow!("read_many failed")))? { - t(b.map_err(|_e| anyhow!("read of individual block failed"))?)?; + let blk = b.map_err(|_e| IoError::Input(anyhow!("read of individual block failed")))?; + t(blk).map_err(to_output_err)?; } } @@ -225,7 +227,7 @@ fn emit_leaves( engine: Arc, out: &mut dyn MetadataVisitor, leaves: &[u64], -) -> Result<()> { +) -> Result<(), IoError> { let mut v = MappingVisitor::new(out); let proc = |b| { emit_leaf(&mut v, &b)?; @@ -234,14 +236,14 @@ fn emit_leaves( read_for(engine, leaves, proc)?; v.end_walk() - .map_err(|e| anyhow!("failed to emit leaves: {}", e)) + .map_err(|e| IoError::Output(anyhow!("failed to emit leaves: {}", e))) } fn emit_entries( engine: Arc, out: &mut dyn MetadataVisitor, entries: &[Entry], -) -> Result<()> { +) -> Result<(), IoError> { let mut leaves = Vec::new(); for e in entries { @@ -255,7 +257,7 @@ fn emit_entries( leaves.clear(); } let str = format!("{}", id); - out.ref_shared(&str)?; + out.ref_shared(&str).map_err(to_output_err)?; } } } @@ -272,8 +274,9 @@ pub fn dump_metadata( out: &mut dyn MetadataVisitor, sb: &Superblock, md: &Metadata, -) -> Result<()> { - let data_root = unpack::(&sb.data_sm_root[0..])?; +) -> Result<(), IoError> { + let data_root = + unpack::(&sb.data_sm_root[0..]).map_err(|e| IoError::Input(e.into()))?; let out_sb = ir::Superblock { uuid: "".to_string(), time: sb.time, @@ -284,12 +287,13 @@ pub fn dump_metadata( nr_data_blocks: data_root.nr_blocks, metadata_snap: None, }; - out.superblock_b(&out_sb)?; + out.superblock_b(&out_sb).map_err(to_output_err)?; for d in &md.defs { - out.def_shared_b(&format!("{}", d.def_id))?; + out.def_shared_b(&format!("{}", d.def_id)) + .map_err(to_output_err)?; emit_entries(engine.clone(), out, &d.map.entries)?; - out.def_shared_e()?; + out.def_shared_e().map_err(to_output_err)?; } for dev in &md.devs { @@ -300,38 +304,42 @@ pub fn dump_metadata( creation_time: dev.detail.creation_time, snap_time: dev.detail.snapshotted_time, }; - out.device_b(&device)?; + out.device_b(&device).map_err(to_output_err)?; emit_entries(engine.clone(), out, &dev.map.entries)?; - out.device_e()?; + out.device_e().map_err(to_output_err)?; } - out.superblock_e()?; - out.eof()?; + out.superblock_e().map_err(to_output_err)?; + out.eof().map_err(to_output_err)?; Ok(()) } //------------------------------------------ -pub fn dump(opts: ThinDumpOptions) -> Result<()> { - let ctx = mk_context(&opts)?; +pub fn dump(opts: ThinDumpOptions) -> Result<(), IoError> { + let ctx = mk_context(&opts).map_err(to_input_err)?; let sb = if opts.repair { read_or_rebuild_superblock( ctx.engine.clone(), ctx.report.clone(), SUPERBLOCK_LOCATION, &opts.overrides, - )? + ) } else if opts.use_metadata_snap { - read_superblock_snap(ctx.engine.as_ref())? + read_superblock_snap(ctx.engine.as_ref()) } else { read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION) - .and_then(|sb| sb.overrides(&opts.overrides))? - }; - let md = build_metadata(ctx.engine.clone(), &sb)?; - let md = optimise_metadata(md)?; + .and_then(|sb| sb.overrides(&opts.overrides)) + } + .map_err(to_input_err)?; + + let md = build_metadata(ctx.engine.clone(), &sb).map_err(to_input_err)?; + let md = optimise_metadata(md).map_err(to_input_err)?; let writer: Box = if opts.output.is_some() { - Box::new(BufWriter::new(File::create(opts.output.unwrap())?)) + Box::new(BufWriter::new( + File::create(opts.output.unwrap()).map_err(|e| IoError::Output(e.into()))?, + )) } else { Box::new(BufWriter::new(std::io::stdout())) }; diff --git a/src/thin/repair.rs b/src/thin/repair.rs index c7ba02b6e..acb68f9bd 100644 --- a/src/thin/repair.rs +++ b/src/thin/repair.rs @@ -72,7 +72,9 @@ pub fn repair(opts: ThinRepairOptions) -> Result<()> { ); let mut restorer = Restorer::new(&mut w, ctx.report); - dump_metadata(ctx.engine_in, &mut restorer, &sb, &md) + dump_metadata(ctx.engine_in, &mut restorer, &sb, &md)?; + + Ok(()) } //------------------------------------------