Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup of deprecated functions + Behavioral Clarifications #307

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
File renamed without changes.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

## Upcoming version

### Added

- \[[#307](https://github.com/rust-vmm/vm-memory/pull/304)\] Introduce `VolatileSlice::truncate`

### Changed

- \[[#307](https://github.com/rust-vmm/vm-memory/pull/304)\] Move `read_volatile_from`, `read_exact_volatile_from`,
`write_volatile_to` and `write_all_volatile_to` functions from the `GuestMemory` trait to the `Bytes` trait.

### Removed

- \[[#307](https://github.com/rust-vmm/vm-memory/pull/304)\] Remove deprecated functions `Bytes::read_from`, `Bytes::read_exact_from`,
`Bytes::write_to`, `Bytes::write_all_to`, `GuestMemory::as_slice`, `GuestMemory::as_slice_mut`, `GuestMemory::with_regions`,
`GuestMemory::with_regions_mut`, `GuestMemory::map_and_fold`, `VolatileSlice::as_ptr`, `VolatileRef::as_ptr`, and
`VolatileArrayRef::as_ptr`.

## \[v0.16.1\]

### Added
Expand Down
2 changes: 1 addition & 1 deletion coverage_config_x86_64.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"coverage_score": 91.41,
"coverage_score": 92.92,
"exclude_path": "mmap_windows.rs",
"crate_features": "backend-mmap,backend-atomic,backend-bitmap"
}
21 changes: 0 additions & 21 deletions src/bitmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ pub type MS<'a, M> = BS<'a, <<M as GuestMemory>::R as GuestMemoryRegion>::B>;
pub(crate) mod tests {
use super::*;

use std::io::Cursor;
use std::marker::PhantomData;
use std::mem::size_of_val;
use std::result::Result;
Expand Down Expand Up @@ -266,26 +265,6 @@ pub(crate) mod tests {
.unwrap();
dirty_offset += step;

// Test `read_from`.
#[allow(deprecated)] // test of deprecated functions
h.test_access(bytes, dirty_offset, BUF_SIZE, |m, addr| {
assert_eq!(
m.read_from(addr, &mut Cursor::new(&buf), BUF_SIZE).unwrap(),
BUF_SIZE
)
})
.unwrap();
dirty_offset += step;

// Test `read_exact_from`.
#[allow(deprecated)] // test of deprecated functions
h.test_access(bytes, dirty_offset, BUF_SIZE, |m, addr| {
m.read_exact_from(addr, &mut Cursor::new(&buf), BUF_SIZE)
.unwrap()
})
.unwrap();
dirty_offset += step;

// Test `store`.
h.test_access(bytes, dirty_offset, size_of_val(&val), |m, addr| {
m.store(val, addr, Ordering::Relaxed).unwrap()
Expand Down
140 changes: 109 additions & 31 deletions src/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
//! Define the `ByteValued` trait to mark that it is safe to instantiate the struct with random
//! data.

use std::io::{Read, Write};
use std::mem::{size_of, MaybeUninit};
use std::result::Result;
use std::slice::{from_raw_parts, from_raw_parts_mut};
use std::sync::atomic::Ordering;

use crate::atomic_integer::AtomicInteger;
use crate::volatile_memory::VolatileSlice;
use crate::{ReadVolatile, WriteVolatile};

/// Types for which it is safe to initialize from raw data.
///
Expand Down Expand Up @@ -227,16 +227,41 @@ pub trait Bytes<A> {
/// Returns the number of bytes written. The number of bytes written can
/// be less than the length of the slice if there isn't enough room in the
/// container.
///
/// If the given slice is empty (e.g. has length 0), always returns `Ok(0)`, even if `addr`
/// is otherwise out of bounds. However, if the container is empty, it will
/// return an error (unless the slice is also empty, in which case the above takes precedence).
///
/// ```rust
/// # use vm_memory::{Bytes, VolatileMemoryError, VolatileSlice};
/// let mut arr = [1, 2, 3, 4, 5];
/// let slice = VolatileSlice::from(arr.as_mut_slice());
///
/// assert_eq!(slice.write(&[1, 2, 3], 0).unwrap(), 3);
/// assert_eq!(slice.write(&[1, 2, 3], 3).unwrap(), 2);
/// assert!(matches!(
/// slice.write(&[1, 2, 3], 5).unwrap_err(),
/// VolatileMemoryError::OutOfBounds { addr: 5 }
/// ));
/// assert_eq!(slice.write(&[], 5).unwrap(), 0);
/// ```
fn write(&self, buf: &[u8], addr: A) -> Result<usize, Self::E>;

/// Reads data from the container at `addr` into a slice.
///
/// Returns the number of bytes read. The number of bytes read can be less than the length
/// of the slice if there isn't enough data within the container.
///
/// If the given slice is empty (e.g. has length 0), always returns `Ok(0)`, even if `addr`
/// is otherwise out of bounds. However, if the container is empty, it will
/// return an error (unless the slice is also empty, in which case the above takes precedence).
fn read(&self, buf: &mut [u8], addr: A) -> Result<usize, Self::E>;

/// Writes the entire content of a slice into the container at `addr`.
///
/// If the given slice is empty (e.g. has length 0), always returns `Ok(0)`, even if `addr`
/// is otherwise out of bounds.
///
/// # Errors
///
/// Returns an error if there isn't enough space within the container to write the entire slice.
Expand All @@ -245,6 +270,9 @@ pub trait Bytes<A> {

/// Reads data from the container at `addr` to fill an entire slice.
///
/// If the given slice is empty (e.g. has length 0), always returns `Ok(0)`, even if `addr`
/// is otherwise out of bounds.
///
/// # Errors
///
/// Returns an error if there isn't enough data within the container to fill the entire slice.
Expand Down Expand Up @@ -277,20 +305,52 @@ pub trait Bytes<A> {
self.read_slice(result.as_mut_slice(), addr).map(|_| result)
}

/// Reads up to `count` bytes from an object and writes them into the container at `addr`.
/// Reads up to `count` bytes from `src` and writes them into the container at `addr`.
/// Unlike `VolatileRead::read_volatile`, this function retries on `EINTR` being returned from
/// the underlying I/O `read` operation.
///
/// Returns the number of bytes written into the container.
///
/// # Arguments
/// * `addr` - Begin writing at this address.
/// * `src` - Copy from `src` into the container.
/// * `count` - Copy `count` bytes from `src` into the container.
#[deprecated(
note = "Use `.read_volatile_from` or the functions of the `ReadVolatile` trait instead"
)]
fn read_from<F>(&self, addr: A, src: &mut F, count: usize) -> Result<usize, Self::E>
///
/// # Examples
///
/// * Read bytes from /dev/urandom (uses the `backend-mmap` feature)
///
/// ```
/// # #[cfg(feature = "backend-mmap")]
/// # {
/// # use vm_memory::{Address, GuestMemory, Bytes, GuestAddress, GuestMemoryMmap};
/// # use std::fs::File;
/// # use std::path::Path;
/// #
/// # let start_addr = GuestAddress(0x1000);
/// # let gm = GuestMemoryMmap::<()>::from_ranges(&vec![(start_addr, 0x400)])
/// # .expect("Could not create guest memory");
/// # let addr = GuestAddress(0x1010);
/// # let mut file = if cfg!(unix) {
/// let mut file = File::open(Path::new("/dev/urandom")).expect("Could not open /dev/urandom");
/// # file
/// # } else {
/// # File::open(Path::new("c:\\Windows\\system32\\ntoskrnl.exe"))
/// # .expect("Could not open c:\\Windows\\system32\\ntoskrnl.exe")
/// # };
///
/// gm.read_volatile_from(addr, &mut file, 128)
/// .expect("Could not read from /dev/urandom into guest memory");
///
/// let read_addr = addr.checked_add(8).expect("Could not compute read address");
/// let rand_val: u32 = gm
/// .read_obj(read_addr)
/// .expect("Could not read u32 val from /dev/urandom");
/// # }
/// ```
fn read_volatile_from<F>(&self, addr: A, src: &mut F, count: usize) -> Result<usize, Self::E>
where
F: Read;
F: ReadVolatile;

/// Reads exactly `count` bytes from an object and writes them into the container at `addr`.
///
Expand All @@ -303,27 +363,28 @@ pub trait Bytes<A> {
/// * `addr` - Begin writing at this address.
/// * `src` - Copy from `src` into the container.
/// * `count` - Copy exactly `count` bytes from `src` into the container.
#[deprecated(
note = "Use `.read_exact_volatile_from` or the functions of the `ReadVolatile` trait instead"
)]
fn read_exact_from<F>(&self, addr: A, src: &mut F, count: usize) -> Result<(), Self::E>
fn read_exact_volatile_from<F>(
&self,
addr: A,
src: &mut F,
count: usize,
) -> Result<(), Self::E>
where
F: Read;
F: ReadVolatile;

/// Reads up to `count` bytes from the container at `addr` and writes them it into an object.
/// Reads up to `count` bytes from the container at `addr` and writes them into `dst`.
/// Unlike `VolatileWrite::write_volatile`, this function retries on `EINTR` being returned by
/// the underlying I/O `write` operation.
///
/// Returns the number of bytes written into the object.
///
/// # Arguments
/// * `addr` - Begin reading from this address.
/// * `dst` - Copy from the container to `dst`.
/// * `count` - Copy `count` bytes from the container to `dst`.
#[deprecated(
note = "Use `.write_volatile_to` or the functions of the `WriteVolatile` trait instead"
)]
fn write_to<F>(&self, addr: A, dst: &mut F, count: usize) -> Result<usize, Self::E>
fn write_volatile_to<F>(&self, addr: A, dst: &mut F, count: usize) -> Result<usize, Self::E>
where
F: Write;
F: WriteVolatile;

/// Reads exactly `count` bytes from the container at `addr` and writes them into an object.
///
Expand All @@ -336,12 +397,9 @@ pub trait Bytes<A> {
/// * `addr` - Begin reading from this address.
/// * `dst` - Copy from the container to `dst`.
/// * `count` - Copy exactly `count` bytes from the container to `dst`.
#[deprecated(
note = "Use `.write_all_volatile_to` or the functions of the `WriteVolatile` trait instead"
)]
fn write_all_to<F>(&self, addr: A, dst: &mut F, count: usize) -> Result<(), Self::E>
fn write_all_volatile_to<F>(&self, addr: A, dst: &mut F, count: usize) -> Result<(), Self::E>
where
F: Write;
F: WriteVolatile;

/// Atomically store a value at the specified address.
fn store<T: AtomicAccess>(&self, val: T, addr: A, order: Ordering) -> Result<(), Self::E>;
Expand Down Expand Up @@ -481,30 +539,50 @@ pub(crate) mod tests {
Ok(())
}

fn read_from<F>(&self, _: usize, _: &mut F, _: usize) -> Result<usize, Self::E>
fn read_volatile_from<F>(
&self,
_addr: usize,
_src: &mut F,
_count: usize,
) -> Result<usize, Self::E>
where
F: Read,
F: ReadVolatile,
{
unimplemented!()
}

fn read_exact_from<F>(&self, _: usize, _: &mut F, _: usize) -> Result<(), Self::E>
fn read_exact_volatile_from<F>(
&self,
_addr: usize,
_src: &mut F,
_count: usize,
) -> Result<(), Self::E>
where
F: Read,
F: ReadVolatile,
{
unimplemented!()
}

fn write_to<F>(&self, _: usize, _: &mut F, _: usize) -> Result<usize, Self::E>
fn write_volatile_to<F>(
&self,
_addr: usize,
_dst: &mut F,
_count: usize,
) -> Result<usize, Self::E>
where
F: Write,
F: WriteVolatile,
{
unimplemented!()
}

fn write_all_to<F>(&self, _: usize, _: &mut F, _: usize) -> Result<(), Self::E>
fn write_all_volatile_to<F>(
&self,
_addr: usize,
_dst: &mut F,
_count: usize,
) -> Result<(), Self::E>
where
F: Write,
F: WriteVolatile,
{
unimplemented!()
}
Expand Down
Loading