summary refs log tree commit diff
path: root/devices/src/virtio/p9.rs
diff options
context:
space:
mode:
Diffstat (limited to 'devices/src/virtio/p9.rs')
-rw-r--r--devices/src/virtio/p9.rs147
1 files changed, 6 insertions, 141 deletions
diff --git a/devices/src/virtio/p9.rs b/devices/src/virtio/p9.rs
index b5d0842..9785eb7 100644
--- a/devices/src/virtio/p9.rs
+++ b/devices/src/virtio/p9.rs
@@ -4,8 +4,7 @@
 
 use std::cmp::min;
 use std::fmt::{self, Display};
-use std::io::{self, Read, Write};
-use std::iter::Peekable;
+use std::io::{self, Write};
 use std::mem;
 use std::os::unix::io::RawFd;
 use std::path::{Path, PathBuf};
@@ -15,12 +14,10 @@ use std::sync::Arc;
 use std::thread;
 
 use p9;
-use sys_util::{
-    error, warn, Error as SysError, EventFd, GuestAddress, GuestMemory, PollContext, PollToken,
-};
+use sys_util::{error, warn, Error as SysError, EventFd, GuestMemory, PollContext, PollToken};
 use virtio_sys::vhost::VIRTIO_F_VERSION_1;
 
-use super::{DescriptorChain, Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_9P};
+use super::{Queue, Reader, VirtioDevice, Writer, INTERRUPT_STATUS_USED_RING, TYPE_9P};
 
 const QUEUE_SIZE: u16 = 128;
 const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE];
@@ -45,8 +42,6 @@ pub enum P9Error {
     NoReadableDescriptors,
     /// A request is missing writable descriptors.
     NoWritableDescriptors,
-    /// A descriptor contained an invalid guest address range.
-    InvalidGuestAddress(GuestAddress, u32),
     /// Failed to signal the virio used queue.
     SignalUsedQueue(SysError),
     /// An internal I/O error occurred.
@@ -76,11 +71,6 @@ impl Display for P9Error {
             ReadQueueEventFd(err) => write!(f, "failed to read from virtio queue EventFd: {}", err),
             NoReadableDescriptors => write!(f, "request does not have any readable descriptors"),
             NoWritableDescriptors => write!(f, "request does not have any writable descriptors"),
-            InvalidGuestAddress(addr, len) => write!(
-                f,
-                "descriptor contained invalid guest address range: address = {}, len = {}",
-                addr, len
-            ),
             SignalUsedQueue(err) => write!(f, "failed to signal used queue: {}", err),
             Internal(err) => write!(f, "P9 internal server error: {}", err),
         }
@@ -89,122 +79,6 @@ impl Display for P9Error {
 
 pub type P9Result<T> = result::Result<T, P9Error>;
 
-struct Reader<'a, I>
-where
-    I: Iterator<Item = DescriptorChain<'a>>,
-{
-    mem: &'a GuestMemory,
-    offset: u32,
-    iter: Peekable<I>,
-}
-
-impl<'a, I> Read for Reader<'a, I>
-where
-    I: Iterator<Item = DescriptorChain<'a>>,
-{
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        let needs_advance = if let Some(current) = self.iter.peek() {
-            self.offset >= current.len
-        } else {
-            false
-        };
-
-        if needs_advance {
-            self.offset = 0;
-            self.iter.next();
-        }
-
-        if let Some(current) = self.iter.peek() {
-            debug_assert!(current.is_read_only());
-            let addr = current
-                .addr
-                .checked_add(self.offset as u64)
-                .ok_or_else(|| {
-                    io::Error::new(
-                        io::ErrorKind::InvalidData,
-                        P9Error::InvalidGuestAddress(current.addr, current.len),
-                    )
-                })?;
-            let len = min(buf.len(), (current.len - self.offset) as usize);
-            let count = self
-                .mem
-                .read_at_addr(&mut buf[..len], addr)
-                .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
-
-            // |count| has to fit into a u32 because it must be less than or equal to
-            // |current.len|, which does fit into a u32.
-            self.offset += count as u32;
-
-            Ok(count)
-        } else {
-            // Nothing left to read.
-            Ok(0)
-        }
-    }
-}
-
-struct Writer<'a, I>
-where
-    I: Iterator<Item = DescriptorChain<'a>>,
-{
-    mem: &'a GuestMemory,
-    bytes_written: u32,
-    offset: u32,
-    iter: Peekable<I>,
-}
-
-impl<'a, I> Write for Writer<'a, I>
-where
-    I: Iterator<Item = DescriptorChain<'a>>,
-{
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let needs_advance = if let Some(current) = self.iter.peek() {
-            self.offset >= current.len
-        } else {
-            false
-        };
-
-        if needs_advance {
-            self.offset = 0;
-            self.iter.next();
-        }
-
-        if let Some(current) = self.iter.peek() {
-            debug_assert!(current.is_write_only());
-            let addr = current
-                .addr
-                .checked_add(self.offset as u64)
-                .ok_or_else(|| {
-                    io::Error::new(
-                        io::ErrorKind::InvalidData,
-                        P9Error::InvalidGuestAddress(current.addr, current.len),
-                    )
-                })?;
-
-            let len = min(buf.len(), (current.len - self.offset) as usize);
-            let count = self
-                .mem
-                .write_at_addr(&buf[..len], addr)
-                .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
-
-            // |count| has to fit into a u32 because it must be less than or equal to
-            // |current.len|, which does fit into a u32.
-            self.offset += count as u32;
-            self.bytes_written += count as u32;
-
-            Ok(count)
-        } else {
-            // No more room in the descriptor chain.
-            Ok(0)
-        }
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        // Nothing to flush since the writes go straight into the buffer.
-        Ok(())
-    }
-}
-
 struct Worker {
     mem: GuestMemory,
     queue: Queue,
@@ -223,24 +97,15 @@ impl Worker {
 
     fn process_queue(&mut self) -> P9Result<()> {
         while let Some(avail_desc) = self.queue.pop(&self.mem) {
-            let mut reader = Reader {
-                mem: &self.mem,
-                offset: 0,
-                iter: avail_desc.clone().into_iter().readable().peekable(),
-            };
-            let mut writer = Writer {
-                mem: &self.mem,
-                bytes_written: 0,
-                offset: 0,
-                iter: avail_desc.clone().into_iter().writable().peekable(),
-            };
+            let mut reader = Reader::new(&self.mem, avail_desc.clone());
+            let mut writer = Writer::new(&self.mem, avail_desc.clone());
 
             self.server
                 .handle_message(&mut reader, &mut writer)
                 .map_err(P9Error::Internal)?;
 
             self.queue
-                .add_used(&self.mem, avail_desc.index, writer.bytes_written);
+                .add_used(&self.mem, avail_desc.index, writer.bytes_written() as u32);
         }
 
         self.signal_used_queue()?;