summary refs log tree commit diff
path: root/disk
diff options
context:
space:
mode:
authorA. Cody Schuffelen <schuffelen@google.com>2019-12-23 18:51:40 -0800
committerCommit Bot <commit-bot@chromium.org>2020-01-22 07:50:03 +0000
commite058314700971f5839cf4153f56d410c3d70a11c (patch)
tree35cbc03fe46d933ee3c0073cc43898fa34b488f0 /disk
parente99b6c7e810437778d0a19bd3fb5d9e8f6adfb84 (diff)
downloadcrosvm-e058314700971f5839cf4153f56d410c3d70a11c.tar
crosvm-e058314700971f5839cf4153f56d410c3d70a11c.tar.gz
crosvm-e058314700971f5839cf4153f56d410c3d70a11c.tar.bz2
crosvm-e058314700971f5839cf4153f56d410c3d70a11c.tar.lz
crosvm-e058314700971f5839cf4153f56d410c3d70a11c.tar.xz
crosvm-e058314700971f5839cf4153f56d410c3d70a11c.tar.zst
crosvm-e058314700971f5839cf4153f56d410c3d70a11c.zip
Use DiskFile in read_cb
This will allow passing in other data sources for the qcow read methods,
without adding extra copies.

TEST=Unit tests
BUG=b:140069322
Change-Id: I2815fa6e416b554968b97959e4b6cd4c93a722f6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1982829
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Cody Schuffelen <schuffelen@google.com>
Diffstat (limited to 'disk')
-rw-r--r--disk/src/qcow/mod.rs68
1 files changed, 36 insertions, 32 deletions
diff --git a/disk/src/qcow/mod.rs b/disk/src/qcow/mod.rs
index 6bd9719..b1df192 100644
--- a/disk/src/qcow/mod.rs
+++ b/disk/src/qcow/mod.rs
@@ -24,7 +24,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
 use crate::qcow::qcow_raw_file::QcowRawFile;
 use crate::qcow::refcount::RefCount;
 use crate::qcow::vec_cache::{CacheMap, Cacheable, VecCache};
-use crate::DiskGetLen;
+use crate::{DiskFile, DiskGetLen};
 
 #[sorted]
 #[derive(Debug)]
@@ -1364,13 +1364,13 @@ impl QcowFile {
         Ok(())
     }
 
-    // Reads `count` bytes starting at `address`, calling `cb` repeatedly with the backing file,
-    // number of bytes read so far, and number of bytes to read from the file in that invocation. If
-    // None is given to `cb` in place of the backing file, the `cb` should infer zeros would have
-    // been read.
+    // Reads `count` bytes starting at `address`, calling `cb` repeatedly with the data source,
+    // number of bytes read so far, offset to read from, and number of bytes to read from the file
+    // in that invocation. If None is given to `cb` in place of the backing file, the `cb` should
+    // infer zeros would have been read.
     fn read_cb<F>(&mut self, address: u64, count: usize, mut cb: F) -> std::io::Result<usize>
     where
-        F: FnMut(Option<&mut File>, usize, usize) -> std::io::Result<()>,
+        F: FnMut(Option<&mut dyn DiskFile>, usize, u64, usize) -> std::io::Result<()>,
     {
         let read_count: usize = self.limit_range_file(address, count);
 
@@ -1381,10 +1381,9 @@ impl QcowFile {
             let count = self.limit_range_cluster(curr_addr, read_count - nread);
 
             if let Some(offset) = file_offset {
-                self.raw_file.file_mut().seek(SeekFrom::Start(offset))?;
-                cb(Some(self.raw_file.file_mut()), nread, count)?;
+                cb(Some(self.raw_file.file_mut()), nread, offset, count)?;
             } else {
-                cb(None, nread, count)?;
+                cb(None, nread, 0, count)?;
             }
 
             nread += count;
@@ -1433,20 +1432,21 @@ impl AsRawFd for QcowFile {
 
 impl Read for QcowFile {
     fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
-        let read_count =
-            self.read_cb(
-                self.current_offset,
-                buf.len(),
-                |file, offset, count| match file {
-                    Some(f) => f.read_exact(&mut buf[offset..(offset + count)]),
+        let slice = buf.get_slice(0, buf.len() as u64).unwrap();
+        let read_count = self.read_cb(
+            self.current_offset,
+            buf.len(),
+            |file, already_read, offset, count| {
+                let sub_slice = slice.get_slice(already_read as u64, count as u64).unwrap();
+                match file {
+                    Some(f) => f.read_exact_at_volatile(sub_slice, offset),
                     None => {
-                        for b in &mut buf[offset..(offset + count)] {
-                            *b = 0;
-                        }
+                        sub_slice.write_bytes(0);
                         Ok(())
                     }
-                },
-            )?;
+                }
+            },
+        )?;
         self.current_offset += read_count as u64;
         Ok(read_count)
     }
@@ -1506,10 +1506,10 @@ impl FileReadWriteVolatile for QcowFile {
         let read_count = self.read_cb(
             self.current_offset,
             slice.size() as usize,
-            |file, offset, count| {
-                let sub_slice = slice.get_slice(offset as u64, count as u64).unwrap();
+            |file, read, offset, count| {
+                let sub_slice = slice.get_slice(read as u64, count as u64).unwrap();
                 match file {
-                    Some(f) => f.read_exact_volatile(sub_slice),
+                    Some(f) => f.read_exact_at_volatile(sub_slice, offset),
                     None => {
                         sub_slice.write_bytes(0);
                         Ok(())
@@ -1537,16 +1537,20 @@ impl FileReadWriteVolatile for QcowFile {
 
 impl FileReadWriteAtVolatile for QcowFile {
     fn read_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> io::Result<usize> {
-        self.read_cb(offset, slice.size() as usize, |file, offset, count| {
-            let sub_slice = slice.get_slice(offset as u64, count as u64).unwrap();
-            match file {
-                Some(f) => f.read_exact_volatile(sub_slice),
-                None => {
-                    sub_slice.write_bytes(0);
-                    Ok(())
+        self.read_cb(
+            offset,
+            slice.size() as usize,
+            |file, read, offset, count| {
+                let sub_slice = slice.get_slice(read as u64, count as u64).unwrap();
+                match file {
+                    Some(f) => f.read_exact_at_volatile(sub_slice, offset),
+                    None => {
+                        sub_slice.write_bytes(0);
+                        Ok(())
+                    }
                 }
-            }
-        })
+            },
+        )
     }
 
     fn write_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> io::Result<usize> {