[thin/cache_dump (rust)] Add buffered outputs, and fix command line options
This commit is contained in:
parent
c71132c056
commit
7daff7350a
@ -10,24 +10,38 @@ use thinp::cache::dump::{dump, CacheDumpOptions};
|
||||
fn main() {
|
||||
let parser = App::new("cache_dump")
|
||||
.version(thinp::version::tools_version())
|
||||
.arg(
|
||||
Arg::with_name("INPUT")
|
||||
.help("Specify the input device to check")
|
||||
.required(true)
|
||||
.index(1),
|
||||
)
|
||||
.about("Dump the cache metadata to stdout in XML format")
|
||||
.arg(
|
||||
Arg::with_name("REPAIR")
|
||||
.help("")
|
||||
.long("repair")
|
||||
.value_name("REPAIR"),
|
||||
.help("Repair the metadata whilst dumping it")
|
||||
.short("r")
|
||||
.long("repair"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("OUTPUT")
|
||||
.help("Specify the output file rather than stdout")
|
||||
.short("o")
|
||||
.long("output")
|
||||
.value_name("OUTPUT"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("INPUT")
|
||||
.help("Specify the input device to dump")
|
||||
.required(true)
|
||||
.index(1),
|
||||
);
|
||||
|
||||
let matches = parser.get_matches();
|
||||
let input_file = Path::new(matches.value_of("INPUT").unwrap());
|
||||
let output_file = if matches.is_present("OUTPUT") {
|
||||
Some(Path::new(matches.value_of("OUTPUT").unwrap()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let opts = CacheDumpOptions {
|
||||
dev: &input_file,
|
||||
input: input_file,
|
||||
output: output_file,
|
||||
async_io: false,
|
||||
repair: matches.is_present("REPAIR"),
|
||||
};
|
||||
|
@ -12,9 +12,9 @@ use thinp::report::*;
|
||||
use thinp::thin::dump::{dump, ThinDumpOptions};
|
||||
|
||||
fn main() {
|
||||
let parser = App::new("thin_check")
|
||||
let parser = App::new("thin_dump")
|
||||
.version(thinp::version::tools_version())
|
||||
.about("Validates thin provisioning metadata on a device or file.")
|
||||
.about("Dump thin-provisioning metadata to stdout in XML format")
|
||||
.arg(
|
||||
Arg::with_name("QUIET")
|
||||
.help("Suppress output messages, return only exit code.")
|
||||
@ -22,60 +22,49 @@ fn main() {
|
||||
.long("quiet"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("SB_ONLY")
|
||||
.help("Only check the superblock.")
|
||||
.long("super-block-only")
|
||||
.value_name("SB_ONLY"),
|
||||
Arg::with_name("REPAIR")
|
||||
.help("Repair the metadata whilst dumping it")
|
||||
.short("r")
|
||||
.long("repair"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("SKIP_MAPPINGS")
|
||||
.help("Don't check the mapping tree")
|
||||
.long("skip-mappings")
|
||||
.value_name("SKIP_MAPPINGS"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("AUTO_REPAIR")
|
||||
.help("Auto repair trivial issues.")
|
||||
.long("auto-repair"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("IGNORE_NON_FATAL")
|
||||
.help("Only return a non-zero exit code if a fatal error is found.")
|
||||
.long("ignore-non-fatal-errors"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("CLEAR_NEEDS_CHECK")
|
||||
.help("Clears the 'needs_check' flag in the superblock")
|
||||
.long("clear-needs-check"),
|
||||
)
|
||||
.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(
|
||||
Arg::with_name("METADATA_SNAPSHOT")
|
||||
.help("Check the metadata snapshot on a live pool")
|
||||
.short("m")
|
||||
.long("metadata-snapshot")
|
||||
.value_name("METADATA_SNAPSHOT"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("INPUT")
|
||||
.help("Specify the input device to check")
|
||||
.required(true)
|
||||
.index(1),
|
||||
.help("Do not dump the mappings")
|
||||
.long("skip-mappings"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("SYNC_IO")
|
||||
.help("Force use of synchronous io")
|
||||
.long("sync-io"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("METADATA_SNAPSHOT")
|
||||
.help("Access the metadata snapshot on a live pool")
|
||||
.short("m")
|
||||
.long("metadata-snapshot")
|
||||
.value_name("METADATA_SNAPSHOT"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("OUTPUT")
|
||||
.help("Specify the output file rather than stdout")
|
||||
.short("o")
|
||||
.long("output")
|
||||
.value_name("OUTPUT"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("INPUT")
|
||||
.help("Specify the input device to dump")
|
||||
.required(true)
|
||||
.index(1),
|
||||
);
|
||||
|
||||
let matches = parser.get_matches();
|
||||
let input_file = Path::new(matches.value_of("INPUT").unwrap());
|
||||
let output_file = if matches.is_present("OUTPUT") {
|
||||
Some(Path::new(matches.value_of("OUTPUT").unwrap()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if !file_utils::file_exists(input_file) {
|
||||
eprintln!("Couldn't find input file '{:?}'.", &input_file);
|
||||
@ -93,7 +82,8 @@ fn main() {
|
||||
}
|
||||
|
||||
let opts = ThinDumpOptions {
|
||||
dev: &input_file,
|
||||
input: input_file,
|
||||
output: output_file,
|
||||
async_io: !matches.is_present("SYNC_IO"),
|
||||
report,
|
||||
};
|
||||
|
29
src/cache/dump.rs
vendored
29
src/cache/dump.rs
vendored
@ -1,5 +1,8 @@
|
||||
use anyhow::anyhow;
|
||||
use fixedbitset::FixedBitSet;
|
||||
use std::fs::File;
|
||||
use std::io::BufWriter;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@ -191,7 +194,8 @@ impl<'a> ArrayVisitor<Hint> for HintEmitter<'a> {
|
||||
//------------------------------------------
|
||||
|
||||
pub struct CacheDumpOptions<'a> {
|
||||
pub dev: &'a Path,
|
||||
pub input: &'a Path,
|
||||
pub output: Option<&'a Path>,
|
||||
pub async_io: bool,
|
||||
pub repair: bool,
|
||||
}
|
||||
@ -204,19 +208,24 @@ fn mk_context(opts: &CacheDumpOptions) -> anyhow::Result<Context> {
|
||||
let engine: Arc<dyn IoEngine + Send + Sync>;
|
||||
|
||||
if opts.async_io {
|
||||
engine = Arc::new(AsyncIoEngine::new(opts.dev, MAX_CONCURRENT_IO, false)?);
|
||||
engine = Arc::new(AsyncIoEngine::new(opts.input, MAX_CONCURRENT_IO, false)?);
|
||||
} else {
|
||||
let nr_threads = std::cmp::max(8, num_cpus::get() * 2);
|
||||
engine = Arc::new(SyncIoEngine::new(opts.dev, nr_threads, false)?);
|
||||
engine = Arc::new(SyncIoEngine::new(opts.input, nr_threads, false)?);
|
||||
}
|
||||
|
||||
Ok(Context { engine })
|
||||
}
|
||||
|
||||
fn dump_metadata(ctx: &Context, sb: &Superblock, _repair: bool) -> anyhow::Result<()> {
|
||||
fn dump_metadata(
|
||||
ctx: &Context,
|
||||
w: &mut dyn Write,
|
||||
sb: &Superblock,
|
||||
_repair: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
let engine = &ctx.engine;
|
||||
|
||||
let mut out = xml::XmlWriter::new(std::io::stdout());
|
||||
let mut out = xml::XmlWriter::new(w);
|
||||
let xml_sb = xml::Superblock {
|
||||
uuid: "".to_string(),
|
||||
block_size: sb.data_block_size,
|
||||
@ -272,6 +281,7 @@ fn dump_metadata(ctx: &Context, sb: &Superblock, _repair: bool) -> anyhow::Resul
|
||||
out.hints_e()?;
|
||||
|
||||
out.superblock_e()?;
|
||||
out.eof()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -281,7 +291,14 @@ pub fn dump(opts: CacheDumpOptions) -> anyhow::Result<()> {
|
||||
let engine = &ctx.engine;
|
||||
let sb = read_superblock(engine.as_ref(), SUPERBLOCK_LOCATION)?;
|
||||
|
||||
dump_metadata(&ctx, &sb, opts.repair)
|
||||
let mut writer: Box<dyn Write>;
|
||||
if opts.output.is_some() {
|
||||
writer = Box::new(BufWriter::new(File::create(opts.output.unwrap())?));
|
||||
} else {
|
||||
writer = Box::new(BufWriter::new(std::io::stdout()));
|
||||
}
|
||||
|
||||
dump_metadata(&ctx, &mut writer, &sb, opts.repair)
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
|
@ -1,5 +1,7 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fs::File;
|
||||
use std::io::BufWriter;
|
||||
use std::io::Write;
|
||||
use std::ops::DerefMut;
|
||||
use std::path::Path;
|
||||
@ -145,7 +147,8 @@ impl<'a> NodeVisitor<BlockTime> for MappingVisitor<'a> {
|
||||
const MAX_CONCURRENT_IO: u32 = 1024;
|
||||
|
||||
pub struct ThinDumpOptions<'a> {
|
||||
pub dev: &'a Path,
|
||||
pub input: &'a Path,
|
||||
pub output: Option<&'a Path>,
|
||||
pub async_io: bool,
|
||||
pub report: Arc<Report>,
|
||||
}
|
||||
@ -159,10 +162,10 @@ fn mk_context(opts: &ThinDumpOptions) -> Result<Context> {
|
||||
let engine: Arc<dyn IoEngine + Send + Sync>;
|
||||
|
||||
if opts.async_io {
|
||||
engine = Arc::new(AsyncIoEngine::new(opts.dev, MAX_CONCURRENT_IO, false)?);
|
||||
engine = Arc::new(AsyncIoEngine::new(opts.input, MAX_CONCURRENT_IO, false)?);
|
||||
} else {
|
||||
let nr_threads = std::cmp::max(8, num_cpus::get() * 2);
|
||||
engine = Arc::new(SyncIoEngine::new(opts.dev, nr_threads, false)?);
|
||||
engine = Arc::new(SyncIoEngine::new(opts.input, nr_threads, false)?);
|
||||
}
|
||||
|
||||
Ok(Context {
|
||||
@ -554,9 +557,9 @@ fn emit_entries<W: Write>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dump_metadata(ctx: &Context, sb: &Superblock, md: &Metadata) -> Result<()> {
|
||||
fn dump_metadata(ctx: &Context, w: &mut dyn Write, sb: &Superblock, md: &Metadata) -> Result<()> {
|
||||
let data_root = unpack::<SMRoot>(&sb.data_sm_root[0..])?;
|
||||
let mut out = xml::XmlWriter::new(std::io::stdout());
|
||||
let mut out = xml::XmlWriter::new(w);
|
||||
let xml_sb = xml::Superblock {
|
||||
uuid: "".to_string(),
|
||||
time: sb.time as u64,
|
||||
@ -590,6 +593,7 @@ fn dump_metadata(ctx: &Context, sb: &Superblock, md: &Metadata) -> Result<()> {
|
||||
out.device_e()?;
|
||||
}
|
||||
out.superblock_e()?;
|
||||
out.eof()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -601,11 +605,18 @@ pub fn dump(opts: ThinDumpOptions) -> Result<()> {
|
||||
let sb = read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION)?;
|
||||
let md = build_metadata(&ctx, &sb)?;
|
||||
|
||||
let mut writer: Box<dyn Write>;
|
||||
if opts.output.is_some() {
|
||||
writer = Box::new(BufWriter::new(File::create(opts.output.unwrap())?));
|
||||
} else {
|
||||
writer = Box::new(BufWriter::new(std::io::stdout()));
|
||||
}
|
||||
|
||||
ctx.report
|
||||
.set_title("Optimising metadata to improve leaf packing");
|
||||
let md = optimise_metadata(md)?;
|
||||
|
||||
dump_metadata(&ctx, &sb, &md)
|
||||
dump_metadata(&ctx, &mut writer, &sb, &md)
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user