Skip to content
This repository was archived by the owner on Oct 24, 2022. It is now read-only.

Commit 8cfe7ce

Browse files
andreeaflorescuSebastien Boeuf
authored and
Sebastien Boeuf
committed
integrate virtio-queue
The virtio-queue interface is updated to take into consideration error cases and to export a single Queue. Signed-off-by: Andreea Florescu <fandree@amazon.com>
1 parent a94e14e commit 8cfe7ce

File tree

5 files changed

+79
-51
lines changed

5 files changed

+79
-51
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ libc = ">=0.2.39"
1212
log = ">=0.4.6"
1313
vhost = { version = "0.4", features = ["vhost-user-slave"] }
1414
virtio-bindings = "0.1"
15-
virtio-queue = "0.4"
15+
virtio-queue = "0.5.0"
1616
vm-memory = {version = ">=0.7", features = ["backend-mmap", "backend-atomic"]}
1717
vmm-sys-util = "0.10"
1818

src/backend.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ pub mod tests {
547547
);
548548
backend.update_memory(mem.clone()).unwrap();
549549

550-
let vring = VringRwLock::new(mem, 0x1000);
550+
let vring = VringRwLock::new(mem, 0x1000).unwrap();
551551
backend
552552
.handle_event(0x1, EventSet::IN, &[vring], 0)
553553
.unwrap();

src/event_loop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ mod tests {
246246
let mem = GuestMemoryAtomic::new(
247247
GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0x100000), 0x10000)]).unwrap(),
248248
);
249-
let vring = VringRwLock::new(mem, 0x1000);
249+
let vring = VringRwLock::new(mem, 0x1000).unwrap();
250250
let backend = Arc::new(Mutex::new(MockVhostBackend::new()));
251251

252252
let handler = VringEpollHandler::new(backend, vec![vring], 0x1).unwrap();

src/handler.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use vhost::vhost_user::{
2020
VhostUserSlaveReqHandlerMut,
2121
};
2222
use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
23+
use virtio_queue::{Error as VirtQueError, QueueT};
2324
use vm_memory::bitmap::Bitmap;
2425
use vm_memory::mmap::NewBitmap;
2526
use vm_memory::{
@@ -38,6 +39,8 @@ const MAX_MEM_SLOTS: u64 = 32;
3839
#[derive(Debug)]
3940
/// Errors related to vhost-user handler.
4041
pub enum VhostUserHandlerError {
42+
/// Failed to create a `Vring`.
43+
CreateVring(VirtQueError),
4144
/// Failed to create vring worker.
4245
CreateEpollHandler(VringEpollError),
4346
/// Failed to spawn vring worker.
@@ -49,6 +52,9 @@ pub enum VhostUserHandlerError {
4952
impl std::fmt::Display for VhostUserHandlerError {
5053
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
5154
match self {
55+
VhostUserHandlerError::CreateVring(e) => {
56+
write!(f, "failed to create vring: {}", e)
57+
}
5258
VhostUserHandlerError::CreateEpollHandler(e) => {
5359
write!(f, "failed to create vring epoll handler: {}", e)
5460
}
@@ -101,7 +107,8 @@ where
101107

102108
let mut vrings = Vec::new();
103109
for _ in 0..num_queues {
104-
let vring = V::new(atomic_mem.clone(), max_queue_size as u16);
110+
let vring = V::new(atomic_mem.clone(), max_queue_size as u16)
111+
.map_err(VhostUserHandlerError::CreateVring)?;
105112
vrings.push(vring);
106113
}
107114

@@ -329,7 +336,9 @@ where
329336
let used_ring = self.vmm_va_to_gpa(used).map_err(|e| {
330337
VhostUserError::ReqHandlerError(io::Error::new(io::ErrorKind::Other, e))
331338
})?;
332-
self.vrings[index as usize].set_queue_info(desc_table, avail_ring, used_ring);
339+
self.vrings[index as usize]
340+
.set_queue_info(desc_table, avail_ring, used_ring)
341+
.map_err(|_| VhostUserError::InvalidParam)?;
333342
Ok(())
334343
} else {
335344
Err(VhostUserError::InvalidParam)

src/vring.rs

Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::os::unix::io::{FromRawFd, IntoRawFd};
1212
use std::result::Result;
1313
use std::sync::{Arc, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
1414

15-
use virtio_queue::{Error as VirtQueError, Queue};
15+
use virtio_queue::{Error as VirtQueError, Queue, QueueT};
1616
use vm_memory::{GuestAddress, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap};
1717
use vmm_sys_util::eventfd::EventFd;
1818

@@ -32,7 +32,9 @@ pub trait VringT<M: GuestAddressSpace>:
3232
for<'a> VringStateGuard<'a, M> + for<'a> VringStateMutGuard<'a, M>
3333
{
3434
/// Create a new instance of Vring.
35-
fn new(mem: M, max_queue_size: u16) -> Self;
35+
fn new(mem: M, max_queue_size: u16) -> Result<Self, VirtQueError>
36+
where
37+
Self: Sized;
3638

3739
/// Get an immutable reference to the kick event fd.
3840
fn get_ref(&self) -> <Self as VringStateGuard<M>>::G;
@@ -59,7 +61,12 @@ pub trait VringT<M: GuestAddressSpace>:
5961
fn set_enabled(&self, enabled: bool);
6062

6163
/// Set queue addresses for descriptor table, available ring and used ring.
62-
fn set_queue_info(&self, desc_table: u64, avail_ring: u64, used_ring: u64);
64+
fn set_queue_info(
65+
&self,
66+
desc_table: u64,
67+
avail_ring: u64,
68+
used_ring: u64,
69+
) -> Result<(), VirtQueError>;
6370

6471
/// Get queue next avail head.
6572
fn queue_next_avail(&self) -> u16;
@@ -94,38 +101,41 @@ pub trait VringT<M: GuestAddressSpace>:
94101
/// This struct maintains all information of a virito queue, and could be used as an `VringT`
95102
/// object for single-threaded context.
96103
pub struct VringState<M: GuestAddressSpace = GuestMemoryAtomic<GuestMemoryMmap>> {
97-
queue: Queue<M>,
104+
queue: Queue,
98105
kick: Option<EventFd>,
99106
call: Option<EventFd>,
100107
err: Option<EventFd>,
101108
enabled: bool,
109+
mem: M,
102110
}
103111

104112
impl<M: GuestAddressSpace> VringState<M> {
105113
/// Create a new instance of Vring.
106-
fn new(mem: M, max_queue_size: u16) -> Self {
107-
VringState {
108-
queue: Queue::new(mem, max_queue_size),
114+
fn new(mem: M, max_queue_size: u16) -> Result<Self, VirtQueError> {
115+
Ok(VringState {
116+
queue: Queue::new(max_queue_size)?,
109117
kick: None,
110118
call: None,
111119
err: None,
112120
enabled: false,
113-
}
121+
mem,
122+
})
114123
}
115124

116125
/// Get an immutable reference to the underlying raw `Queue` object.
117-
pub fn get_queue(&self) -> &Queue<M> {
126+
pub fn get_queue(&self) -> &Queue {
118127
&self.queue
119128
}
120129

121130
/// Get a mutable reference to the underlying raw `Queue` object.
122-
pub fn get_queue_mut(&mut self) -> &mut Queue<M> {
131+
pub fn get_queue_mut(&mut self) -> &mut Queue {
123132
&mut self.queue
124133
}
125134

126135
/// Add an used descriptor into the used queue.
127136
pub fn add_used(&mut self, desc_index: u16, len: u32) -> Result<(), VirtQueError> {
128-
self.queue.add_used(desc_index, len)
137+
self.queue
138+
.add_used(self.mem.memory().deref(), desc_index, len)
129139
}
130140

131141
/// Notify the vhost-user master that used descriptors have been put into the used queue.
@@ -139,17 +149,17 @@ impl<M: GuestAddressSpace> VringState<M> {
139149

140150
/// Enable event notification for queue.
141151
pub fn enable_notification(&mut self) -> Result<bool, VirtQueError> {
142-
self.queue.enable_notification()
152+
self.queue.enable_notification(self.mem.memory().deref())
143153
}
144154

145155
/// Disable event notification for queue.
146156
pub fn disable_notification(&mut self) -> Result<(), VirtQueError> {
147-
self.queue.disable_notification()
157+
self.queue.disable_notification(self.mem.memory().deref())
148158
}
149159

150160
/// Check whether a notification to the guest is needed.
151161
pub fn needs_notification(&mut self) -> Result<bool, VirtQueError> {
152-
self.queue.needs_notification()
162+
self.queue.needs_notification(self.mem.memory().deref())
153163
}
154164

155165
/// Set vring enabled state.
@@ -158,10 +168,18 @@ impl<M: GuestAddressSpace> VringState<M> {
158168
}
159169

160170
/// Set queue addresses for descriptor table, available ring and used ring.
161-
pub fn set_queue_info(&mut self, desc_table: u64, avail_ring: u64, used_ring: u64) {
162-
self.queue.state.desc_table = GuestAddress(desc_table);
163-
self.queue.state.avail_ring = GuestAddress(avail_ring);
164-
self.queue.state.used_ring = GuestAddress(used_ring);
171+
pub fn set_queue_info(
172+
&mut self,
173+
desc_table: u64,
174+
avail_ring: u64,
175+
used_ring: u64,
176+
) -> Result<(), VirtQueError> {
177+
self.queue
178+
.try_set_desc_table_address(GuestAddress(desc_table))?;
179+
self.queue
180+
.try_set_avail_ring_address(GuestAddress(avail_ring))?;
181+
self.queue
182+
.try_set_used_ring_address(GuestAddress(used_ring))
165183
}
166184

167185
/// Get queue next avail head.
@@ -252,10 +270,10 @@ impl<'a, M: 'a + GuestAddressSpace> VringStateMutGuard<'a, M> for VringMutex<M>
252270
}
253271

254272
impl<M: 'static + GuestAddressSpace> VringT<M> for VringMutex<M> {
255-
fn new(mem: M, max_queue_size: u16) -> Self {
256-
VringMutex {
257-
state: Arc::new(Mutex::new(VringState::new(mem, max_queue_size))),
258-
}
273+
fn new(mem: M, max_queue_size: u16) -> Result<Self, VirtQueError> {
274+
Ok(VringMutex {
275+
state: Arc::new(Mutex::new(VringState::new(mem, max_queue_size)?)),
276+
})
259277
}
260278

261279
fn get_ref(&self) -> <Self as VringStateGuard<M>>::G {
@@ -290,7 +308,12 @@ impl<M: 'static + GuestAddressSpace> VringT<M> for VringMutex<M> {
290308
self.lock().set_enabled(enabled)
291309
}
292310

293-
fn set_queue_info(&self, desc_table: u64, avail_ring: u64, used_ring: u64) {
311+
fn set_queue_info(
312+
&self,
313+
desc_table: u64,
314+
avail_ring: u64,
315+
used_ring: u64,
316+
) -> Result<(), VirtQueError> {
294317
self.lock()
295318
.set_queue_info(desc_table, avail_ring, used_ring)
296319
}
@@ -354,10 +377,10 @@ impl<'a, M: 'a + GuestAddressSpace> VringStateMutGuard<'a, M> for VringRwLock<M>
354377
}
355378

356379
impl<M: 'static + GuestAddressSpace> VringT<M> for VringRwLock<M> {
357-
fn new(mem: M, max_queue_size: u16) -> Self {
358-
VringRwLock {
359-
state: Arc::new(RwLock::new(VringState::new(mem, max_queue_size))),
360-
}
380+
fn new(mem: M, max_queue_size: u16) -> Result<Self, VirtQueError> {
381+
Ok(VringRwLock {
382+
state: Arc::new(RwLock::new(VringState::new(mem, max_queue_size)?)),
383+
})
361384
}
362385

363386
fn get_ref(&self) -> <Self as VringStateGuard<M>>::G {
@@ -392,7 +415,12 @@ impl<M: 'static + GuestAddressSpace> VringT<M> for VringRwLock<M> {
392415
self.write_lock().set_enabled(enabled)
393416
}
394417

395-
fn set_queue_info(&self, desc_table: u64, avail_ring: u64, used_ring: u64) {
418+
fn set_queue_info(
419+
&self,
420+
desc_table: u64,
421+
avail_ring: u64,
422+
used_ring: u64,
423+
) -> Result<(), VirtQueError> {
396424
self.write_lock()
397425
.set_queue_info(desc_table, avail_ring, used_ring)
398426
}
@@ -447,39 +475,30 @@ mod tests {
447475
GuestMemoryMmap::<AtomicBitmap>::from_ranges(&[(GuestAddress(0x100000), 0x10000)])
448476
.unwrap(),
449477
);
450-
let vring = VringMutex::new(mem, 0x1000);
478+
let vring = VringMutex::new(mem, 0x1000).unwrap();
451479

452480
assert!(vring.get_ref().get_kick().is_none());
453481
assert!(!vring.get_mut().enabled);
454482
assert!(!vring.lock().queue.ready());
455-
assert!(!vring.lock().queue.state.event_idx_enabled);
483+
assert!(!vring.lock().queue.event_idx_enabled());
456484

457485
vring.set_enabled(true);
458486
assert!(vring.get_ref().enabled);
459487

460-
vring.set_queue_info(0x100100, 0x100200, 0x100300);
461-
assert_eq!(
462-
vring.lock().get_queue().state.desc_table,
463-
GuestAddress(0x100100)
464-
);
465-
assert_eq!(
466-
vring.lock().get_queue().state.avail_ring,
467-
GuestAddress(0x100200)
468-
);
469-
assert_eq!(
470-
vring.lock().get_queue().state.used_ring,
471-
GuestAddress(0x100300)
472-
);
488+
vring.set_queue_info(0x100100, 0x100200, 0x100300).unwrap();
489+
assert_eq!(vring.lock().get_queue().desc_table(), 0x100100);
490+
assert_eq!(vring.lock().get_queue().avail_ring(), 0x100200);
491+
assert_eq!(vring.lock().get_queue().used_ring(), 0x100300);
473492

474493
assert_eq!(vring.queue_next_avail(), 0);
475494
vring.set_queue_next_avail(0x20);
476495
assert_eq!(vring.queue_next_avail(), 0x20);
477496

478497
vring.set_queue_size(0x200);
479-
assert_eq!(vring.lock().queue.state.size, 0x200);
498+
assert_eq!(vring.lock().queue.size(), 0x200);
480499

481500
vring.set_queue_event_idx(true);
482-
assert!(vring.lock().queue.state.event_idx_enabled);
501+
assert!(vring.lock().queue.event_idx_enabled());
483502

484503
vring.set_queue_ready(true);
485504
assert!(vring.lock().queue.ready());
@@ -490,7 +509,7 @@ mod tests {
490509
let mem = GuestMemoryAtomic::new(
491510
GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0x100000), 0x10000)]).unwrap(),
492511
);
493-
let vring = VringMutex::new(mem, 0x1000);
512+
let vring = VringMutex::new(mem, 0x1000).unwrap();
494513

495514
vring.set_enabled(true);
496515
assert!(vring.get_ref().enabled);

0 commit comments

Comments
 (0)