[thin_restore (rust)] Build metadata and data space maps

This commit is contained in:
Ming-Hung Tsai 2021-05-26 21:18:53 +08:00
parent c142cd0d48
commit 3a653eaa5f
2 changed files with 60 additions and 11 deletions

View File

@ -2,12 +2,17 @@ use anyhow::{anyhow, Result};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::Cursor;
use std::ops::Deref;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::{Arc, Mutex};
use crate::io_engine::*; use crate::io_engine::*;
use crate::pdata::btree_builder::*; use crate::pdata::btree_builder::*;
use crate::pdata::space_map::*; use crate::pdata::space_map::*;
use crate::pdata::space_map_disk::*;
use crate::pdata::space_map_metadata::*;
use crate::pdata::unpack::Pack;
use crate::report::*; use crate::report::*;
use crate::thin::block_time::*; use crate::thin::block_time::*;
use crate::thin::device_detail::*; use crate::thin::device_detail::*;
@ -17,6 +22,25 @@ use crate::write_batcher::*;
//------------------------------------------ //------------------------------------------
struct MappingRC {
sm: Arc<Mutex<dyn SpaceMap>>,
}
impl RefCounter<BlockTime> for MappingRC {
fn get(&self, v: &BlockTime) -> Result<u32> {
return self.sm.lock().unwrap().get(v.block);
}
fn inc(&mut self, v: &BlockTime) -> Result<()> {
self.sm.lock().unwrap().inc(v.block, 1)
}
fn dec(&mut self, v: &BlockTime) -> Result<()> {
self.sm.lock().unwrap().dec(v.block)?;
Ok(())
}
}
//------------------------------------------
enum MappedSection { enum MappedSection {
Def(String), Def(String),
Dev(u32), Dev(u32),
@ -31,9 +55,12 @@ impl std::fmt::Display for MappedSection {
} }
} }
//------------------------------------------
struct Pass1Result { struct Pass1Result {
sb: xml::Superblock, sb: xml::Superblock,
devices: BTreeMap<u32, (DeviceDetail, Vec<NodeSummary>)>, devices: BTreeMap<u32, (DeviceDetail, Vec<NodeSummary>)>,
data_sm: Arc<Mutex<dyn SpaceMap>>,
} }
struct Pass1<'a> { struct Pass1<'a> {
@ -47,6 +74,7 @@ struct Pass1<'a> {
sb: Option<xml::Superblock>, sb: Option<xml::Superblock>,
devices: BTreeMap<u32, (DeviceDetail, Vec<NodeSummary>)>, devices: BTreeMap<u32, (DeviceDetail, Vec<NodeSummary>)>,
data_sm: Option<Arc<Mutex<dyn SpaceMap>>>,
} }
impl<'a> Pass1<'a> { impl<'a> Pass1<'a> {
@ -58,6 +86,7 @@ impl<'a> Pass1<'a> {
map: None, map: None,
sb: None, sb: None,
devices: BTreeMap::new(), devices: BTreeMap::new(),
data_sm: None,
} }
} }
@ -68,6 +97,7 @@ impl<'a> Pass1<'a> {
Ok(Pass1Result { Ok(Pass1Result {
sb: self.sb.unwrap(), sb: self.sb.unwrap(),
devices: self.devices, devices: self.devices,
data_sm: self.data_sm.unwrap(),
}) })
} }
@ -80,7 +110,9 @@ impl<'a> Pass1<'a> {
return Err(anyhow!(msg)); return Err(anyhow!(msg));
} }
let value_rc = Box::new(NoopRC {}); let value_rc = Box::new(MappingRC {
sm: self.data_sm.as_ref().unwrap().clone(),
});
let leaf_builder = NodeBuilder::new(Box::new(LeafIO {}), value_rc); let leaf_builder = NodeBuilder::new(Box::new(LeafIO {}), value_rc);
self.map = Some((section, leaf_builder)); self.map = Some((section, leaf_builder));
@ -103,6 +135,7 @@ impl<'a> Pass1<'a> {
impl<'a> MetadataVisitor for Pass1<'a> { impl<'a> MetadataVisitor for Pass1<'a> {
fn superblock_b(&mut self, sb: &xml::Superblock) -> Result<Visit> { fn superblock_b(&mut self, sb: &xml::Superblock) -> Result<Visit> {
self.sb = Some(sb.clone()); self.sb = Some(sb.clone());
self.data_sm = Some(core_sm(sb.nr_data_blocks, u32::MAX));
self.w.alloc()?; self.w.alloc()?;
Ok(Visit::Continue) Ok(Visit::Continue)
} }
@ -196,13 +229,29 @@ impl<'a> MetadataVisitor for Pass1<'a> {
} }
//------------------------------------------ //------------------------------------------
/*
/// Writes a data space map to disk. Returns the space map root that needs /// Writes a data space map to disk. Returns the space map root that needs
/// to be written to the superblock. /// to be written to the superblock.
fn build_data_sm(batcher: WriteBatcher, sm: Box<dyn SpaceMap>) -> Result<Vec<u8>> { fn build_data_sm(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result<Vec<u8>> {
let mut sm_root = vec![0u8; SPACE_MAP_ROOT_SIZE];
let mut cur = Cursor::new(&mut sm_root);
let r = write_disk_sm(w, sm)?;
r.pack(&mut cur)?;
Ok(sm_root)
}
/// Writes the metadata space map to disk. Returns the space map root that needs
/// to be written to the superblock.
fn build_metadata_sm(w: &mut WriteBatcher) -> Result<Vec<u8>> {
let mut sm_root = vec![0u8; SPACE_MAP_ROOT_SIZE];
let mut cur = Cursor::new(&mut sm_root);
let sm_without_meta = clone_space_map(w.sm.lock().unwrap().deref())?;
let r = write_metadata_sm(w, sm_without_meta.deref())?;
r.pack(&mut cur)?;
Ok(sm_root)
} }
*/
//------------------------------------------ //------------------------------------------
@ -279,11 +328,11 @@ pub fn restore(opts: ThinRestoreOptions) -> Result<()> {
let mapping_root = builder.complete(&mut w)?; let mapping_root = builder.complete(&mut w)?;
// Build data space map // Build data space map
let data_sm_root = build_data_sm(&mut w, pass.data_sm.lock().unwrap().deref())?;
// FIXME: I think we need to decrement the shared leaves // FIXME: I think we need to decrement the shared leaves
// Build metadata space map // Build metadata space map
let metadata_sm_root = build_metadata_sm(&mut w)?;
w.flush()?;
// Write the superblock // Write the superblock
let sb = superblock::Superblock { let sb = superblock::Superblock {
@ -293,8 +342,8 @@ pub fn restore(opts: ThinRestoreOptions) -> Result<()> {
time: pass.sb.time as u32, time: pass.sb.time as u32,
transaction_id: pass.sb.transaction, transaction_id: pass.sb.transaction,
metadata_snap: 0, metadata_snap: 0,
data_sm_root: vec![0; SPACE_MAP_ROOT_SIZE], data_sm_root,
metadata_sm_root: vec![0; SPACE_MAP_ROOT_SIZE], metadata_sm_root,
mapping_root, mapping_root,
details_root, details_root,
data_block_size: pass.sb.data_block_size, data_block_size: pass.sb.data_block_size,

View File

@ -116,8 +116,8 @@ fn pack_superblock<W: WriteBytesExt>(sb: &Superblock, w: &mut W) -> Result<()> {
w.write_u32::<LittleEndian>(sb.time)?; w.write_u32::<LittleEndian>(sb.time)?;
w.write_u64::<LittleEndian>(sb.transaction_id)?; w.write_u64::<LittleEndian>(sb.transaction_id)?;
w.write_u64::<LittleEndian>(sb.metadata_snap)?; w.write_u64::<LittleEndian>(sb.metadata_snap)?;
w.write_all(&[0; SPACE_MAP_ROOT_SIZE])?; // data sm root w.write_all(&sb.data_sm_root)?;
w.write_all(&[0; SPACE_MAP_ROOT_SIZE])?; // metadata sm root w.write_all(&sb.metadata_sm_root)?;
w.write_u64::<LittleEndian>(sb.mapping_root)?; w.write_u64::<LittleEndian>(sb.mapping_root)?;
w.write_u64::<LittleEndian>(sb.details_root)?; w.write_u64::<LittleEndian>(sb.details_root)?;
w.write_u32::<LittleEndian>(sb.data_block_size)?; w.write_u32::<LittleEndian>(sb.data_block_size)?;