[thin_shrink] Very simple copier implementation
This commit is contained in:
		| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user