[cache_dump (rust)] Allow partially broken dirty bitset

This commit is contained in:
Ming-Hung Tsai 2021-05-13 23:04:47 +08:00
parent db48f51049
commit 7e2d69ede9

63
src/cache/dump.rs vendored
View File

@ -10,6 +10,7 @@ use crate::cache::xml::{self, MetadataVisitor};
use crate::io_engine::{AsyncIoEngine, IoEngine, SyncIoEngine}; use crate::io_engine::{AsyncIoEngine, IoEngine, SyncIoEngine};
use crate::pdata::array::{self, ArrayBlock}; use crate::pdata::array::{self, ArrayBlock};
use crate::pdata::array_walker::*; use crate::pdata::array_walker::*;
use crate::pdata::bitset::{read_bitset, CheckedBitSet};
//------------------------------------------ //------------------------------------------
@ -78,49 +79,12 @@ mod format1 {
mod format2 { mod format2 {
use super::*; use super::*;
//-------------------
// Dirty bitset visitor
pub struct DirtyVisitor {
nr_entries: usize,
bits: Mutex<FixedBitSet>,
}
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<u64> for DirtyVisitor {
fn visit(&self, index: u64, b: ArrayBlock<u64>) -> 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 // Mapping visitor
struct Inner<'a> { struct Inner<'a> {
visitor: &'a mut dyn MetadataVisitor, visitor: &'a mut dyn MetadataVisitor,
dirty_bits: FixedBitSet, dirty_bits: CheckedBitSet,
valid_mappings: FixedBitSet, valid_mappings: FixedBitSet,
} }
@ -131,7 +95,7 @@ mod format2 {
impl<'a> MappingEmitter<'a> { impl<'a> MappingEmitter<'a> {
pub fn new( pub fn new(
nr_entries: usize, nr_entries: usize,
dirty_bits: FixedBitSet, dirty_bits: CheckedBitSet,
visitor: &'a mut dyn MetadataVisitor, visitor: &'a mut dyn MetadataVisitor,
) -> MappingEmitter<'a> { ) -> MappingEmitter<'a> {
MappingEmitter { MappingEmitter {
@ -159,7 +123,13 @@ mod format2 {
} }
let mut inner = self.inner.lock().unwrap(); 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 { let m = xml::Map {
cblock, cblock,
oblock: map.oblock, oblock: map.oblock,
@ -266,17 +236,20 @@ fn dump_metadata(ctx: &Context, sb: &Superblock, _repair: bool) -> anyhow::Resul
} }
2 => { 2 => {
// We need to walk the dirty bitset first. // We need to walk the dirty bitset first.
let w = ArrayWalker::new(engine.clone(), false); let dirty_bits;
let mut v = format2::DirtyVisitor::new(sb.cache_blocks as usize);
if let Some(root) = sb.dirty_root { 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 { } else {
// FIXME: is there a way this can legally happen? eg, // FIXME: is there a way this can legally happen? eg,
// a crash of a freshly created cache? // a crash of a freshly created cache?
return Err(anyhow!("format 2 selected, but no dirty bitset present")); 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 w = ArrayWalker::new(engine.clone(), false);
let mut emitter = let mut emitter =