diff --git a/src/cache/check.rs b/src/cache/check.rs index d162eb4..82e37c1 100644 --- a/src/cache/check.rs +++ b/src/cache/check.rs @@ -12,7 +12,7 @@ use crate::pdata::array_walker::*; use crate::pdata::bitset::*; use crate::pdata::space_map::*; use crate::pdata::space_map_checker::*; -use crate::pdata::space_map_disk::*; +use crate::pdata::space_map_common::*; use crate::pdata::unpack::unpack; use crate::report::*; diff --git a/src/pdata/mod.rs b/src/pdata/mod.rs index 2ae347b..21ce07c 100644 --- a/src/pdata/mod.rs +++ b/src/pdata/mod.rs @@ -9,5 +9,7 @@ pub mod btree_merge; pub mod btree_walker; pub mod space_map; pub mod space_map_checker; +pub mod space_map_common; pub mod space_map_disk; +pub mod space_map_metadata; pub mod unpack; diff --git a/src/pdata/space_map_checker.rs b/src/pdata/space_map_checker.rs index 9a944a1..d0a9f47 100644 --- a/src/pdata/space_map_checker.rs +++ b/src/pdata/space_map_checker.rs @@ -7,7 +7,8 @@ use crate::io_engine::IoEngine; use crate::pdata::btree::{self, *}; use crate::pdata::btree_walker::*; use crate::pdata::space_map::*; -use crate::pdata::space_map_disk::*; +use crate::pdata::space_map_common::*; +use crate::pdata::space_map_metadata::*; use crate::pdata::unpack::*; use crate::report::Report; diff --git a/src/pdata/space_map_common.rs b/src/pdata/space_map_common.rs new file mode 100644 index 0000000..33e3a51 --- /dev/null +++ b/src/pdata/space_map_common.rs @@ -0,0 +1,257 @@ +use anyhow::{anyhow, Result}; +use byteorder::{LittleEndian, WriteBytesExt}; +use nom::{number::complete::*, IResult}; +use std::io::Cursor; + +use crate::checksum; +use crate::io_engine::*; +use crate::math::*; +use crate::pdata::btree_builder::*; +use crate::pdata::space_map::*; +use crate::pdata::unpack::*; +use crate::write_batcher::*; + +//------------------------------------------ + +pub const ENTRIES_PER_BITMAP: usize = WORDS_PER_BITMAP * 8 * ENTRIES_PER_BYTE; +const WORDS_PER_BITMAP: usize = (BLOCK_SIZE - 16) / 8; +const ENTRIES_PER_BYTE: usize = 4; + +//------------------------------------------ + +#[derive(Clone, Copy, Debug)] +pub struct IndexEntry { + pub blocknr: u64, + pub nr_free: u32, + pub none_free_before: u32, +} + +impl Unpack for IndexEntry { + fn disk_size() -> u32 { + 16 + } + + fn unpack(i: &[u8]) -> IResult<&[u8], IndexEntry> { + let (i, blocknr) = le_u64(i)?; + let (i, nr_free) = le_u32(i)?; + let (i, none_free_before) = le_u32(i)?; + + Ok(( + i, + IndexEntry { + blocknr, + nr_free, + none_free_before, + }, + )) + } +} + +impl Pack for IndexEntry { + fn pack(&self, w: &mut W) -> Result<()> { + w.write_u64::(self.blocknr)?; + w.write_u32::(self.nr_free)?; + w.write_u32::(self.none_free_before)?; + Ok(()) + } +} + +//------------------------------------------ + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BitmapEntry { + Small(u8), + Overflow, +} + +#[derive(Debug)] +pub struct Bitmap { + pub blocknr: u64, + pub entries: Vec, +} + +impl Unpack for Bitmap { + fn disk_size() -> u32 { + BLOCK_SIZE as u32 + } + + fn unpack(data: &[u8]) -> IResult<&[u8], Self> { + let (i, _csum) = le_u32(data)?; + let (i, _not_used) = le_u32(i)?; + let (mut i, blocknr) = le_u64(i)?; + + let header_size = 16; + let nr_words = (BLOCK_SIZE - header_size) / 8; + let mut entries = Vec::with_capacity(nr_words * 32); + for _w in 0..nr_words { + let (tmp, mut word) = le_u64(i)?; + + for _b in 0..32 { + let val = word & 0x3; + word >>= 2; + + // The bits are stored with the high bit at b * 2 + 1, + // and low at b *2. So we have to interpret this val. + entries.push(match val { + 0 => BitmapEntry::Small(0), + 1 => BitmapEntry::Small(2), + 2 => BitmapEntry::Small(1), + _ => BitmapEntry::Overflow, + }); + } + + i = tmp; + } + + Ok((i, Bitmap { blocknr, entries })) + } +} + +impl Pack for Bitmap { + fn pack(&self, out: &mut W) -> Result<()> { + use BitmapEntry::*; + + out.write_u32::(0)?; + out.write_u32::(0)?; + out.write_u64::(self.blocknr)?; + + for chunk in self.entries.chunks(32) { + let mut w = 0u64; + for e in chunk { + w >>= 2; + match e { + Small(0) => {} + Small(1) => { + w |= 0x2 << 62; + } + Small(2) => { + w |= 0x1 << 62; + } + Small(_) => { + return Err(anyhow!("Bad small value in bitmap entry")); + } + Overflow => { + w |= 0x3 << 62; + } + } + } + + u64::pack(&w, out)?; + } + + Ok(()) + } +} + +//------------------------------------------ + +#[derive(Debug)] +pub struct SMRoot { + pub nr_blocks: u64, + pub nr_allocated: u64, + pub bitmap_root: u64, + pub ref_count_root: u64, +} + +impl Unpack for SMRoot { + fn disk_size() -> u32 { + 32 + } + + fn unpack(i: &[u8]) -> IResult<&[u8], Self> { + let (i, nr_blocks) = le_u64(i)?; + let (i, nr_allocated) = le_u64(i)?; + let (i, bitmap_root) = le_u64(i)?; + let (i, ref_count_root) = le_u64(i)?; + + Ok(( + i, + SMRoot { + nr_blocks, + nr_allocated, + bitmap_root, + ref_count_root, + }, + )) + } +} + +pub fn unpack_root(data: &[u8]) -> Result { + match SMRoot::unpack(data) { + Err(_e) => Err(anyhow!("couldn't parse SMRoot")), + Ok((_i, v)) => Ok(v), + } +} + +impl Pack for SMRoot { + fn pack(&self, w: &mut W) -> Result<()> { + w.write_u64::(self.nr_blocks)?; + w.write_u64::(self.nr_allocated)?; + w.write_u64::(self.bitmap_root)?; + w.write_u64::(self.ref_count_root)?; + + Ok(()) + } +} + +//------------------------------------------ + +pub fn write_common(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result<(Vec, u64)> { + use BitmapEntry::*; + + let mut index_entries = Vec::new(); + let mut overflow_builder: Builder = Builder::new(Box::new(NoopRC {})); + + // how many bitmaps do we need? + for bm in 0..div_up(sm.get_nr_blocks()? as usize, ENTRIES_PER_BITMAP) { + let mut entries = Vec::with_capacity(ENTRIES_PER_BITMAP); + let mut first_free: Option = None; + let mut nr_free: u32 = 0; + for i in 0..ENTRIES_PER_BITMAP { + let b: u64 = ((bm * ENTRIES_PER_BITMAP) as u64) + i as u64; + if b > sm.get_nr_blocks()? { + break; + } + let rc = sm.get(b)?; + let e = match rc { + 0 => { + nr_free += 1; + if first_free.is_none() { + first_free = Some(i as u32); + } + Small(0) + } + 1 => Small(1), + 2 => Small(2), + _ => { + overflow_builder.push_value(w, b as u64, rc)?; + Overflow + } + }; + entries.push(e); + } + + // allocate a new block + let b = w.alloc()?; + let mut cursor = Cursor::new(b.get_data()); + + // write the bitmap to it + let blocknr = b.loc; + let bitmap = Bitmap { blocknr, entries }; + bitmap.pack(&mut cursor)?; + w.write(b, checksum::BT::BITMAP)?; + + // Insert into the index tree + let ie = IndexEntry { + blocknr, + nr_free, + none_free_before: first_free.unwrap_or(ENTRIES_PER_BITMAP as u32), + }; + index_entries.push(ie); + } + + let ref_count_root = overflow_builder.complete(w)?; + Ok((index_entries, ref_count_root)) +} + +//------------------------------------------ diff --git a/src/pdata/space_map_disk.rs b/src/pdata/space_map_disk.rs index 2dee628..1389d78 100644 --- a/src/pdata/space_map_disk.rs +++ b/src/pdata/space_map_disk.rs @@ -1,301 +1,11 @@ -use anyhow::{anyhow, Result}; -use byteorder::{LittleEndian, WriteBytesExt}; -use nom::{number::complete::*, IResult}; -use std::collections::BTreeMap; -use std::io::Cursor; +use anyhow::Result; -use crate::checksum; -use crate::io_engine::*; -use crate::math::*; use crate::pdata::btree_builder::*; use crate::pdata::space_map::*; -use crate::pdata::unpack::*; +use crate::pdata::space_map_common::*; use crate::write_batcher::*; -//-------------------------------- - -const MAX_METADATA_BITMAPS: usize = 255; -// const MAX_METADATA_BLOCKS: u64 = 255 * ((1 << 14) - 64); -const ENTRIES_PER_BYTE: usize = 4; -const ENTRIES_PER_BITMAP: usize = WORDS_PER_BITMAP * 8 * ENTRIES_PER_BYTE; - -//-------------------------------- - -#[derive(Clone, Copy, Debug)] -pub struct IndexEntry { - pub blocknr: u64, - pub nr_free: u32, - pub none_free_before: u32, -} - -impl Unpack for IndexEntry { - fn disk_size() -> u32 { - 16 - } - - fn unpack(i: &[u8]) -> IResult<&[u8], IndexEntry> { - let (i, blocknr) = le_u64(i)?; - let (i, nr_free) = le_u32(i)?; - let (i, none_free_before) = le_u32(i)?; - - Ok(( - i, - IndexEntry { - blocknr, - nr_free, - none_free_before, - }, - )) - } -} - -impl Pack for IndexEntry { - fn pack(&self, w: &mut W) -> Result<()> { - w.write_u64::(self.blocknr)?; - w.write_u32::(self.nr_free)?; - w.write_u32::(self.none_free_before)?; - Ok(()) - } -} - -//-------------------------------- - -pub struct MetadataIndex { - pub blocknr: u64, - pub indexes: Vec, -} - -impl Unpack for MetadataIndex { - fn disk_size() -> u32 { - BLOCK_SIZE as u32 - } - - fn unpack(i: &[u8]) -> IResult<&[u8], MetadataIndex> { - // FIXME: check the checksum - let (i, _csum) = le_u32(i)?; - let (i, _padding) = le_u32(i)?; - let (i, blocknr) = le_u64(i)?; - let (i, indexes) = nom::multi::count(IndexEntry::unpack, MAX_METADATA_BITMAPS)(i)?; - - Ok((i, MetadataIndex { blocknr, indexes })) - } -} - -impl Pack for MetadataIndex { - fn pack(&self, w: &mut W) -> Result<()> { - w.write_u32::(0)?; // csum - w.write_u32::(0)?; // padding - w.write_u64::(self.blocknr)?; - - assert!(self.indexes.len() <= MAX_METADATA_BITMAPS); - - for ie in &self.indexes { - ie.pack(w)?; - } - - Ok(()) - } -} - -//-------------------------------- - -const WORDS_PER_BITMAP: usize = (BLOCK_SIZE - 16) / 8; - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum BitmapEntry { - Small(u8), - Overflow, -} - -#[derive(Debug)] -pub struct Bitmap { - pub blocknr: u64, - pub entries: Vec, -} - -impl Unpack for Bitmap { - fn disk_size() -> u32 { - BLOCK_SIZE as u32 - } - - fn unpack(data: &[u8]) -> IResult<&[u8], Self> { - let (i, _csum) = le_u32(data)?; - let (i, _not_used) = le_u32(i)?; - let (mut i, blocknr) = le_u64(i)?; - - let header_size = 16; - let nr_words = (BLOCK_SIZE - header_size) / 8; - let mut entries = Vec::with_capacity(nr_words * 32); - for _w in 0..nr_words { - let (tmp, mut word) = le_u64(i)?; - - for _b in 0..32 { - let val = word & 0x3; - word >>= 2; - - // The bits are stored with the high bit at b * 2 + 1, - // and low at b *2. So we have to interpret this val. - entries.push(match val { - 0 => BitmapEntry::Small(0), - 1 => BitmapEntry::Small(2), - 2 => BitmapEntry::Small(1), - _ => BitmapEntry::Overflow, - }); - } - - i = tmp; - } - - Ok((i, Bitmap { blocknr, entries })) - } -} - -impl Pack for Bitmap { - fn pack(&self, out: &mut W) -> Result<()> { - use BitmapEntry::*; - - out.write_u32::(0)?; - out.write_u32::(0)?; - out.write_u64::(self.blocknr)?; - - for chunk in self.entries.chunks(32) { - let mut w = 0u64; - for e in chunk { - w >>= 2; - match e { - Small(0) => {} - Small(1) => { - w |= 0x2 << 62; - } - Small(2) => { - w |= 0x1 << 62; - } - Small(_) => { - return Err(anyhow!("Bad small value in bitmap entry")); - } - Overflow => { - w |= 0x3 << 62; - } - } - } - - u64::pack(&w, out)?; - } - - Ok(()) - } -} - -//-------------------------------- - -#[derive(Debug)] -pub struct SMRoot { - pub nr_blocks: u64, - pub nr_allocated: u64, - pub bitmap_root: u64, - pub ref_count_root: u64, -} - -impl Unpack for SMRoot { - fn disk_size() -> u32 { - 32 - } - - fn unpack(i: &[u8]) -> IResult<&[u8], Self> { - let (i, nr_blocks) = le_u64(i)?; - let (i, nr_allocated) = le_u64(i)?; - let (i, bitmap_root) = le_u64(i)?; - let (i, ref_count_root) = le_u64(i)?; - - Ok(( - i, - SMRoot { - nr_blocks, - nr_allocated, - bitmap_root, - ref_count_root, - }, - )) - } -} - -pub fn unpack_root(data: &[u8]) -> Result { - match SMRoot::unpack(data) { - Err(_e) => Err(anyhow!("couldn't parse SMRoot")), - Ok((_i, v)) => Ok(v), - } -} - -impl Pack for SMRoot { - fn pack(&self, w: &mut W) -> Result<()> { - w.write_u64::(self.nr_blocks)?; - w.write_u64::(self.nr_allocated)?; - w.write_u64::(self.bitmap_root)?; - w.write_u64::(self.ref_count_root)?; - - Ok(()) - } -} - -//-------------------------------- - -pub fn write_common(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result<(Vec, u64)> { - use BitmapEntry::*; - - let mut index_entries = Vec::new(); - let mut overflow_builder: Builder = Builder::new(Box::new(NoopRC {})); - - // how many bitmaps do we need? - for bm in 0..div_up(sm.get_nr_blocks()? as usize, ENTRIES_PER_BITMAP) { - let mut entries = Vec::with_capacity(ENTRIES_PER_BITMAP); - let mut first_free: Option = None; - let mut nr_free: u32 = 0; - for i in 0..ENTRIES_PER_BITMAP { - let b: u64 = ((bm * ENTRIES_PER_BITMAP) as u64) + i as u64; - if b > sm.get_nr_blocks()? { - break; - } - let rc = sm.get(b)?; - let e = match rc { - 0 => { - nr_free += 1; - if first_free.is_none() { - first_free = Some(i as u32); - } - Small(0) - } - 1 => Small(1), - 2 => Small(2), - _ => { - overflow_builder.push_value(w, b as u64, rc)?; - Overflow - } - }; - entries.push(e); - } - - // allocate a new block - let b = w.alloc()?; - let mut cursor = Cursor::new(b.get_data()); - - // write the bitmap to it - let blocknr = b.loc; - let bitmap = Bitmap { blocknr, entries }; - bitmap.pack(&mut cursor)?; - w.write(b, checksum::BT::BITMAP)?; - - // Insert into the index tree - let ie = IndexEntry { - blocknr, - nr_free, - none_free_before: first_free.unwrap_or(ENTRIES_PER_BITMAP as u32), - }; - index_entries.push(ie); - } - - let ref_count_root = overflow_builder.complete(w)?; - Ok((index_entries, ref_count_root)) -} +//------------------------------------------ pub fn write_disk_sm(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result { let (index_entries, ref_count_root) = write_common(w, sm)?; @@ -315,85 +25,4 @@ pub fn write_disk_sm(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result }) } -//---------------------------- - -fn block_to_bitmap(b: u64) -> usize { - (b / ENTRIES_PER_BITMAP as u64) as usize -} - -fn adjust_counts(w: &mut WriteBatcher, ie: &IndexEntry, allocs: &[u64]) -> Result { - use BitmapEntry::*; - - let mut first_free = ie.none_free_before; - let mut nr_free = ie.nr_free - allocs.len() as u32; - - // Read the bitmap - let bitmap_block = w.engine.read(ie.blocknr)?; - let (_, mut bitmap) = Bitmap::unpack(bitmap_block.get_data())?; - - // Update all the entries - for a in allocs { - if first_free == *a as u32 { - first_free = *a as u32 + 1; - } - - if bitmap.entries[*a as usize] == Small(0) { - nr_free -= 1; - } - - bitmap.entries[*a as usize] = Small(1); - } - - // Write the bitmap - let mut cur = Cursor::new(bitmap_block.get_data()); - bitmap.pack(&mut cur)?; - w.write(bitmap_block, checksum::BT::BITMAP)?; - - // Return the adjusted index entry - Ok(IndexEntry { - blocknr: ie.blocknr, - nr_free, - none_free_before: first_free, - }) -} - -pub fn write_metadata_sm(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result { - w.clear_allocations(); - let (mut indexes, ref_count_root) = write_common(w, sm)?; - - let bitmap_root = w.alloc()?; - - // Now we need to patch up the counts for the metadata that was used for storing - // the space map itself. These ref counts all went from 0 to 1. - let allocations = w.clear_allocations(); - - // Sort the allocations by bitmap - let mut by_bitmap = BTreeMap::new(); - for b in allocations { - let bitmap = block_to_bitmap(b); - (*by_bitmap.entry(bitmap).or_insert_with(Vec::new)).push(b % ENTRIES_PER_BITMAP as u64); - } - - for (bitmap, allocs) in by_bitmap { - indexes[bitmap] = adjust_counts(w, &indexes[bitmap], &allocs)?; - } - - // Write out the metadata index - let metadata_index = MetadataIndex { - blocknr: bitmap_root.loc, - indexes, - }; - let mut cur = Cursor::new(bitmap_root.get_data()); - metadata_index.pack(&mut cur)?; - let loc = bitmap_root.loc; - w.write(bitmap_root, checksum::BT::INDEX)?; - - Ok(SMRoot { - nr_blocks: sm.get_nr_blocks()?, - nr_allocated: sm.get_nr_allocated()?, - bitmap_root: loc, - ref_count_root, - }) -} - -//-------------------------------- +//------------------------------------------ diff --git a/src/pdata/space_map_metadata.rs b/src/pdata/space_map_metadata.rs new file mode 100644 index 0000000..85f6828 --- /dev/null +++ b/src/pdata/space_map_metadata.rs @@ -0,0 +1,138 @@ +use anyhow::Result; +use byteorder::{LittleEndian, WriteBytesExt}; +use nom::{number::complete::*, IResult}; +use std::collections::BTreeMap; +use std::io::Cursor; + +use crate::checksum; +use crate::io_engine::*; +use crate::pdata::space_map::*; +use crate::pdata::space_map_common::*; +use crate::pdata::unpack::*; +use crate::write_batcher::*; + +//------------------------------------------ + +const MAX_METADATA_BITMAPS: usize = 255; + +//------------------------------------------ + +pub struct MetadataIndex { + pub blocknr: u64, + pub indexes: Vec, +} + +impl Unpack for MetadataIndex { + fn disk_size() -> u32 { + BLOCK_SIZE as u32 + } + + fn unpack(i: &[u8]) -> IResult<&[u8], MetadataIndex> { + // FIXME: check the checksum + let (i, _csum) = le_u32(i)?; + let (i, _padding) = le_u32(i)?; + let (i, blocknr) = le_u64(i)?; + let (i, indexes) = nom::multi::count(IndexEntry::unpack, MAX_METADATA_BITMAPS)(i)?; + + Ok((i, MetadataIndex { blocknr, indexes })) + } +} + +impl Pack for MetadataIndex { + fn pack(&self, w: &mut W) -> Result<()> { + w.write_u32::(0)?; // csum + w.write_u32::(0)?; // padding + w.write_u64::(self.blocknr)?; + + assert!(self.indexes.len() <= MAX_METADATA_BITMAPS); + + for ie in &self.indexes { + ie.pack(w)?; + } + + Ok(()) + } +} + +//------------------------------------------ + +fn block_to_bitmap(b: u64) -> usize { + (b / ENTRIES_PER_BITMAP as u64) as usize +} + +fn adjust_counts(w: &mut WriteBatcher, ie: &IndexEntry, allocs: &[u64]) -> Result { + use BitmapEntry::*; + + let mut first_free = ie.none_free_before; + let mut nr_free = ie.nr_free - allocs.len() as u32; + + // Read the bitmap + let bitmap_block = w.engine.read(ie.blocknr)?; + let (_, mut bitmap) = Bitmap::unpack(bitmap_block.get_data())?; + + // Update all the entries + for a in allocs { + if first_free == *a as u32 { + first_free = *a as u32 + 1; + } + + if bitmap.entries[*a as usize] == Small(0) { + nr_free -= 1; + } + + bitmap.entries[*a as usize] = Small(1); + } + + // Write the bitmap + let mut cur = Cursor::new(bitmap_block.get_data()); + bitmap.pack(&mut cur)?; + w.write(bitmap_block, checksum::BT::BITMAP)?; + + // Return the adjusted index entry + Ok(IndexEntry { + blocknr: ie.blocknr, + nr_free, + none_free_before: first_free, + }) +} + +pub fn write_metadata_sm(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result { + w.clear_allocations(); + let (mut indexes, ref_count_root) = write_common(w, sm)?; + + let bitmap_root = w.alloc()?; + + // Now we need to patch up the counts for the metadata that was used for storing + // the space map itself. These ref counts all went from 0 to 1. + let allocations = w.clear_allocations(); + + // Sort the allocations by bitmap + let mut by_bitmap = BTreeMap::new(); + for b in allocations { + let bitmap = block_to_bitmap(b); + (*by_bitmap.entry(bitmap).or_insert_with(Vec::new)).push(b % ENTRIES_PER_BITMAP as u64); + } + + for (bitmap, allocs) in by_bitmap { + indexes[bitmap] = adjust_counts(w, &indexes[bitmap], &allocs)?; + } + + // Write out the metadata index + let metadata_index = MetadataIndex { + blocknr: bitmap_root.loc, + indexes, + }; + let mut cur = Cursor::new(bitmap_root.get_data()); + metadata_index.pack(&mut cur)?; + let loc = bitmap_root.loc; + w.write(bitmap_root, checksum::BT::INDEX)?; + + Ok(SMRoot { + nr_blocks: sm.get_nr_blocks()?, + nr_allocated: sm.get_nr_allocated()?, + bitmap_root: loc, + ref_count_root, + }) +} + +//------------------------------------------ diff --git a/src/thin/check.rs b/src/thin/check.rs index d3aba19..1c5836e 100644 --- a/src/thin/check.rs +++ b/src/thin/check.rs @@ -10,7 +10,7 @@ use crate::pdata::btree::{self, *}; use crate::pdata::btree_walker::*; use crate::pdata::space_map::*; use crate::pdata::space_map_checker::*; -use crate::pdata::space_map_disk::*; +use crate::pdata::space_map_common::*; use crate::pdata::unpack::*; use crate::report::*; use crate::thin::block_time::*; diff --git a/src/thin/dump.rs b/src/thin/dump.rs index f1c9080..d8c796f 100644 --- a/src/thin/dump.rs +++ b/src/thin/dump.rs @@ -11,7 +11,7 @@ use crate::pdata::btree::{self, *}; use crate::pdata::btree_leaf_walker::*; use crate::pdata::btree_walker::*; use crate::pdata::space_map::*; -use crate::pdata::space_map_disk::*; +use crate::pdata::space_map_common::*; use crate::pdata::unpack::*; use crate::report::*; use crate::thin::block_time::*;