Skip to content

Commit 4562ffd

Browse files
committed
add QueueStateT::pop_descriptor_chain
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]>
1 parent 2f01935 commit 4562ffd

File tree

4 files changed

+52
-7
lines changed

4 files changed

+52
-7
lines changed

crates/virtio-queue/src/iterator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ pub struct AvailIter<'b, M> {
102102
impl<'b, M> AvailIter<'b, M>
103103
where
104104
M: Deref,
105-
M::Target: GuestMemory + Sized,
105+
M::Target: GuestMemory,
106106
{
107107
/// Create a new instance of `AvailInter`.
108108
///

crates/virtio-queue/src/lib.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ pub trait QueueStateT: for<'a> QueueStateGuard<'a> {
152152
fn set_event_idx(&mut self, enabled: bool);
153153

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

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

191193
/// Set the index for the next descriptor in the used ring.
192194
fn set_next_used(&mut self, next_used: u16);
195+
196+
/// Pop and return the next available descriptor chain, or `None` when there are no more
197+
/// descriptor chains available.
198+
///
199+
/// This enables the consumption of available descriptor chains in a "one at a time"
200+
/// manner, without having to hold a borrow after the method returns.
201+
fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>>
202+
where
203+
M: Clone + Deref,
204+
M::Target: GuestMemory;
193205
}

crates/virtio-queue/src/state.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ use crate::defs::{
1919
VIRTQ_USED_ELEMENT_SIZE, VIRTQ_USED_F_NO_NOTIFY, VIRTQ_USED_RING_HEADER_SIZE,
2020
VIRTQ_USED_RING_META_SIZE,
2121
};
22-
use crate::{error, AvailIter, Descriptor, Error, QueueStateGuard, QueueStateT, VirtqUsedElem};
22+
use crate::{
23+
error, AvailIter, Descriptor, DescriptorChain, Error, QueueStateGuard, QueueStateT,
24+
VirtqUsedElem,
25+
};
2326

2427
/// Struct to maintain information and manipulate state of a virtio queue.
2528
#[derive(Clone, Debug)]
@@ -63,7 +66,7 @@ impl QueueState {
6366
pub fn iter<M>(&mut self, mem: M) -> Result<AvailIter<'_, M>, Error>
6467
where
6568
M: Deref,
66-
M::Target: GuestMemory + Sized,
69+
M::Target: GuestMemory,
6770
{
6871
self.avail_idx(mem.deref(), Ordering::Acquire)
6972
.map(move |idx| AvailIter::new(mem, idx, self))
@@ -299,7 +302,10 @@ impl QueueStateT for QueueState {
299302
self.event_idx_enabled = enabled;
300303
}
301304

302-
fn avail_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> {
305+
fn avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>
306+
where
307+
M: GuestMemory + ?Sized,
308+
{
303309
let addr = self
304310
.avail_ring
305311
.checked_add(2)
@@ -438,4 +444,19 @@ impl QueueStateT for QueueState {
438444
fn set_next_used(&mut self, next_used: u16) {
439445
self.next_used = Wrapping(next_used);
440446
}
447+
448+
fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>>
449+
where
450+
M: Clone + Deref,
451+
M::Target: GuestMemory,
452+
{
453+
// Default, iter-based impl. Will be subsequently improved.
454+
match self.iter(mem) {
455+
Ok(mut iter) => iter.next(),
456+
Err(e) => {
457+
error!("Iterator error {}", e);
458+
None
459+
}
460+
}
461+
}
441462
}

crates/virtio-queue/src/state_sync.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
44

55
use std::num::Wrapping;
6+
use std::ops::Deref;
67
use std::sync::atomic::Ordering;
78
use std::sync::{Arc, Mutex, MutexGuard};
89

910
use vm_memory::GuestMemory;
1011

11-
use crate::{Error, QueueState, QueueStateGuard, QueueStateT};
12+
use crate::{DescriptorChain, Error, QueueState, QueueStateGuard, QueueStateT};
1213

1314
/// Struct to maintain information and manipulate state of a virtio queue for multi-threaded
1415
/// context.
@@ -103,7 +104,10 @@ impl QueueStateT for QueueStateSync {
103104
self.lock_state().set_event_idx(enabled);
104105
}
105106

106-
fn avail_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> {
107+
fn avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>
108+
where
109+
M: GuestMemory + ?Sized,
110+
{
107111
self.lock_state().avail_idx(mem, order)
108112
}
109113

@@ -147,6 +151,14 @@ impl QueueStateT for QueueStateSync {
147151
fn set_next_used(&mut self, next_used: u16) {
148152
self.lock_state().set_next_used(next_used);
149153
}
154+
155+
fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>>
156+
where
157+
M: Clone + Deref,
158+
M::Target: GuestMemory,
159+
{
160+
self.lock_state().pop_descriptor_chain(mem)
161+
}
150162
}
151163

152164
#[cfg(test)]

0 commit comments

Comments
 (0)