summary refs log tree commit diff
path: root/devices/src/virtio/descriptor_utils.rs
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2019-09-19 11:23:46 -0700
committerCommit Bot <commit-bot@chromium.org>2019-11-05 19:26:37 +0000
commit102278e944dcdc9a489a41644a53c225d8985380 (patch)
tree539cba723f143a34f33b5b2351bd4117d81cfa30 /devices/src/virtio/descriptor_utils.rs
parent21556bf5d8dbf49f9aa29782a96e12b5579e5e58 (diff)
downloadcrosvm-102278e944dcdc9a489a41644a53c225d8985380.tar
crosvm-102278e944dcdc9a489a41644a53c225d8985380.tar.gz
crosvm-102278e944dcdc9a489a41644a53c225d8985380.tar.bz2
crosvm-102278e944dcdc9a489a41644a53c225d8985380.tar.lz
crosvm-102278e944dcdc9a489a41644a53c225d8985380.tar.xz
crosvm-102278e944dcdc9a489a41644a53c225d8985380.tar.zst
crosvm-102278e944dcdc9a489a41644a53c225d8985380.zip
devices: add into_iovec() for DescriptorUtils
This allows the conversion of (part of) a descriptor chain into an iovec
suitable for use with sys_util functions like send_with_fds().

BUG=None
TEST=./build_test.py

Change-Id: I4e3f7d9c1175c1173661b0661d3fa15d1da72d1a
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1815417
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'devices/src/virtio/descriptor_utils.rs')
-rw-r--r--devices/src/virtio/descriptor_utils.rs50
1 files changed, 49 insertions, 1 deletions
diff --git a/devices/src/virtio/descriptor_utils.rs b/devices/src/virtio/descriptor_utils.rs
index 0c228ed..00c52c9 100644
--- a/devices/src/virtio/descriptor_utils.rs
+++ b/devices/src/virtio/descriptor_utils.rs
@@ -6,12 +6,15 @@ use std::cmp;
 use std::collections::VecDeque;
 use std::fmt::{self, Display};
 use std::io::{self, Read, Write};
+use std::marker::PhantomData;
 use std::mem::{size_of, MaybeUninit};
 use std::ptr::copy_nonoverlapping;
 use std::result;
 
 use data_model::{DataInit, Le16, Le32, Le64, VolatileMemory, VolatileMemoryError, VolatileSlice};
-use sys_util::{FileReadWriteAtVolatile, FileReadWriteVolatile, GuestAddress, GuestMemory};
+use sys_util::{
+    FileReadWriteAtVolatile, FileReadWriteVolatile, GuestAddress, GuestMemory, IntoIovec,
+};
 
 use super::DescriptorChain;
 
@@ -177,6 +180,27 @@ impl<'a> DescriptorChainConsumer<'a> {
             Err(Error::SplitOutOfBounds(offset))
         }
     }
+
+    fn get_iovec(&mut self, len: usize) -> io::Result<DescriptorIovec<'a>> {
+        let mut iovec = Vec::new();
+
+        self.consume(len, |bufs| {
+            let mut total = 0;
+            for vs in bufs {
+                iovec.push(libc::iovec {
+                    iov_base: vs.as_ptr() as *mut libc::c_void,
+                    iov_len: vs.size() as usize,
+                });
+                total += vs.size() as usize;
+            }
+            Ok(total)
+        })?;
+
+        Ok(DescriptorIovec {
+            iovec,
+            mem: PhantomData,
+        })
+    }
 }
 
 /// Provides high-level interface over the sequence of memory regions
@@ -303,6 +327,12 @@ impl<'a> Reader<'a> {
     pub fn split_at(&mut self, offset: usize) -> Result<Reader<'a>> {
         self.buffer.split_at(offset).map(|buffer| Reader { buffer })
     }
+
+    /// Returns a DescriptorIovec for the next `len` bytes of the descriptor chain
+    /// buffer, which can be used as an IntoIovec.
+    pub fn get_iovec(&mut self, len: usize) -> io::Result<DescriptorIovec<'a>> {
+        self.buffer.get_iovec(len)
+    }
 }
 
 impl<'a> io::Read for Reader<'a> {
@@ -442,6 +472,12 @@ impl<'a> Writer<'a> {
     pub fn split_at(&mut self, offset: usize) -> Result<Writer<'a>> {
         self.buffer.split_at(offset).map(|buffer| Writer { buffer })
     }
+
+    /// Returns a DescriptorIovec for the next `len` bytes of the descriptor chain
+    /// buffer, which can be used as an IntoIovec.
+    pub fn get_iovec(&mut self, len: usize) -> io::Result<DescriptorIovec<'a>> {
+        self.buffer.get_iovec(len)
+    }
 }
 
 impl<'a> io::Write for Writer<'a> {
@@ -471,6 +507,18 @@ impl<'a> io::Write for Writer<'a> {
     }
 }
 
+pub struct DescriptorIovec<'a> {
+    iovec: Vec<libc::iovec>,
+    mem: PhantomData<&'a GuestMemory>,
+}
+
+// Safe because the lifetime of DescriptorIovec is tied to the underlying GuestMemory.
+unsafe impl<'a> IntoIovec for DescriptorIovec<'a> {
+    fn into_iovec(&self) -> Vec<libc::iovec> {
+        self.iovec.clone()
+    }
+}
+
 const VIRTQ_DESC_F_NEXT: u16 = 0x1;
 const VIRTQ_DESC_F_WRITE: u16 = 0x2;