[cache_dump (rust)] Allow partially broken dirty bitset
This commit is contained in:
parent
db48f51049
commit
7e2d69ede9
63
src/cache/dump.rs
vendored
63
src/cache/dump.rs
vendored
@ -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 =
|
||||||
|
Loading…
Reference in New Issue
Block a user