pub struct VirtioBlkQueue<'a, C> { /* private fields */ }
Expand description
A queue of a virtio-blk device.
This is used to send block I/O requests to the device and receive completions. Note that calling
transport specific functions may need to be called before or after certain operations on the
VirtioBlkQueue
:
-
All request methods only enqueue the requests in the rings. They don’t notify the device of new requests, so it may or may not start processing them. Call
crate::QueueNotifier::notify
on the result ofVirtioTransport::get_submission_notifier
after queuing requests to notify the device. You can queue multiple requests and then send a single notification for all of them. -
To be notified of new completions, use the
EventFd
returned byVirtioTransport::get_completion_fd
.
When a request is submitted, the user provides a “context” of type C
that will later be
returned in the completion for that request.
Use setup_queues
to create the queues for a device.
§Examples
use rustix::fs::{memfd_create, MemfdFlags};
use std::ffi::CStr;
use std::fs::File;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::sync::{Arc, RwLock};
// Connect to the vhost-user socket and create the queues
let mut vhost = VhostUser::new("/tmp/vhost.sock", VirtioFeatureFlags::VERSION_1.bits())?;
let mut vhost = Arc::new(RwLock::new(Box::new(vhost) as Box<VirtioBlkTransport>));
let mut queues = VirtioBlkQueue::<&'static str>::setup_queues(&vhost, 1, 128)?;
// Create shared memory that is visible for the device
let mem_file: File = memfd_create("guest-ram", MemfdFlags::empty())?.into();
mem_file.set_len(512)?;
let mut mem = unsafe { memmap2::MmapMut::map_mut(&mem_file) }?;
vhost.write().unwrap().map_mem_region(mem.as_ptr() as usize, 512, mem_file.as_raw_fd(), 0)?;
// Submit a request
queues[0].read(0, &mut mem, "my-request-context")?;
vhost.read().unwrap().get_submission_notifier(0).notify()?;
// Wait for its completion
let mut done = false;
while !done {
let ret = vhost.read().unwrap().get_completion_fd(0).read();
if ret.is_err() {
continue;
}
for c in queues[0].completions() {
println!("Completed request with context {:?}, return value {}", c.context, c.ret);
done = true;
}
}
Implementations§
Source§impl<'a, C> VirtioBlkQueue<'a, C>
impl<'a, C> VirtioBlkQueue<'a, C>
Sourcepub fn setup_queues(
transport: &mut VirtioBlkTransport,
num_queues: usize,
queue_size: u16,
) -> Result<Vec<Self>, Error>
pub fn setup_queues( transport: &mut VirtioBlkTransport, num_queues: usize, queue_size: u16, ) -> Result<Vec<Self>, Error>
Creates the queues for a virtio-blk device.
Sourcepub unsafe fn readv(
&mut self,
offset: u64,
iovec: *const iovec,
iovcnt: usize,
context: C,
) -> Result<(), Error>
pub unsafe fn readv( &mut self, offset: u64, iovec: *const iovec, iovcnt: usize, context: C, ) -> Result<(), Error>
Reads from the disk image into a given iovec.
context
is an arbitrary caller-defined value that is returned in the corresponding
Completion
to allow associating the result with a specific request.
§Safety
The caller must ensure that the iovec
/iovcnt
pair is valid and all memory regions
referenced by it are safe to access.
Sourcepub unsafe fn read_raw(
&mut self,
offset: u64,
buf: *mut u8,
len: usize,
context: C,
) -> Result<(), Error>
pub unsafe fn read_raw( &mut self, offset: u64, buf: *mut u8, len: usize, context: C, ) -> Result<(), Error>
Reads from the disk image into a given buffer.
context
is an arbitrary caller-defined value that is returned in the corresponding
Completion
to allow associating the result with a specific request.
§Safety
The caller must ensure that the buffer described by buf
and len
is safe to access.
Sourcepub fn read(
&mut self,
offset: u64,
buf: &mut [u8],
context: C,
) -> Result<(), Error>
pub fn read( &mut self, offset: u64, buf: &mut [u8], context: C, ) -> Result<(), Error>
Reads from the disk image into a given byte slice.
context
is an arbitrary caller-defined value that is returned in the corresponding
Completion
to allow associating the result with a specific request.
Sourcepub unsafe fn writev(
&mut self,
offset: u64,
iovec: *const iovec,
iovcnt: usize,
context: C,
) -> Result<(), Error>
pub unsafe fn writev( &mut self, offset: u64, iovec: *const iovec, iovcnt: usize, context: C, ) -> Result<(), Error>
Writes to the disk image from a given iovec.
context
is an arbitrary caller-defined value that is returned in the corresponding
Completion
to allow associating the result with a specific request.
§Safety
The caller must ensure that the iovec
/iovcnt
pair is valid and all memory regions
referenced by it are safe to access.
Sourcepub unsafe fn write_raw(
&mut self,
offset: u64,
buf: *const u8,
len: usize,
context: C,
) -> Result<(), Error>
pub unsafe fn write_raw( &mut self, offset: u64, buf: *const u8, len: usize, context: C, ) -> Result<(), Error>
Writes to the disk image from a given buffer.
context
is an arbitrary caller-defined value that is returned in the corresponding
Completion
to allow associating the result with a specific request.
§Safety
The caller must ensure that the buffer described by buf
and len
is safe to access.
Sourcepub fn write(
&mut self,
offset: u64,
buf: &[u8],
context: C,
) -> Result<(), Error>
pub fn write( &mut self, offset: u64, buf: &[u8], context: C, ) -> Result<(), Error>
Writes to the disk image from a given byte slice.
context
is an arbitrary caller-defined value that is returned in the corresponding
Completion
to allow associating the result with a specific request.
Sourcepub fn discard(
&mut self,
offset: u64,
len: u64,
context: C,
) -> Result<(), Error>
pub fn discard( &mut self, offset: u64, len: u64, context: C, ) -> Result<(), Error>
Discards an area in the disk image.
After completion, the content of the specified area is undefined. Discard is only a hint and doing nothing is a valid implementation. This means that the discarded data may remain accessible, this is not a way to safely delete data.
context
is an arbitrary caller-defined value that is returned in the corresponding
Completion
to allow associating the result with a specific request.
Sourcepub fn write_zeroes(
&mut self,
offset: u64,
len: u64,
unmap: bool,
context: C,
) -> Result<(), Error>
pub fn write_zeroes( &mut self, offset: u64, len: u64, unmap: bool, context: C, ) -> Result<(), Error>
Zeroes out an area in the disk image.
If unmap
is true
, the area is tried to be deallocated if we know that it will read back
as all zeroes afterwards. If it is false
, allocated parts will remain allocated.
context
is an arbitrary caller-defined value that is returned in the corresponding
Completion
to allow associating the result with a specific request.
Sourcepub fn flush(&mut self, context: C) -> Result<(), Error>
pub fn flush(&mut self, context: C) -> Result<(), Error>
Flushes the disk cache.
This ensures that on successful completion, any requests that had completed before this flush request was issued are not sitting in any writeback cache, but are actually stored on disk.
context
is an arbitrary caller-defined value that is returned in the corresponding
Completion
to allow associating the result with a specific request.
Sourcepub fn completions(&mut self) -> CompletionIter<'_, 'a, C>
pub fn completions(&mut self) -> CompletionIter<'_, 'a, C>
Returns the result for any completed requests.