[thin_restore (rust)] Prepare for thin_repair
- Finalize the metadata in the Restorer - Make the Restorer public
This commit is contained in:
parent
d42bde371f
commit
dccd844714
@ -22,6 +22,12 @@ fn main() {
|
|||||||
.long("async-io")
|
.long("async-io")
|
||||||
.hidden(true),
|
.hidden(true),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("QUIET")
|
||||||
|
.help("Suppress output messages, return only exit code.")
|
||||||
|
.short("q")
|
||||||
|
.long("quiet"),
|
||||||
|
)
|
||||||
// options
|
// options
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("INPUT")
|
Arg::with_name("INPUT")
|
||||||
@ -33,7 +39,7 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("OUTPUT")
|
Arg::with_name("OUTPUT")
|
||||||
.help("Specify the output device to check")
|
.help("Specify the output device")
|
||||||
.short("o")
|
.short("o")
|
||||||
.long("output")
|
.long("output")
|
||||||
.value_name("OUTPUT")
|
.value_name("OUTPUT")
|
||||||
|
@ -10,6 +10,7 @@ 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_common::SMRoot;
|
||||||
use crate::pdata::space_map_disk::*;
|
use crate::pdata::space_map_disk::*;
|
||||||
use crate::pdata::space_map_metadata::*;
|
use crate::pdata::space_map_metadata::*;
|
||||||
use crate::pdata::unpack::Pack;
|
use crate::pdata::unpack::Pack;
|
||||||
@ -58,13 +59,7 @@ impl std::fmt::Display for MappedSection {
|
|||||||
|
|
||||||
//------------------------------------------
|
//------------------------------------------
|
||||||
|
|
||||||
struct RestoreResult {
|
pub struct Restorer<'a> {
|
||||||
sb: ir::Superblock,
|
|
||||||
devices: BTreeMap<u32, (DeviceDetail, u64)>,
|
|
||||||
data_sm: Arc<Mutex<dyn SpaceMap>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Restorer<'a> {
|
|
||||||
w: &'a mut WriteBatcher,
|
w: &'a mut WriteBatcher,
|
||||||
report: Arc<Report>,
|
report: Arc<Report>,
|
||||||
|
|
||||||
@ -81,7 +76,7 @@ struct Restorer<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Restorer<'a> {
|
impl<'a> Restorer<'a> {
|
||||||
fn new(w: &'a mut WriteBatcher, report: Arc<Report>) -> Self {
|
pub fn new(w: &'a mut WriteBatcher, report: Arc<Report>) -> Self {
|
||||||
Restorer {
|
Restorer {
|
||||||
w,
|
w,
|
||||||
report,
|
report,
|
||||||
@ -94,17 +89,6 @@ impl<'a> Restorer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_result(self) -> Result<RestoreResult> {
|
|
||||||
if self.sb.is_none() {
|
|
||||||
return Err(anyhow!("No superblock found in xml file"));
|
|
||||||
}
|
|
||||||
Ok(RestoreResult {
|
|
||||||
sb: self.sb.unwrap(),
|
|
||||||
devices: self.devices,
|
|
||||||
data_sm: self.data_sm.unwrap(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn begin_section(&mut self, section: MappedSection) -> Result<Visit> {
|
fn begin_section(&mut self, section: MappedSection) -> Result<Visit> {
|
||||||
if let Some((outer, _)) = self.current_map.as_ref() {
|
if let Some((outer, _)) = self.current_map.as_ref() {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
@ -134,17 +118,65 @@ impl<'a> Restorer<'a> {
|
|||||||
Err(anyhow!(msg))
|
Err(anyhow!(msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build the device details and the top level mapping trees
|
||||||
|
fn build_device_details(&mut self) -> Result<(u64, u64)> {
|
||||||
|
let mut details_builder: BTreeBuilder<DeviceDetail> =
|
||||||
|
BTreeBuilder::new(Box::new(NoopRC {}));
|
||||||
|
let mut dev_builder: BTreeBuilder<u64> = BTreeBuilder::new(Box::new(NoopRC {}));
|
||||||
|
for (thin_id, (detail, root)) in self.devices.iter() {
|
||||||
|
details_builder.push_value(self.w, *thin_id as u64, *detail)?;
|
||||||
|
dev_builder.push_value(self.w, *thin_id as u64, *root)?;
|
||||||
|
}
|
||||||
|
let details_root = details_builder.complete(self.w)?;
|
||||||
|
let mapping_root = dev_builder.complete(self.w)?;
|
||||||
|
|
||||||
|
Ok((details_root, mapping_root))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Result<()> {
|
||||||
|
let (details_root, mapping_root) = self.build_device_details()?;
|
||||||
|
|
||||||
|
// Build data space map
|
||||||
|
let data_sm = self.data_sm.as_ref().unwrap();
|
||||||
|
let data_sm_root = build_data_sm(self.w, data_sm.lock().unwrap().deref())?;
|
||||||
|
|
||||||
|
// Build metadata space map
|
||||||
|
let (metadata_sm, metadata_sm_root) = build_metadata_sm(self.w)?;
|
||||||
|
|
||||||
|
// Write the superblock
|
||||||
|
let sb = self.sb.as_ref().unwrap();
|
||||||
|
let sb = superblock::Superblock {
|
||||||
|
flags: SuperblockFlags { needs_check: false },
|
||||||
|
block: SUPERBLOCK_LOCATION,
|
||||||
|
version: 2,
|
||||||
|
time: sb.time as u32,
|
||||||
|
transaction_id: sb.transaction,
|
||||||
|
metadata_snap: 0,
|
||||||
|
data_sm_root,
|
||||||
|
metadata_sm_root,
|
||||||
|
mapping_root,
|
||||||
|
details_root,
|
||||||
|
data_block_size: sb.data_block_size,
|
||||||
|
nr_metadata_blocks: metadata_sm.nr_blocks,
|
||||||
|
};
|
||||||
|
write_superblock(self.w.engine.as_ref(), SUPERBLOCK_LOCATION, &sb)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MetadataVisitor for Restorer<'a> {
|
impl<'a> MetadataVisitor for Restorer<'a> {
|
||||||
fn superblock_b(&mut self, sb: &ir::Superblock) -> Result<Visit> {
|
fn superblock_b(&mut self, sb: &ir::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.data_sm = Some(core_sm(sb.nr_data_blocks, u32::MAX));
|
||||||
self.w.alloc()?;
|
let b = self.w.alloc()?;
|
||||||
|
if b.loc != SUPERBLOCK_LOCATION {
|
||||||
|
return Err(anyhow!("superblock was occupied"));
|
||||||
|
}
|
||||||
Ok(Visit::Continue)
|
Ok(Visit::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn superblock_e(&mut self) -> Result<Visit> {
|
fn superblock_e(&mut self) -> Result<Visit> {
|
||||||
|
self.finalize()?;
|
||||||
Ok(Visit::Continue)
|
Ok(Visit::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,13 +281,13 @@ fn build_data_sm(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result<Vec<u8>> {
|
|||||||
|
|
||||||
/// Writes the metadata space map to disk. Returns the space map root that needs
|
/// Writes the metadata 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_metadata_sm(w: &mut WriteBatcher) -> Result<Vec<u8>> {
|
fn build_metadata_sm(w: &mut WriteBatcher) -> Result<(SMRoot, Vec<u8>)> {
|
||||||
let mut sm_root = vec![0u8; SPACE_MAP_ROOT_SIZE];
|
let mut sm_root = vec![0u8; SPACE_MAP_ROOT_SIZE];
|
||||||
let mut cur = Cursor::new(&mut sm_root);
|
let mut cur = Cursor::new(&mut sm_root);
|
||||||
let r = write_metadata_sm(w)?;
|
let r = write_metadata_sm(w)?;
|
||||||
r.pack(&mut cur)?;
|
r.pack(&mut cur)?;
|
||||||
|
|
||||||
Ok(sm_root)
|
Ok((r, sm_root))
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------
|
//------------------------------------------
|
||||||
@ -303,42 +335,8 @@ pub fn restore(opts: ThinRestoreOptions) -> Result<()> {
|
|||||||
|
|
||||||
let sm = core_sm(ctx.engine.get_nr_blocks(), max_count);
|
let sm = core_sm(ctx.engine.get_nr_blocks(), max_count);
|
||||||
let mut w = WriteBatcher::new(ctx.engine.clone(), sm.clone(), ctx.engine.get_batch_size());
|
let mut w = WriteBatcher::new(ctx.engine.clone(), sm.clone(), ctx.engine.get_batch_size());
|
||||||
let mut restorer = Restorer::new(&mut w, ctx.report.clone());
|
let mut restorer = Restorer::new(&mut w, ctx.report);
|
||||||
xml::read(input, &mut restorer)?;
|
xml::read(input, &mut restorer)?;
|
||||||
let result = restorer.get_result()?;
|
|
||||||
|
|
||||||
// Build the device details and top level mapping tree
|
|
||||||
let mut details_builder: BTreeBuilder<DeviceDetail> = BTreeBuilder::new(Box::new(NoopRC {}));
|
|
||||||
let mut dev_builder: BTreeBuilder<u64> = BTreeBuilder::new(Box::new(NoopRC {}));
|
|
||||||
for (thin_id, (detail, root)) in &result.devices {
|
|
||||||
details_builder.push_value(&mut w, *thin_id as u64, *detail)?;
|
|
||||||
dev_builder.push_value(&mut w, *thin_id as u64, *root)?;
|
|
||||||
}
|
|
||||||
let details_root = details_builder.complete(&mut w)?;
|
|
||||||
let mapping_root = dev_builder.complete(&mut w)?;
|
|
||||||
|
|
||||||
// Build data space map
|
|
||||||
let data_sm_root = build_data_sm(&mut w, result.data_sm.lock().unwrap().deref())?;
|
|
||||||
|
|
||||||
// Build metadata space map
|
|
||||||
let metadata_sm_root = build_metadata_sm(&mut w)?;
|
|
||||||
|
|
||||||
// Write the superblock
|
|
||||||
let sb = superblock::Superblock {
|
|
||||||
flags: SuperblockFlags { needs_check: false },
|
|
||||||
block: SUPERBLOCK_LOCATION,
|
|
||||||
version: 2,
|
|
||||||
time: result.sb.time as u32,
|
|
||||||
transaction_id: result.sb.transaction,
|
|
||||||
metadata_snap: 0,
|
|
||||||
data_sm_root,
|
|
||||||
metadata_sm_root,
|
|
||||||
mapping_root,
|
|
||||||
details_root,
|
|
||||||
data_block_size: result.sb.data_block_size,
|
|
||||||
nr_metadata_blocks: ctx.engine.get_nr_blocks(),
|
|
||||||
};
|
|
||||||
write_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION, &sb)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user