summary refs log tree commit diff
path: root/qcow
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2018-09-26 17:03:27 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-09-27 19:44:08 -0700
commiteaaf3e17e68e2a08012b23adb99b2a80b14a21f5 (patch)
tree8914785ddee1d8989a9b435fc94ad95e329e0f22 /qcow
parent610fa31a0b03b9482a14f94e302a3dce45ecd2be (diff)
downloadcrosvm-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.rs24
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(())
     }