[thin_repair/thin_dump (rust)] Support rebuilding superblock

This commit is contained in:
Ming-Hung Tsai 2021-08-24 02:18:08 +08:00
parent 213442bffd
commit 8a822cebec
4 changed files with 102 additions and 7 deletions

View File

@ -10,6 +10,7 @@ use std::sync::Arc;
use thinp::file_utils; use thinp::file_utils;
use thinp::report::*; use thinp::report::*;
use thinp::thin::dump::{dump, ThinDumpOptions}; use thinp::thin::dump::{dump, ThinDumpOptions};
use thinp::thin::metadata_repair::SuperblockOverrides;
fn main() { fn main() {
let parser = App::new("thin_dump") let parser = App::new("thin_dump")
@ -40,6 +41,12 @@ fn main() {
.long("skip-mappings"), .long("skip-mappings"),
) )
// options // 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(
Arg::with_name("METADATA_SNAPSHOT") Arg::with_name("METADATA_SNAPSHOT")
.help("Access the metadata snapshot on a live pool") .help("Access the metadata snapshot on a live pool")
@ -47,6 +54,12 @@ fn main() {
.long("metadata-snapshot") .long("metadata-snapshot")
.value_name("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(
Arg::with_name("OUTPUT") Arg::with_name("OUTPUT")
.help("Specify the output file rather than stdout") .help("Specify the output file rather than stdout")
@ -54,6 +67,12 @@ fn main() {
.long("output") .long("output")
.value_name("FILE"), .value_name("FILE"),
) )
.arg(
Arg::with_name("TRANSACTION_ID")
.help("Override the transaction id if needed")
.long("transaction-id")
.value_name("NUM"),
)
// arguments // arguments
.arg( .arg(
Arg::with_name("INPUT") Arg::with_name("INPUT")
@ -75,6 +94,27 @@ fn main() {
exit(1); exit(1);
} }
let transaction_id = matches.value_of("TRANSACTION_ID").map(|s| {
s.parse::<u64>().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::<u32>().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::<u64>().unwrap_or_else(|_| {
eprintln!("Couldn't parse nr_data_blocks");
exit(1);
})
});
let report; let report;
if matches.is_present("QUIET") { if matches.is_present("QUIET") {
@ -90,6 +130,12 @@ fn main() {
output: output_file, output: output_file,
async_io: matches.is_present("ASYNC_IO"), async_io: matches.is_present("ASYNC_IO"),
report, report,
repair: matches.is_present("REPAIR"),
overrides: SuperblockOverrides {
transaction_id,
data_block_size,
nr_data_blocks,
},
}; };
if let Err(reason) = dump(opts) { if let Err(reason) = dump(opts) {

View File

@ -9,6 +9,7 @@ use std::process::exit;
use std::sync::Arc; use std::sync::Arc;
use thinp::file_utils; use thinp::file_utils;
use thinp::report::*; use thinp::report::*;
use thinp::thin::metadata_repair::SuperblockOverrides;
use thinp::thin::repair::{repair, ThinRepairOptions}; use thinp::thin::repair::{repair, ThinRepairOptions};
fn main() { fn main() {
@ -29,6 +30,12 @@ fn main() {
.long("quiet"), .long("quiet"),
) )
// options // 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(
Arg::with_name("INPUT") Arg::with_name("INPUT")
.help("Specify the input device") .help("Specify the input device")
@ -37,6 +44,12 @@ fn main() {
.value_name("FILE") .value_name("FILE")
.required(true), .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(
Arg::with_name("OUTPUT") Arg::with_name("OUTPUT")
.help("Specify the output device") .help("Specify the output device")
@ -46,11 +59,10 @@ fn main() {
.required(true), .required(true),
) )
.arg( .arg(
Arg::with_name("OVERRIDE_MAPPING_ROOT") Arg::with_name("TRANSACTION_ID")
.help("Specify a mapping root to use") .help("Override the transaction id if needed")
.long("override-mapping-root") .long("transaction-id")
.value_name("OVERRIDE_MAPPING_ROOT") .value_name("NUM"),
.takes_value(true),
); );
let matches = parser.get_matches(); let matches = parser.get_matches();
@ -62,6 +74,27 @@ fn main() {
exit(1); exit(1);
} }
let transaction_id = matches.value_of("TRANSACTION_ID").map(|s| {
s.parse::<u64>().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::<u32>().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::<u64>().unwrap_or_else(|_| {
eprintln!("Couldn't parse nr_data_blocks");
exit(1);
})
});
let report; let report;
if matches.is_present("QUIET") { if matches.is_present("QUIET") {
@ -77,6 +110,11 @@ fn main() {
output: &output_file, output: &output_file,
async_io: matches.is_present("ASYNC_IO"), async_io: matches.is_present("ASYNC_IO"),
report, report,
overrides: SuperblockOverrides {
transaction_id,
data_block_size,
nr_data_blocks,
},
}; };
if let Err(reason) = repair(opts) { if let Err(reason) = repair(opts) {

View File

@ -15,6 +15,7 @@ use crate::report::*;
use crate::thin::block_time::*; use crate::thin::block_time::*;
use crate::thin::ir::{self, MetadataVisitor}; use crate::thin::ir::{self, MetadataVisitor};
use crate::thin::metadata::*; use crate::thin::metadata::*;
use crate::thin::metadata_repair::*;
use crate::thin::superblock::*; use crate::thin::superblock::*;
use crate::thin::xml; use crate::thin::xml;
@ -147,6 +148,8 @@ pub struct ThinDumpOptions<'a> {
pub output: Option<&'a Path>, pub output: Option<&'a Path>,
pub async_io: bool, pub async_io: bool,
pub report: Arc<Report>, pub report: Arc<Report>,
pub repair: bool,
pub overrides: SuperblockOverrides,
} }
struct Context { struct Context {
@ -311,7 +314,12 @@ pub fn dump_metadata(
pub fn dump(opts: ThinDumpOptions) -> Result<()> { pub fn dump(opts: ThinDumpOptions) -> Result<()> {
let ctx = mk_context(&opts)?; 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)?; let md = build_metadata(ctx.engine.clone(), &sb)?;
ctx.report ctx.report

View File

@ -7,6 +7,7 @@ use crate::pdata::space_map_metadata::*;
use crate::report::*; use crate::report::*;
use crate::thin::dump::*; use crate::thin::dump::*;
use crate::thin::metadata::*; use crate::thin::metadata::*;
use crate::thin::metadata_repair::*;
use crate::thin::restore::*; use crate::thin::restore::*;
use crate::thin::superblock::*; use crate::thin::superblock::*;
use crate::write_batcher::*; use crate::write_batcher::*;
@ -18,6 +19,7 @@ pub struct ThinRepairOptions<'a> {
pub output: &'a Path, pub output: &'a Path,
pub async_io: bool, pub async_io: bool,
pub report: Arc<Report>, pub report: Arc<Report>,
pub overrides: SuperblockOverrides,
} }
struct Context { struct Context {
@ -53,7 +55,8 @@ fn new_context(opts: &ThinRepairOptions) -> Result<Context> {
pub fn repair(opts: ThinRepairOptions) -> Result<()> { pub fn repair(opts: ThinRepairOptions) -> Result<()> {
let ctx = new_context(&opts)?; 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 = build_metadata(ctx.engine_in.clone(), &sb)?;
let md = optimise_metadata(md)?; let md = optimise_metadata(md)?;