Skip to content

Commit

Permalink
add QueueStateT::pop_descriptor_chain
Browse files Browse the repository at this point in the history
This commit also introduces a relaxation of the trait bound on the
generic type parameter `M` for `QueueStateT::avail_idx` (i.e. it no
longer has to be `Sized`, as it was implicitly the case before). This
change reduces the number of trait bounds that have to be explicitly
propagated to the newly introduced methods. We should apply a similar
update to the rest of the interface as well (tracked by rust-vmm#152).

Signed-off-by: Alexandru Agache <[email protected]>
  • Loading branch information
alexandruag committed Mar 30, 2022
1 parent a332453 commit 4b3c905
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 7 deletions.
2 changes: 1 addition & 1 deletion crates/virtio-queue/src/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub struct AvailIter<'b, M> {
impl<'b, M> AvailIter<'b, M>
where
M: Deref,
M::Target: GuestMemory + Sized,
M::Target: GuestMemory,
{
/// Create a new instance of `AvailInter`.
///
Expand Down
14 changes: 13 additions & 1 deletion crates/virtio-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ pub trait QueueStateT: for<'a> QueueStateGuard<'a> {
fn set_event_idx(&mut self, enabled: bool);

/// Read the `idx` field from the available ring.
fn avail_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>;
fn avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>
where
M: GuestMemory + ?Sized;

/// Read the `idx` field from the used ring.
fn used_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>;
Expand Down Expand Up @@ -193,4 +195,14 @@ pub trait QueueStateT: for<'a> QueueStateGuard<'a> {

/// Set the index for the next descriptor in the used ring.
fn set_next_used(&mut self, next_used: u16);

/// Pop and return the next available descriptor chain, or `None` when there are no more
/// descriptor chains available.
///
/// This enables the consumption of available descriptor chains in a "one at a time"
/// manner, without having to hold a borrow after the method returns.
fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>>
where
M: Clone + Deref,
M::Target: GuestMemory;
}
27 changes: 24 additions & 3 deletions crates/virtio-queue/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ use crate::defs::{
VIRTQ_USED_ELEMENT_SIZE, VIRTQ_USED_F_NO_NOTIFY, VIRTQ_USED_RING_HEADER_SIZE,
VIRTQ_USED_RING_META_SIZE,
};
use crate::{error, AvailIter, Descriptor, Error, QueueStateGuard, QueueStateT, VirtqUsedElem};
use crate::{
error, AvailIter, Descriptor, DescriptorChain, Error, QueueStateGuard, QueueStateT,
VirtqUsedElem,
};

/// Struct to maintain information and manipulate state of a virtio queue.
///
Expand Down Expand Up @@ -71,7 +74,7 @@ impl QueueState {
pub fn iter<M>(&mut self, mem: M) -> Result<AvailIter<'_, M>, Error>
where
M: Deref,
M::Target: GuestMemory + Sized,
M::Target: GuestMemory,
{
self.avail_idx(mem.deref(), Ordering::Acquire)
.map(move |idx| AvailIter::new(mem, idx, self))
Expand Down Expand Up @@ -311,7 +314,10 @@ impl QueueStateT for QueueState {
self.event_idx_enabled = enabled;
}

fn avail_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> {
fn avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>
where
M: GuestMemory + ?Sized,
{
let addr = self
.avail_ring
.checked_add(2)
Expand Down Expand Up @@ -450,4 +456,19 @@ impl QueueStateT for QueueState {
fn set_next_used(&mut self, next_used: u16) {
self.next_used = Wrapping(next_used);
}

fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>>
where
M: Clone + Deref,
M::Target: GuestMemory,
{
// Default, iter-based impl. Will be subsequently improved.
match self.iter(mem) {
Ok(mut iter) => iter.next(),
Err(e) => {
error!("Iterator error {}", e);
None
}
}
}
}
16 changes: 14 additions & 2 deletions crates/virtio-queue/src/state_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause

use std::num::Wrapping;
use std::ops::Deref;
use std::sync::atomic::Ordering;
use std::sync::{Arc, Mutex, MutexGuard};

use vm_memory::GuestMemory;

use crate::{Error, QueueState, QueueStateGuard, QueueStateT};
use crate::{DescriptorChain, Error, QueueState, QueueStateGuard, QueueStateT};

/// Struct to maintain information and manipulate state of a virtio queue for multi-threaded
/// context.
Expand Down Expand Up @@ -107,7 +108,10 @@ impl QueueStateT for QueueStateSync {
self.lock_state().set_event_idx(enabled);
}

fn avail_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> {
fn avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>
where
M: GuestMemory + ?Sized,
{
self.lock_state().avail_idx(mem, order)
}

Expand Down Expand Up @@ -151,6 +155,14 @@ impl QueueStateT for QueueStateSync {
fn set_next_used(&mut self, next_used: u16) {
self.lock_state().set_next_used(next_used);
}

fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>>
where
M: Clone + Deref,
M::Target: GuestMemory,
{
self.lock_state().pop_descriptor_chain(mem)
}
}

#[cfg(test)]
Expand Down

0 comments on commit 4b3c905

Please sign in to comment.