[thin_check (rust)] Fix auto-repair related errors

- Returns error on metadata leaks
- Clear needs_check flag on success
- Check auto-repair write errors
- Fix file open flags, and correct spelling
This commit is contained in:
Ming-Hung Tsai 2021-09-09 16:46:39 +08:00
parent e7fa012701
commit a18fd60f3f
4 changed files with 51 additions and 9 deletions

View File

@ -109,16 +109,18 @@ fn main() {
}
let engine: Arc<dyn IoEngine + Send + Sync>;
let writable = matches.is_present("AUTO_REPAIR") || matches.is_present("CLEAR_NEEDS_CHECK");
if matches.is_present("ASYNC_IO") {
engine = Arc::new(
AsyncIoEngine::new(&input_file, MAX_CONCURRENT_IO, false)
AsyncIoEngine::new(&input_file, MAX_CONCURRENT_IO, writable)
.expect("unable to open input file"),
);
} else {
let nr_threads = std::cmp::max(8, num_cpus::get() * 2);
engine = Arc::new(
SyncIoEngine::new(&input_file, nr_threads, false).expect("unable to open input file"),
SyncIoEngine::new(&input_file, nr_threads, writable)
.expect("unable to open input file"),
);
}
@ -128,6 +130,7 @@ fn main() {
skip_mappings: matches.is_present("SKIP_MAPPINGS"),
ignore_non_fatal: matches.is_present("IGNORE_NON_FATAL"),
auto_repair: matches.is_present("AUTO_REPAIR"),
clear_needs_check: matches.is_present("CLEAR_NEEDS_CHECK"),
report,
};

View File

@ -131,16 +131,16 @@ impl<'a> Drop for FileGuard<'a> {
}
impl SyncIoEngine {
fn open_file(path: &Path, writeable: bool) -> Result<File> {
let file = OpenOptions::new().read(true).write(writeable).open(path)?;
fn open_file(path: &Path, writable: bool) -> Result<File> {
let file = OpenOptions::new().read(true).write(writable).open(path)?;
Ok(file)
}
pub fn new(path: &Path, nr_files: usize, writeable: bool) -> Result<SyncIoEngine> {
pub fn new(path: &Path, nr_files: usize, writable: bool) -> Result<SyncIoEngine> {
let mut files = Vec::with_capacity(nr_files);
for _n in 0..nr_files {
files.push(SyncIoEngine::open_file(path, writeable)?);
files.push(SyncIoEngine::open_file(path, writable)?);
}
Ok(SyncIoEngine {
@ -231,10 +231,10 @@ pub struct AsyncIoEngine {
}
impl AsyncIoEngine {
pub fn new(path: &Path, queue_len: u32, writeable: bool) -> Result<AsyncIoEngine> {
pub fn new(path: &Path, queue_len: u32, writable: bool) -> Result<AsyncIoEngine> {
let input = OpenOptions::new()
.read(true)
.write(writeable)
.write(writable)
.custom_flags(libc::O_DIRECT)
.open(path)?;

View File

@ -309,7 +309,12 @@ pub fn repair_space_map(
}
}
engine.write_many(&write_blocks[0..])?;
let results = engine.write_many(&write_blocks[0..])?;
for ret in results {
if ret.is_err() {
return Err(anyhow!("Unable to repair space map: {:?}", ret));
}
}
Ok(())
}

View File

@ -87,6 +87,7 @@ pub struct ThinCheckOptions {
pub skip_mappings: bool,
pub ignore_non_fatal: bool,
pub auto_repair: bool,
pub clear_needs_check: bool,
pub report: Arc<Report>,
}
@ -276,6 +277,10 @@ pub fn check(opts: ThinCheckOptions) -> Result<()> {
)?;
if opts.skip_mappings {
let cleared = clear_needs_check_flag(ctx.engine.clone())?;
if cleared {
ctx.report.info("Cleared needs_check flag");
}
return Ok(());
}
@ -331,6 +336,26 @@ pub fn check(opts: ThinCheckOptions) -> Result<()> {
ctx.report.info("Repairing metadata leaks.");
repair_space_map(ctx.engine.clone(), metadata_leaks, metadata_sm.clone())?;
}
let cleared = clear_needs_check_flag(ctx.engine.clone())?;
if cleared {
ctx.report.info("Cleared needs_check flag");
}
} else if !opts.ignore_non_fatal {
if !data_leaks.is_empty() {
return Err(anyhow!("data space map contains leaks"));
}
if !metadata_leaks.is_empty() {
return Err(anyhow!("metadata space map contains leaks"));
}
if opts.clear_needs_check {
let cleared = clear_needs_check_flag(ctx.engine.clone())?;
if cleared {
ctx.report.info("Cleared needs_check flag");
}
}
}
stop_progress.store(true, Ordering::Relaxed);
@ -339,6 +364,15 @@ pub fn check(opts: ThinCheckOptions) -> Result<()> {
Ok(())
}
pub fn clear_needs_check_flag(engine: Arc<dyn IoEngine + Send + Sync>) -> Result<bool> {
let mut sb = read_superblock(engine.as_ref(), SUPERBLOCK_LOCATION)?;
if !sb.flags.needs_check {
return Ok(false);
}
sb.flags.needs_check = false;
write_superblock(engine.as_ref(), SUPERBLOCK_LOCATION, &sb).map(|_| true)
}
//------------------------------------------
// Some callers wish to know which blocks are allocated.