[thin_shrink] Very simple copier implementation
This commit is contained in:
parent
fcf44d46b7
commit
27c6e36f5c
@ -1,14 +1,59 @@
|
||||
use anyhow::Result;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{Seek, SeekFrom, Write, Read};
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
|
||||
pub type Sector = u64;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Region {
|
||||
src: Sector,
|
||||
dest: Sector,
|
||||
len: Sector,
|
||||
pub src: Sector,
|
||||
pub dest: Sector,
|
||||
pub len: Sector,
|
||||
}
|
||||
|
||||
// FIXME: pass in
|
||||
pub fn copy(path: &str, regions: &Vec<Region>) -> Result<()> {
|
||||
|
||||
fn copy_step<W>(file: &mut W, src_byte: u64, dest_byte: u64, len: usize) -> Result<()>
|
||||
where
|
||||
W: Write + Seek + Read,
|
||||
{
|
||||
let mut buf = vec![0; len];
|
||||
file.seek(SeekFrom::Start(src_byte))?;
|
||||
file.read_exact(&mut buf[0..])?;
|
||||
file.seek(SeekFrom::Start(dest_byte))?;
|
||||
file.write_all(&buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_region<W>(file: &mut W, r: &Region) -> Result<()>
|
||||
where
|
||||
W: Write + Seek + Read,
|
||||
{
|
||||
const MAX_BYTES: Sector = 1024 * 1024 * 64;
|
||||
|
||||
let src_bytes = r.src * 512;
|
||||
let dest_bytes = r.dest * 512;
|
||||
let len_bytes = r.len * 512;
|
||||
let mut written = 0;
|
||||
while written != len_bytes {
|
||||
let step = u64::min(len_bytes - written, MAX_BYTES);
|
||||
copy_step(file, src_bytes + written, dest_bytes + written, step as usize)?;
|
||||
written += step;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn copy(path: &str, regions: &Vec<Region>) -> Result<()> {
|
||||
let mut input = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
//.custom_flags(libc::O_DIRECT)
|
||||
.open(path)?;
|
||||
|
||||
for r in regions {
|
||||
eprintln!("copying {:?}", r);
|
||||
copy_region(&mut input, r)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ struct Pass1 {
|
||||
/// High blocks are beyond the new, reduced end of the pool. These
|
||||
/// will need to be moved.
|
||||
nr_high_blocks: u64,
|
||||
block_size: Option<u64>,
|
||||
}
|
||||
|
||||
impl Pass1 {
|
||||
@ -27,6 +28,7 @@ impl Pass1 {
|
||||
allocated_blocks: FixedBitSet::with_capacity(0),
|
||||
nr_blocks,
|
||||
nr_high_blocks: 0,
|
||||
block_size: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,6 +36,7 @@ impl Pass1 {
|
||||
impl xml::MetadataVisitor for Pass1 {
|
||||
fn superblock_b(&mut self, sb: &xml::Superblock) -> Result<()> {
|
||||
self.allocated_blocks.grow(sb.nr_data_blocks as usize);
|
||||
self.block_size = Some(sb.data_block_size as u64);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -414,8 +417,17 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_copy_regions(remaps: &Vec<(BlockRange, BlockRange)>) -> Vec<Region> {
|
||||
let rs = Vec::new();
|
||||
fn build_copy_regions(remaps: &Vec<(BlockRange, BlockRange)>, block_size: u64) -> Vec<Region> {
|
||||
let mut rs = Vec::new();
|
||||
|
||||
for (from, to) in remaps {
|
||||
rs.push(Region {
|
||||
src: from.start * block_size,
|
||||
dest: to.start * block_size,
|
||||
len: range_len(&from) * block_size,
|
||||
});
|
||||
}
|
||||
|
||||
rs
|
||||
}
|
||||
|
||||
@ -467,10 +479,10 @@ pub fn shrink(input_path: &str, output_path: &str, data_path: &str, nr_blocks: u
|
||||
let remaps = build_remaps(above, free);
|
||||
eprintln!("remappings {:?}.", remaps);
|
||||
|
||||
let regions = build_copy_regions(&remaps);
|
||||
eprint!("Copying data...");
|
||||
copier::copy(data_path, ®ions);
|
||||
eprintln!("done.");
|
||||
let regions = build_copy_regions(&remaps, pass1.block_size.unwrap() as u64);
|
||||
//eprint!("Copying data...");
|
||||
copier::copy(data_path, ®ions)?;
|
||||
//eprintln!("done.");
|
||||
|
||||
let output = OpenOptions::new()
|
||||
.read(false)
|
||||
|
Loading…
Reference in New Issue
Block a user