diff options
Diffstat (limited to 'devices/src/virtio/p9.rs')
-rw-r--r-- | devices/src/virtio/p9.rs | 147 |
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()?; |