From 7e2d69ede932b47147b2cc3b66065f64f3de1986 Mon Sep 17 00:00:00 2001 From: Ming-Hung Tsai Date: Thu, 13 May 2021 23:04:47 +0800 Subject: [PATCH] [cache_dump (rust)] Allow partially broken dirty bitset --- src/cache/dump.rs | 63 ++++++++++++++--------------------------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/src/cache/dump.rs b/src/cache/dump.rs index 22f16fd..f80421a 100644 --- a/src/cache/dump.rs +++ b/src/cache/dump.rs @@ -10,6 +10,7 @@ use crate::cache::xml::{self, MetadataVisitor}; use crate::io_engine::{AsyncIoEngine, IoEngine, SyncIoEngine}; use crate::pdata::array::{self, ArrayBlock}; use crate::pdata::array_walker::*; +use crate::pdata::bitset::{read_bitset, CheckedBitSet}; //------------------------------------------ @@ -78,49 +79,12 @@ mod format1 { mod format2 { use super::*; - //------------------- - // Dirty bitset visitor - pub struct DirtyVisitor { - nr_entries: usize, - bits: Mutex, - } - - impl DirtyVisitor { - pub fn new(nr_entries: usize) -> Self { - DirtyVisitor { - nr_entries, // number of bits - bits: Mutex::new(FixedBitSet::with_capacity(nr_entries)), - } - } - - pub fn get_bits(self) -> FixedBitSet { - self.bits.into_inner().unwrap() - } - } - - impl ArrayVisitor for DirtyVisitor { - fn visit(&self, index: u64, b: ArrayBlock) -> array::Result<()> { - let mut pos = (index as usize * (b.header.max_entries as usize)) << 6; - for bits in b.values.iter() { - for bi in 0..64u64 { - if pos >= self.nr_entries { - break; - } - - self.bits.lock().unwrap().set(pos, bits & (1 << bi) != 0); - pos += 1; - } - } - Ok(()) - } - } - //------------------- // Mapping visitor struct Inner<'a> { visitor: &'a mut dyn MetadataVisitor, - dirty_bits: FixedBitSet, + dirty_bits: CheckedBitSet, valid_mappings: FixedBitSet, } @@ -131,7 +95,7 @@ mod format2 { impl<'a> MappingEmitter<'a> { pub fn new( nr_entries: usize, - dirty_bits: FixedBitSet, + dirty_bits: CheckedBitSet, visitor: &'a mut dyn MetadataVisitor, ) -> MappingEmitter<'a> { MappingEmitter { @@ -159,7 +123,13 @@ mod format2 { } let mut inner = self.inner.lock().unwrap(); - let dirty = inner.dirty_bits.contains(cblock as usize); + let dirty; + if let Some(bit) = inner.dirty_bits.contains(cblock as usize) { + dirty = bit; + } else { + // default to dirty if the bitset is damaged + dirty = true; + } let m = xml::Map { cblock, oblock: map.oblock, @@ -266,17 +236,20 @@ fn dump_metadata(ctx: &Context, sb: &Superblock, _repair: bool) -> anyhow::Resul } 2 => { // We need to walk the dirty bitset first. - let w = ArrayWalker::new(engine.clone(), false); - let mut v = format2::DirtyVisitor::new(sb.cache_blocks as usize); - + let dirty_bits; if let Some(root) = sb.dirty_root { - w.walk(&mut v, root)?; + let (bits, errs) = + read_bitset(engine.clone(), root, sb.cache_blocks as usize, false); + // TODO: allow errors in repair mode + if errs.is_some() { + return Err(anyhow!("errors in bitset {}", errs.unwrap())); + } + dirty_bits = bits; } else { // FIXME: is there a way this can legally happen? eg, // a crash of a freshly created cache? return Err(anyhow!("format 2 selected, but no dirty bitset present")); } - let dirty_bits = v.get_bits(); let w = ArrayWalker::new(engine.clone(), false); let mut emitter =