[thin_shrink] Very simple copier implementation
This commit is contained in:
parent
fcf44d46b7
commit
27c6e36f5c
@ -1,14 +1,59 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::io::{Seek, SeekFrom, Write, Read};
|
||||||
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
|
|
||||||
pub type Sector = u64;
|
pub type Sector = u64;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Region {
|
pub struct Region {
|
||||||
src: Sector,
|
pub src: Sector,
|
||||||
dest: Sector,
|
pub dest: Sector,
|
||||||
len: Sector,
|
pub len: Sector,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: pass in
|
|
||||||
pub fn copy(path: &str, regions: &Vec<Region>) -> Result<()> {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ struct Pass1 {
|
|||||||
/// High blocks are beyond the new, reduced end of the pool. These
|
/// High blocks are beyond the new, reduced end of the pool. These
|
||||||
/// will need to be moved.
|
/// will need to be moved.
|
||||||
nr_high_blocks: u64,
|
nr_high_blocks: u64,
|
||||||
|
block_size: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pass1 {
|
impl Pass1 {
|
||||||
@ -27,6 +28,7 @@ impl Pass1 {
|
|||||||
allocated_blocks: FixedBitSet::with_capacity(0),
|
allocated_blocks: FixedBitSet::with_capacity(0),
|
||||||
nr_blocks,
|
nr_blocks,
|
||||||
nr_high_blocks: 0,
|
nr_high_blocks: 0,
|
||||||
|
block_size: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,6 +36,7 @@ impl Pass1 {
|
|||||||
impl xml::MetadataVisitor for Pass1 {
|
impl xml::MetadataVisitor for Pass1 {
|
||||||
fn superblock_b(&mut self, sb: &xml::Superblock) -> Result<()> {
|
fn superblock_b(&mut self, sb: &xml::Superblock) -> Result<()> {
|
||||||
self.allocated_blocks.grow(sb.nr_data_blocks as usize);
|
self.allocated_blocks.grow(sb.nr_data_blocks as usize);
|
||||||
|
self.block_size = Some(sb.data_block_size as u64);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,8 +417,17 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_copy_regions(remaps: &Vec<(BlockRange, BlockRange)>) -> Vec<Region> {
|
fn build_copy_regions(remaps: &Vec<(BlockRange, BlockRange)>, block_size: u64) -> Vec<Region> {
|
||||||
let rs = Vec::new();
|
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
|
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);
|
let remaps = build_remaps(above, free);
|
||||||
eprintln!("remappings {:?}.", remaps);
|
eprintln!("remappings {:?}.", remaps);
|
||||||
|
|
||||||
let regions = build_copy_regions(&remaps);
|
let regions = build_copy_regions(&remaps, pass1.block_size.unwrap() as u64);
|
||||||
eprint!("Copying data...");
|
//eprint!("Copying data...");
|
||||||
copier::copy(data_path, ®ions);
|
copier::copy(data_path, ®ions)?;
|
||||||
eprintln!("done.");
|
//eprintln!("done.");
|
||||||
|
|
||||||
let output = OpenOptions::new()
|
let output = OpenOptions::new()
|
||||||
.read(false)
|
.read(false)
|
||||||
|
Loading…
Reference in New Issue
Block a user