diff options
author | Daniel Verkamp <dverkamp@chromium.org> | 2018-09-26 17:03:27 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-09-27 19:44:08 -0700 |
commit | eaaf3e17e68e2a08012b23adb99b2a80b14a21f5 (patch) | |
tree | 8914785ddee1d8989a9b435fc94ad95e329e0f22 /qcow | |
parent | 610fa31a0b03b9482a14f94e302a3dce45ecd2be (diff) | |
download | crosvm-eaaf3e17e68e2a08012b23adb99b2a80b14a21f5.tar crosvm-eaaf3e17e68e2a08012b23adb99b2a80b14a21f5.tar.gz crosvm-eaaf3e17e68e2a08012b23adb99b2a80b14a21f5.tar.bz2 crosvm-eaaf3e17e68e2a08012b23adb99b2a80b14a21f5.tar.lz crosvm-eaaf3e17e68e2a08012b23adb99b2a80b14a21f5.tar.xz crosvm-eaaf3e17e68e2a08012b23adb99b2a80b14a21f5.tar.zst crosvm-eaaf3e17e68e2a08012b23adb99b2a80b14a21f5.zip |
qcow: buffer reads and writes in QcowRawFile
When reading and writing refcount blocks and pointer tables, the QcowRawFile implementation was performing many individual read() and write() system calls (one per table entry), which is quite inefficient. Use the read_*_into functions from ReadBytesExt for reads and BufWriter for writes to buffer the I/O into larger chunks. BUG=None TEST=Manually verify larger reads/writes with strace Change-Id: I276963db0a4e91b22335c26c799ae8fb55bf6ad3 Signed-off-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1247441 Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'qcow')
-rw-r--r-- | qcow/src/qcow_raw_file.rs | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/qcow/src/qcow_raw_file.rs b/qcow/src/qcow_raw_file.rs index 37bdca2..c178b3c 100644 --- a/qcow/src/qcow_raw_file.rs +++ b/qcow/src/qcow_raw_file.rs @@ -3,7 +3,7 @@ // found in the LICENSE file. use std::fs::File; -use std::io::{self, Seek, SeekFrom}; +use std::io::{self, BufWriter, Seek, SeekFrom}; use std::mem::size_of; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; @@ -38,11 +38,13 @@ impl QcowRawFile { count: u64, mask: Option<u64>, ) -> io::Result<Vec<u64>> { - let mut table = Vec::with_capacity(count as usize); + let mut table = vec![0; count as usize]; self.file.seek(SeekFrom::Start(offset))?; - let mask = mask.unwrap_or(0xffff_ffff_ffff_ffff); - for _ in 0..count { - table.push(self.file.read_u64::<BigEndian>()? & mask); + self.file.read_u64_into::<BigEndian>(&mut table)?; + if let Some(m) = mask { + for ptr in table.iter_mut() { + *ptr &= m; + } } Ok(table) } @@ -64,13 +66,14 @@ impl QcowRawFile { non_zero_flags: u64, ) -> io::Result<()> { self.file.seek(SeekFrom::Start(offset))?; + let mut buffer = BufWriter::new(&self.file); for addr in table { let val = if *addr == 0 { 0 } else { *addr | non_zero_flags }; - self.file.write_u64::<BigEndian>(val)?; + buffer.write_u64::<BigEndian>(val)?; } Ok(()) } @@ -79,19 +82,18 @@ impl QcowRawFile { /// Always returns a cluster's worth of data. pub fn read_refcount_block(&mut self, offset: u64) -> io::Result<Vec<u16>> { let count = self.cluster_size / size_of::<u16>() as u64; - let mut table = Vec::with_capacity(count as usize); + let mut table = vec![0; count as usize]; self.file.seek(SeekFrom::Start(offset))?; - for _ in 0..count { - table.push(self.file.read_u16::<BigEndian>()?); - } + self.file.read_u16_into::<BigEndian>(&mut table)?; Ok(table) } /// Writes a refcount block to the file. pub fn write_refcount_block(&mut self, offset: u64, table: &[u16]) -> io::Result<()> { self.file.seek(SeekFrom::Start(offset))?; + let mut buffer = BufWriter::new(&self.file); for count in table { - self.file.write_u16::<BigEndian>(*count)?; + buffer.write_u16::<BigEndian>(*count)?; } Ok(()) } |