disk: switch from WriteZeroes to WriteZeroesAt

This eliminates an extra seek per guest write zeroes request.

Additionally, it allows us to stop depending on the file cursor and pass
the offset directly, making multi-queue implementation easier.

BUG=chromium:858815
TEST=Boot Termina in crosvm

Change-Id: I8b15a39752a1b68597a2b1e1fd72382a484a3cb2
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1913521
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
diff --git a/devices/src/virtio/block.rs b/devices/src/virtio/block.rs
index 987cb03..2910e1d 100644
--- a/devices/src/virtio/block.rs
+++ b/devices/src/virtio/block.rs
@@ -140,10 +140,6 @@
         sector: u64,
         desc_error: io::Error,
     },
-    Seek {
-        ioerr: io::Error,
-        sector: u64,
-    },
     TimerFd(SysError),
     WriteIo {
         length: usize,
@@ -182,7 +178,6 @@
                 "io error reading {} bytes from sector {}: {}",
                 length, sector, desc_error,
             ),
-            Seek { ioerr, sector } => write!(f, "failed to seek to sector {}: {}", sector, ioerr),
             TimerFd(e) => write!(f, "{}", e),
             WriteIo {
                 length,
@@ -229,7 +224,6 @@
             ExecuteError::WriteStatus(_) => VIRTIO_BLK_S_IOERR,
             ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR,
             ExecuteError::ReadIo { .. } => VIRTIO_BLK_S_IOERR,
-            ExecuteError::Seek { .. } => VIRTIO_BLK_S_IOERR,
             ExecuteError::TimerFd(_) => VIRTIO_BLK_S_IOERR,
             ExecuteError::WriteIo { .. } => VIRTIO_BLK_S_IOERR,
             ExecuteError::DiscardWriteZeroes { .. } => VIRTIO_BLK_S_IOERR,
@@ -661,16 +655,13 @@
                         // FALLOC_FL_PUNCH_HOLE, ignore punch_hole errors.
                         let _ = disk.punch_hole(offset, length);
                     } else {
-                        disk.seek(SeekFrom::Start(offset))
-                            .map_err(|e| ExecuteError::Seek { ioerr: e, sector })?;
-                        disk.write_zeroes_all(length as usize).map_err(|e| {
-                            ExecuteError::DiscardWriteZeroes {
+                        disk.write_zeroes_all_at(offset, length as usize)
+                            .map_err(|e| ExecuteError::DiscardWriteZeroes {
                                 ioerr: Some(e),
                                 sector,
                                 num_sectors,
                                 flags,
-                            }
-                        })?;
+                            })?;
                     }
                 }
             }
diff --git a/disk/src/composite.rs b/disk/src/composite.rs
index 6e0d2a0..da0fe07 100644
--- a/disk/src/composite.rs
+++ b/disk/src/composite.rs
@@ -14,7 +14,7 @@
 use data_model::VolatileSlice;
 use protos::cdisk_spec;
 use remain::sorted;
-use sys_util::{AsRawFds, FileReadWriteAtVolatile, FileSetLen, FileSync, PunchHole, WriteZeroes};
+use sys_util::{AsRawFds, FileReadWriteAtVolatile, FileSetLen, FileSync, PunchHole, WriteZeroesAt};
 
 #[sorted]
 #[derive(Debug)]
@@ -300,22 +300,17 @@
     }
 }
 
-impl WriteZeroes for CompositeDiskFile {
-    fn write_zeroes(&mut self, length: usize) -> io::Result<usize> {
-        let cursor_location = self.cursor_location;
+impl WriteZeroesAt for CompositeDiskFile {
+    fn write_zeroes_at(&mut self, offset: u64, length: usize) -> io::Result<usize> {
+        let cursor_location = offset;
         let disk = self.disk_at_offset(cursor_location)?;
-        disk.file
-            .seek(SeekFrom::Start(cursor_location - disk.offset))?;
+        let offset_within_disk = cursor_location - disk.offset;
         let new_length = if cursor_location + length as u64 > disk.offset + disk.length {
             (disk.offset + disk.length - cursor_location) as usize
         } else {
             length
         };
-        let result = disk.file.write_zeroes(new_length);
-        if let Ok(size) = result {
-            self.cursor_location += size as u64;
-        }
-        result
+        disk.file.write_zeroes_at(offset_within_disk, new_length)
     }
 }
 
@@ -524,10 +519,11 @@
         composite
             .write_all_at_volatile(input_volatile_memory.get_slice(0, 300).unwrap(), 0)
             .unwrap();
-        composite.seek(SeekFrom::Start(50)).unwrap();
         let mut zeroes_written = 0;
         while zeroes_written < 200 {
-            zeroes_written += composite.write_zeroes(200 - zeroes_written).unwrap();
+            zeroes_written += composite
+                .write_zeroes_at(50 + zeroes_written as u64, 200 - zeroes_written)
+                .unwrap();
         }
         let mut output_memory = [0u8; 300];
         let output_volatile_memory = &mut output_memory[..];
diff --git a/disk/src/disk.rs b/disk/src/disk.rs
index b5692a3..a9c44c6 100644
--- a/disk/src/disk.rs
+++ b/disk/src/disk.rs
@@ -11,7 +11,7 @@
 use qcow::{QcowFile, QCOW_MAGIC};
 use remain::sorted;
 use sys_util::{
-    AsRawFds, FileReadWriteAtVolatile, FileSetLen, FileSync, PunchHole, SeekHole, WriteZeroes,
+    AsRawFds, FileReadWriteAtVolatile, FileSetLen, FileSync, PunchHole, SeekHole, WriteZeroesAt,
 };
 
 #[cfg(feature = "composite-disk")]
@@ -45,7 +45,7 @@
     + FileReadWriteAtVolatile
     + PunchHole
     + Seek
-    + WriteZeroes
+    + WriteZeroesAt
     + Send
     + AsRawFds
 {
@@ -56,7 +56,7 @@
             + PunchHole
             + FileReadWriteAtVolatile
             + Seek
-            + WriteZeroes
+            + WriteZeroesAt
             + Send
             + AsRawFds,
     > DiskFile for D