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

Commit e80fab8

Browse files
committed
vring: add generic parameter for VringT
Enhance VhostUserBackend, VhostUserBackendMut, VringEpollHandler, VhostUserHandler and VhostUserDaemon to support generic type `V: VringT', so clients could choose different VringT implementations. Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
1 parent ed929c0 commit e80fab8

File tree

4 files changed

+104
-37
lines changed

4 files changed

+104
-37
lines changed

src/backend.rs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,18 @@ use vhost::vhost_user::SlaveFsCacheReq;
2828
use vm_memory::bitmap::Bitmap;
2929
use vmm_sys_util::eventfd::EventFd;
3030

31-
use super::{VringRwLock, GM};
31+
use super::vring::VringT;
32+
use super::GM;
3233

3334
/// Trait with interior mutability for vhost user backend servers to implement concrete services.
3435
///
3536
/// To support multi-threading and asynchronous IO, we enforce `the Send + Sync + 'static`.
3637
/// So there's no plan for support of "Rc<T>" and "RefCell<T>".
37-
pub trait VhostUserBackend<B: Bitmap + 'static = ()>: Send + Sync + 'static {
38+
pub trait VhostUserBackend<V, B = ()>: Send + Sync + 'static
39+
where
40+
V: VringT<GM<B>>,
41+
B: Bitmap + 'static,
42+
{
3843
/// Get number of queues supported.
3944
fn num_queues(&self) -> usize;
4045

@@ -107,13 +112,17 @@ pub trait VhostUserBackend<B: Bitmap + 'static = ()>: Send + Sync + 'static {
107112
&self,
108113
device_event: u16,
109114
evset: epoll::Events,
110-
vrings: &[VringRwLock<GM<B>>],
115+
vrings: &[V],
111116
thread_id: usize,
112117
) -> result::Result<bool, io::Error>;
113118
}
114119

115120
/// Trait without interior mutability for vhost user backend servers to implement concrete services.
116-
pub trait VhostUserBackendMut<B: Bitmap + 'static = ()>: Send + Sync + 'static {
121+
pub trait VhostUserBackendMut<V, B = ()>: Send + Sync + 'static
122+
where
123+
V: VringT<GM<B>>,
124+
B: Bitmap + 'static,
125+
{
117126
/// Get number of queues supported.
118127
fn num_queues(&self) -> usize;
119128

@@ -186,12 +195,16 @@ pub trait VhostUserBackendMut<B: Bitmap + 'static = ()>: Send + Sync + 'static {
186195
&mut self,
187196
device_event: u16,
188197
evset: epoll::Events,
189-
vrings: &[VringRwLock<GM<B>>],
198+
vrings: &[V],
190199
thread_id: usize,
191200
) -> result::Result<bool, io::Error>;
192201
}
193202

194-
impl<T: VhostUserBackend<B>, B: Bitmap + 'static> VhostUserBackend<B> for Arc<T> {
203+
impl<T: VhostUserBackend<V, B>, V, B> VhostUserBackend<V, B> for Arc<T>
204+
where
205+
V: VringT<GM<B>>,
206+
B: Bitmap + 'static,
207+
{
195208
fn num_queues(&self) -> usize {
196209
self.deref().num_queues()
197210
}
@@ -244,15 +257,19 @@ impl<T: VhostUserBackend<B>, B: Bitmap + 'static> VhostUserBackend<B> for Arc<T>
244257
&self,
245258
device_event: u16,
246259
evset: epoll::Events,
247-
vrings: &[VringRwLock<GM<B>>],
260+
vrings: &[V],
248261
thread_id: usize,
249262
) -> Result<bool, io::Error> {
250263
self.deref()
251264
.handle_event(device_event, evset, vrings, thread_id)
252265
}
253266
}
254267

255-
impl<T: VhostUserBackendMut<B>, B: Bitmap + 'static> VhostUserBackend<B> for Mutex<T> {
268+
impl<T: VhostUserBackendMut<V, B>, V, B> VhostUserBackend<V, B> for Mutex<T>
269+
where
270+
V: VringT<GM<B>>,
271+
B: Bitmap + 'static,
272+
{
256273
fn num_queues(&self) -> usize {
257274
self.lock().unwrap().num_queues()
258275
}
@@ -305,7 +322,7 @@ impl<T: VhostUserBackendMut<B>, B: Bitmap + 'static> VhostUserBackend<B> for Mut
305322
&self,
306323
device_event: u16,
307324
evset: epoll::Events,
308-
vrings: &[VringRwLock<GM<B>>],
325+
vrings: &[V],
309326
thread_id: usize,
310327
) -> Result<bool, io::Error> {
311328
self.lock()
@@ -314,7 +331,11 @@ impl<T: VhostUserBackendMut<B>, B: Bitmap + 'static> VhostUserBackend<B> for Mut
314331
}
315332
}
316333

317-
impl<T: VhostUserBackendMut<B>, B: Bitmap + 'static> VhostUserBackend<B> for RwLock<T> {
334+
impl<T: VhostUserBackendMut<V, B>, V, B> VhostUserBackend<V, B> for RwLock<T>
335+
where
336+
V: VringT<GM<B>>,
337+
B: Bitmap + 'static,
338+
{
318339
fn num_queues(&self) -> usize {
319340
self.read().unwrap().num_queues()
320341
}
@@ -367,7 +388,7 @@ impl<T: VhostUserBackendMut<B>, B: Bitmap + 'static> VhostUserBackend<B> for RwL
367388
&self,
368389
device_event: u16,
369390
evset: epoll::Events,
370-
vrings: &[VringRwLock<GM<B>>],
391+
vrings: &[V],
371392
thread_id: usize,
372393
) -> Result<bool, io::Error> {
373394
self.write()
@@ -379,6 +400,7 @@ impl<T: VhostUserBackendMut<B>, B: Bitmap + 'static> VhostUserBackend<B> for RwL
379400
#[cfg(test)]
380401
pub mod tests {
381402
use super::*;
403+
use crate::VringRwLock;
382404
use epoll::Events;
383405
use std::io::Error;
384406
use std::sync::Mutex;
@@ -400,7 +422,7 @@ pub mod tests {
400422
}
401423
}
402424

403-
impl VhostUserBackendMut<()> for MockVhostBackend {
425+
impl VhostUserBackendMut<VringRwLock, ()> for MockVhostBackend {
404426
fn num_queues(&self) -> usize {
405427
2
406428
}

src/event_loop.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
use std::fmt::{Display, Formatter};
77
use std::fs::File;
88
use std::io;
9+
use std::marker::PhantomData;
910
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
1011
use std::result;
1112

1213
use vm_memory::bitmap::Bitmap;
1314
use vmm_sys_util::eventfd::EventFd;
1415

16+
use super::backend::VhostUserBackend;
1517
use super::vring::VringT;
16-
use super::{VhostUserBackend, VringRwLock, GM};
18+
use super::GM;
1719

1820
/// Errors related to vring epoll event handling.
1921
#[derive(Debug)]
@@ -57,22 +59,29 @@ pub type VringEpollResult<T> = std::result::Result<T, VringEpollError>;
5759
/// - add file descriptors to be monitored by the epoll fd
5860
/// - remove registered file descriptors from the epoll fd
5961
/// - run the event loop to handle pending events on the epoll fd
60-
pub struct VringEpollHandler<S: VhostUserBackend<B>, B: Bitmap + 'static> {
62+
pub struct VringEpollHandler<S, V, B>
63+
where
64+
S: VhostUserBackend<V, B>,
65+
V: VringT<GM<B>>,
66+
B: Bitmap + 'static,
67+
{
6168
epoll_file: File,
6269
backend: S,
63-
vrings: Vec<VringRwLock<GM<B>>>,
70+
vrings: Vec<V>,
6471
thread_id: usize,
6572
exit_event_fd: Option<EventFd>,
6673
exit_event_id: Option<u16>,
74+
phantom: PhantomData<B>,
6775
}
6876

69-
impl<S: VhostUserBackend<B>, B: Bitmap + 'static> VringEpollHandler<S, B> {
77+
impl<S, V, B> VringEpollHandler<S, V, B>
78+
where
79+
S: VhostUserBackend<V, B>,
80+
V: VringT<GM<B>>,
81+
B: Bitmap + 'static,
82+
{
7083
/// Create a `VringEpollHandler` instance.
71-
pub(crate) fn new(
72-
backend: S,
73-
vrings: Vec<VringRwLock<GM<B>>>,
74-
thread_id: usize,
75-
) -> VringEpollResult<Self> {
84+
pub(crate) fn new(backend: S, vrings: Vec<V>, thread_id: usize) -> VringEpollResult<Self> {
7685
let epoll_fd = epoll::create(true).map_err(VringEpollError::EpollCreateFd)?;
7786
let epoll_file = unsafe { File::from_raw_fd(epoll_fd) };
7887

@@ -93,6 +102,7 @@ impl<S: VhostUserBackend<B>, B: Bitmap + 'static> VringEpollHandler<S, B> {
93102
thread_id,
94103
exit_event_fd: Some(exit_event_fd),
95104
exit_event_id: Some(exit_event_id),
105+
phantom: PhantomData,
96106
}
97107
}
98108
None => VringEpollHandler {
@@ -102,6 +112,7 @@ impl<S: VhostUserBackend<B>, B: Bitmap + 'static> VringEpollHandler<S, B> {
102112
thread_id,
103113
exit_event_fd: None,
104114
exit_event_id: None,
115+
phantom: PhantomData,
105116
},
106117
};
107118

@@ -225,6 +236,7 @@ impl<S: VhostUserBackend<B>, B: Bitmap + 'static> VringEpollHandler<S, B> {
225236
#[cfg(test)]
226237
mod tests {
227238
use super::super::backend::tests::MockVhostBackend;
239+
use super::super::vring::VringRwLock;
228240
use super::*;
229241
use std::sync::{Arc, Mutex};
230242
use vm_memory::{GuestAddress, GuestMemoryAtomic, GuestMemoryMmap};

src/handler.rs

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use vm_memory::{
2929
use super::backend::VhostUserBackend;
3030
use super::event_loop::VringEpollHandler;
3131
use super::event_loop::{VringEpollError, VringEpollResult};
32-
use super::vring::{VringRwLock, VringT};
32+
use super::vring::VringT;
3333
use super::GM;
3434

3535
const MAX_MEM_SLOTS: u64 = 32;
@@ -70,9 +70,14 @@ struct AddrMapping {
7070
gpa_base: u64,
7171
}
7272

73-
pub struct VhostUserHandler<S: VhostUserBackend<B>, B: Bitmap + 'static> {
73+
pub struct VhostUserHandler<S, V, B>
74+
where
75+
S: VhostUserBackend<V, B>,
76+
V: VringT<GM<B>>,
77+
B: Bitmap + 'static,
78+
{
7479
backend: S,
75-
handlers: Vec<Arc<VringEpollHandler<S, B>>>,
80+
handlers: Vec<Arc<VringEpollHandler<S, V, B>>>,
7681
owned: bool,
7782
features_acked: bool,
7883
acked_features: u64,
@@ -82,19 +87,24 @@ pub struct VhostUserHandler<S: VhostUserBackend<B>, B: Bitmap + 'static> {
8287
queues_per_thread: Vec<u64>,
8388
mappings: Vec<AddrMapping>,
8489
atomic_mem: GM<B>,
85-
vrings: Vec<VringRwLock<GM<B>>>,
90+
vrings: Vec<V>,
8691
worker_threads: Vec<thread::JoinHandle<VringEpollResult<()>>>,
8792
}
8893

89-
impl<S: VhostUserBackend<B> + Clone, B: Bitmap + Clone + Send + Sync> VhostUserHandler<S, B> {
94+
impl<S, V, B> VhostUserHandler<S, V, B>
95+
where
96+
S: VhostUserBackend<V, B> + Clone,
97+
V: VringT<GM<B>> + Clone + Send + Sync + 'static,
98+
B: Bitmap + Clone + Send + Sync,
99+
{
90100
pub(crate) fn new(backend: S, atomic_mem: GM<B>) -> VhostUserHandlerResult<Self> {
91101
let num_queues = backend.num_queues();
92102
let max_queue_size = backend.max_queue_size();
93103
let queues_per_thread = backend.queues_per_thread();
94104

95105
let mut vrings = Vec::new();
96106
for _ in 0..num_queues {
97-
let vring = VringRwLock::new(atomic_mem.clone(), max_queue_size as u16);
107+
let vring = V::new(atomic_mem.clone(), max_queue_size as u16);
98108
vrings.push(vring);
99109
}
100110

@@ -140,8 +150,13 @@ impl<S: VhostUserBackend<B> + Clone, B: Bitmap + Clone + Send + Sync> VhostUserH
140150
}
141151
}
142152

143-
impl<S: VhostUserBackend<B>, B: Bitmap> VhostUserHandler<S, B> {
144-
pub(crate) fn get_epoll_handlers(&self) -> Vec<Arc<VringEpollHandler<S, B>>> {
153+
impl<S, V, B> VhostUserHandler<S, V, B>
154+
where
155+
S: VhostUserBackend<V, B>,
156+
V: VringT<GM<B>>,
157+
B: Bitmap,
158+
{
159+
pub(crate) fn get_epoll_handlers(&self) -> Vec<Arc<VringEpollHandler<S, V, B>>> {
145160
self.handlers.clone()
146161
}
147162

@@ -162,8 +177,11 @@ impl<S: VhostUserBackend<B>, B: Bitmap> VhostUserHandler<S, B> {
162177
}
163178
}
164179

165-
impl<S: VhostUserBackend<B>, B: NewBitmap + Clone> VhostUserSlaveReqHandlerMut
166-
for VhostUserHandler<S, B>
180+
impl<S, V, B> VhostUserSlaveReqHandlerMut for VhostUserHandler<S, V, B>
181+
where
182+
S: VhostUserBackend<V, B>,
183+
V: VringT<GM<B>>,
184+
B: NewBitmap + Clone,
167185
{
168186
fn set_owner(&mut self) -> VhostUserResult<()> {
169187
if self.owned {
@@ -538,7 +556,12 @@ impl<S: VhostUserBackend<B>, B: NewBitmap + Clone> VhostUserSlaveReqHandlerMut
538556
}
539557
}
540558

541-
impl<S: VhostUserBackend<B>, B: Bitmap> Drop for VhostUserHandler<S, B> {
559+
impl<S, V, B> Drop for VhostUserHandler<S, V, B>
560+
where
561+
S: VhostUserBackend<V, B>,
562+
V: VringT<GM<B>>,
563+
B: Bitmap,
564+
{
542565
fn drop(&mut self) {
543566
// Signal all working threads to exit.
544567
self.send_exit_event();

src/lib.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ mod handler;
3131
pub use self::handler::VhostUserHandlerError;
3232

3333
mod vring;
34-
pub use self::vring::{VringRwLock, VringState};
34+
pub use self::vring::{VringMutex, VringRwLock, VringState, VringT};
3535

3636
/// An alias for `GuestMemoryAtomic<GuestMemoryMmap<B>>` to simplify code.
3737
type GM<B> = GuestMemoryAtomic<GuestMemoryMmap<B>>;
@@ -73,13 +73,23 @@ pub type Result<T> = result::Result<T, Error>;
7373
///
7474
/// This structure is the public API the backend is allowed to interact with in order to run
7575
/// a fully functional vhost-user daemon.
76-
pub struct VhostUserDaemon<S: VhostUserBackend<B>, B: Bitmap + 'static = ()> {
76+
pub struct VhostUserDaemon<S, V, B = ()>
77+
where
78+
S: VhostUserBackend<V, B>,
79+
V: VringT<GM<B>> + Clone + Send + Sync + 'static,
80+
B: Bitmap + 'static,
81+
{
7782
name: String,
78-
handler: Arc<Mutex<VhostUserHandler<S, B>>>,
83+
handler: Arc<Mutex<VhostUserHandler<S, V, B>>>,
7984
main_thread: Option<thread::JoinHandle<Result<()>>>,
8085
}
8186

82-
impl<S: VhostUserBackend<B> + Clone, B: NewBitmap + Clone + Send + Sync> VhostUserDaemon<S, B> {
87+
impl<S, V, B> VhostUserDaemon<S, V, B>
88+
where
89+
S: VhostUserBackend<V, B> + Clone,
90+
V: VringT<GM<B>> + Clone + Send + Sync + 'static,
91+
B: NewBitmap + Clone + Send + Sync,
92+
{
8393
/// Create the daemon instance, providing the backend implementation of `VhostUserBackend`.
8494
///
8595
/// Under the hood, this will start a dedicated thread responsible for listening onto
@@ -144,7 +154,7 @@ impl<S: VhostUserBackend<B> + Clone, B: NewBitmap + Clone + Send + Sync> VhostUs
144154
///
145155
/// This is necessary to perform further actions like registering and unregistering some extra
146156
/// event file descriptors.
147-
pub fn get_epoll_handlers(&self) -> Vec<Arc<VringEpollHandler<S, B>>> {
157+
pub fn get_epoll_handlers(&self) -> Vec<Arc<VringEpollHandler<S, V, B>>> {
148158
self.handler.lock().unwrap().get_epoll_handlers()
149159
}
150160
}

0 commit comments

Comments
 (0)