[thin_check (rust)] Keep track of data block ref counts

as we walk the mapping tree.
This commit is contained in:
Joe Thornber
2020-08-08 09:54:16 +01:00
parent 8f76371bb2
commit ec8f7b7fa8
3 changed files with 206 additions and 28 deletions

View File

@@ -1,7 +1,7 @@
use anyhow::{anyhow, Result};
use fixedbitset::FixedBitSet;
use nom::{number::complete::*, IResult};
use std::collections::HashMap;
use std::collections::{HashMap, BTreeMap};
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::time::Instant;
@@ -66,10 +66,21 @@ impl Unpack for BlockTime {
}
}
struct BottomLevelVisitor {}
struct BottomLevelVisitor {
data_sm: Arc<Mutex<CoreSpaceMap>>,
}
impl NodeVisitor<BlockTime> for BottomLevelVisitor {
fn visit(&mut self, _w: &BTreeWalker, _b: &Block, _node: &Node<BlockTime>) -> Result<()> {
fn visit(&mut self, _w: &BTreeWalker, _b: &Block, node: &Node<BlockTime>) -> Result<()> {
// FIXME: do other checks
if let Node::Leaf {header: _h, keys: _k, values} = node {
let mut data_sm = self.data_sm.lock().unwrap();
for bt in values {
data_sm.inc(bt.block)?;
}
}
Ok(())
}
}
@@ -197,6 +208,46 @@ impl<V: Unpack + Clone> NodeVisitor<V> for ValueCollector<V> {
//------------------------------------------
struct RangeBuilder {
run: Option<(u64, BitmapEntry)>,
runs: Vec<(u64, BitmapEntry)>
}
impl RangeBuilder {
fn new() -> RangeBuilder {
RangeBuilder {
run: None,
runs: Vec::new(),
}
}
fn push(&mut self, e: &BitmapEntry) {
match &self.run {
Some((len, e2)) if *e == *e2 => {
self.run = Some((*len + 1, e2.clone()));
},
Some((len, e2)) => {
self.runs.push((*len, e2.clone()));
self.run = Some((1, e.clone()));
},
None => {
self.run = Some((1, e.clone()));
}
}
}
fn complete(&mut self) {
match &self.run {
Some((len, e)) => {
self.runs.push((*len, e.clone()));
},
None => {}
}
}
}
//------------------------------------------
pub fn check(dev: &Path) -> Result<()> {
let engine = Arc::new(AsyncIoEngine::new(dev, 256)?);
@@ -230,10 +281,14 @@ pub fn check(dev: &Path) -> Result<()> {
engine.get_nr_blocks() as usize,
)));
let root = unpack::<SMRoot>(&sb.data_sm_root[0..])?;
let data_sm = Arc::new(Mutex::new(CoreSpaceMap::new(root.nr_blocks)));
for (thin_id, root) in roots {
let mut w = BTreeWalker::new_with_seen(engine.clone(), seen.clone(), false);
let data_sm = data_sm.clone();
pool.execute(move || {
let mut v = BottomLevelVisitor {};
let mut v = BottomLevelVisitor {data_sm};
let result = w.walk(&mut v, root).expect("walk failed"); // FIXME: return error
eprintln!("checked thin_dev {} -> {:?}", thin_id, result);
});
@@ -266,6 +321,8 @@ pub fn check(dev: &Path) -> Result<()> {
let _result = w.walk(&mut v, root.bitmap_root);
eprintln!("{} index entries", v.entries.len());
let mut builder = RangeBuilder::new();
for i in v.entries {
let mut b = Block::new(i.blocknr);
engine.read(&mut b)?;
@@ -274,7 +331,26 @@ pub fn check(dev: &Path) -> Result<()> {
return Err(anyhow!("Index entry points to block ({}) that isn't a bitmap", b.loc));
}
let _bitmap = unpack::<Bitmap>(b.get_data())?;
let bitmap = unpack::<Bitmap>(b.get_data())?;
for e in bitmap.entries {
builder.push(&e);
}
}
builder.complete();
eprintln!("{} ranges", builder.runs.len());
let mut counts = BTreeMap::new();
for (len, _v) in builder.runs {
if let Some(c) = counts.get(&len) {
let new_c = *c + 1;
counts.insert(len, new_c);
} else {
counts.insert(len, 1);
}
}
for (len, c) in counts {
eprintln!("{}: {}", len, c);
}
}