From 8a822cebec8c52b6010f91872c5fe537aa3f4299 Mon Sep 17 00:00:00 2001 From: Ming-Hung Tsai Date: Tue, 24 Aug 2021 02:18:08 +0800 Subject: [PATCH] [thin_repair/thin_dump (rust)] Support rebuilding superblock --- src/bin/thin_dump.rs | 46 ++++++++++++++++++++++++++++++++++++++++ src/bin/thin_repair.rs | 48 +++++++++++++++++++++++++++++++++++++----- src/thin/dump.rs | 10 ++++++++- src/thin/repair.rs | 5 ++++- 4 files changed, 102 insertions(+), 7 deletions(-) diff --git a/src/bin/thin_dump.rs b/src/bin/thin_dump.rs index 7533961..4f6c07d 100644 --- a/src/bin/thin_dump.rs +++ b/src/bin/thin_dump.rs @@ -10,6 +10,7 @@ use std::sync::Arc; use thinp::file_utils; use thinp::report::*; use thinp::thin::dump::{dump, ThinDumpOptions}; +use thinp::thin::metadata_repair::SuperblockOverrides; fn main() { let parser = App::new("thin_dump") @@ -40,6 +41,12 @@ fn main() { .long("skip-mappings"), ) // options + .arg( + Arg::with_name("DATA_BLOCK_SIZE") + .help("Provide the data block size for repairing") + .long("data-block-size") + .value_name("SECTORS"), + ) .arg( Arg::with_name("METADATA_SNAPSHOT") .help("Access the metadata snapshot on a live pool") @@ -47,6 +54,12 @@ fn main() { .long("metadata-snapshot") .value_name("METADATA_SNAPSHOT"), ) + .arg( + Arg::with_name("NR_DATA_BLOCKS") + .help("Override the number of data blocks if needed") + .long("nr-data-blocks") + .value_name("NUM"), + ) .arg( Arg::with_name("OUTPUT") .help("Specify the output file rather than stdout") @@ -54,6 +67,12 @@ fn main() { .long("output") .value_name("FILE"), ) + .arg( + Arg::with_name("TRANSACTION_ID") + .help("Override the transaction id if needed") + .long("transaction-id") + .value_name("NUM"), + ) // arguments .arg( Arg::with_name("INPUT") @@ -75,6 +94,27 @@ fn main() { exit(1); } + let transaction_id = matches.value_of("TRANSACTION_ID").map(|s| { + s.parse::().unwrap_or_else(|_| { + eprintln!("Couldn't parse transaction_id"); + exit(1); + }) + }); + + let data_block_size = matches.value_of("DATA_BLOCK_SIZE").map(|s| { + s.parse::().unwrap_or_else(|_| { + eprintln!("Couldn't parse data_block_size"); + exit(1); + }) + }); + + let nr_data_blocks = matches.value_of("NR_DATA_BLOCKS").map(|s| { + s.parse::().unwrap_or_else(|_| { + eprintln!("Couldn't parse nr_data_blocks"); + exit(1); + }) + }); + let report; if matches.is_present("QUIET") { @@ -90,6 +130,12 @@ fn main() { output: output_file, async_io: matches.is_present("ASYNC_IO"), report, + repair: matches.is_present("REPAIR"), + overrides: SuperblockOverrides { + transaction_id, + data_block_size, + nr_data_blocks, + }, }; if let Err(reason) = dump(opts) { diff --git a/src/bin/thin_repair.rs b/src/bin/thin_repair.rs index 2cac56e..781cb31 100644 --- a/src/bin/thin_repair.rs +++ b/src/bin/thin_repair.rs @@ -9,6 +9,7 @@ use std::process::exit; use std::sync::Arc; use thinp::file_utils; use thinp::report::*; +use thinp::thin::metadata_repair::SuperblockOverrides; use thinp::thin::repair::{repair, ThinRepairOptions}; fn main() { @@ -29,6 +30,12 @@ fn main() { .long("quiet"), ) // options + .arg( + Arg::with_name("DATA_BLOCK_SIZE") + .help("Provide the data block size for repairing") + .long("data-block-size") + .value_name("SECTORS"), + ) .arg( Arg::with_name("INPUT") .help("Specify the input device") @@ -37,6 +44,12 @@ fn main() { .value_name("FILE") .required(true), ) + .arg( + Arg::with_name("NR_DATA_BLOCKS") + .help("Override the number of data blocks if needed") + .long("nr-data-blocks") + .value_name("NUM"), + ) .arg( Arg::with_name("OUTPUT") .help("Specify the output device") @@ -46,11 +59,10 @@ fn main() { .required(true), ) .arg( - Arg::with_name("OVERRIDE_MAPPING_ROOT") - .help("Specify a mapping root to use") - .long("override-mapping-root") - .value_name("OVERRIDE_MAPPING_ROOT") - .takes_value(true), + Arg::with_name("TRANSACTION_ID") + .help("Override the transaction id if needed") + .long("transaction-id") + .value_name("NUM"), ); let matches = parser.get_matches(); @@ -62,6 +74,27 @@ fn main() { exit(1); } + let transaction_id = matches.value_of("TRANSACTION_ID").map(|s| { + s.parse::().unwrap_or_else(|_| { + eprintln!("Couldn't parse transaction_id"); + exit(1); + }) + }); + + let data_block_size = matches.value_of("DATA_BLOCK_SIZE").map(|s| { + s.parse::().unwrap_or_else(|_| { + eprintln!("Couldn't parse data_block_size"); + exit(1); + }) + }); + + let nr_data_blocks = matches.value_of("NR_DATA_BLOCKS").map(|s| { + s.parse::().unwrap_or_else(|_| { + eprintln!("Couldn't parse nr_data_blocks"); + exit(1); + }) + }); + let report; if matches.is_present("QUIET") { @@ -77,6 +110,11 @@ fn main() { output: &output_file, async_io: matches.is_present("ASYNC_IO"), report, + overrides: SuperblockOverrides { + transaction_id, + data_block_size, + nr_data_blocks, + }, }; if let Err(reason) = repair(opts) { diff --git a/src/thin/dump.rs b/src/thin/dump.rs index f588c5d..7127c16 100644 --- a/src/thin/dump.rs +++ b/src/thin/dump.rs @@ -15,6 +15,7 @@ use crate::report::*; use crate::thin::block_time::*; use crate::thin::ir::{self, MetadataVisitor}; use crate::thin::metadata::*; +use crate::thin::metadata_repair::*; use crate::thin::superblock::*; use crate::thin::xml; @@ -147,6 +148,8 @@ pub struct ThinDumpOptions<'a> { pub output: Option<&'a Path>, pub async_io: bool, pub report: Arc, + pub repair: bool, + pub overrides: SuperblockOverrides, } struct Context { @@ -311,7 +314,12 @@ pub fn dump_metadata( pub fn dump(opts: ThinDumpOptions) -> Result<()> { let ctx = mk_context(&opts)?; - let sb = read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION)?; + let sb; + if opts.repair { + sb = read_or_rebuild_superblock(ctx.engine.clone(), SUPERBLOCK_LOCATION, &opts.overrides)?; + } else { + sb = read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION)?; + } let md = build_metadata(ctx.engine.clone(), &sb)?; ctx.report diff --git a/src/thin/repair.rs b/src/thin/repair.rs index 4f74371..dd5b996 100644 --- a/src/thin/repair.rs +++ b/src/thin/repair.rs @@ -7,6 +7,7 @@ use crate::pdata::space_map_metadata::*; use crate::report::*; use crate::thin::dump::*; use crate::thin::metadata::*; +use crate::thin::metadata_repair::*; use crate::thin::restore::*; use crate::thin::superblock::*; use crate::write_batcher::*; @@ -18,6 +19,7 @@ pub struct ThinRepairOptions<'a> { pub output: &'a Path, pub async_io: bool, pub report: Arc, + pub overrides: SuperblockOverrides, } struct Context { @@ -53,7 +55,8 @@ fn new_context(opts: &ThinRepairOptions) -> Result { pub fn repair(opts: ThinRepairOptions) -> Result<()> { let ctx = new_context(&opts)?; - let sb = read_superblock(ctx.engine_in.as_ref(), SUPERBLOCK_LOCATION)?; + let sb = + read_or_rebuild_superblock(ctx.engine_in.clone(), SUPERBLOCK_LOCATION, &opts.overrides)?; let md = build_metadata(ctx.engine_in.clone(), &sb)?; let md = optimise_metadata(md)?;