33// 
44// SPDX-License-Identifier: Apache-2.0 
55
6+ use  std:: collections:: HashSet ; 
67use  std:: fmt:: { Display ,  Formatter } ; 
78use  std:: io:: { self ,  Result } ; 
89use  std:: marker:: PhantomData ; 
910use  std:: os:: fd:: IntoRawFd ; 
1011use  std:: os:: unix:: io:: { AsRawFd ,  RawFd } ; 
12+ use  std:: sync:: Mutex ; 
1113
12- use  vmm_sys_util:: epoll:: { ControlOperation ,  Epoll ,  EpollEvent ,  EventSet } ; 
14+ use  mio:: event:: Event ; 
15+ use  mio:: unix:: SourceFd ; 
16+ use  mio:: { Events ,  Interest ,  Poll ,  Registry ,  Token } ; 
1317use  vmm_sys_util:: event:: EventNotifier ; 
1418
1519use  super :: backend:: VhostUserBackend ; 
1620use  super :: vring:: VringT ; 
1721
1822/// Errors related to vring epoll event handling. 
1923#[ derive( Debug ) ]  
20- pub  enum  VringEpollError  { 
24+ pub  enum  VringPollError  { 
2125    /// Failed to create epoll file descriptor. 
22- EpollCreateFd ( io:: Error ) , 
26+ PollerCreate ( io:: Error ) , 
2327    /// Failed while waiting for events. 
24- EpollWait ( io:: Error ) , 
28+ PollerWait ( io:: Error ) , 
2529    /// Could not register exit event 
2630RegisterExitEvent ( io:: Error ) , 
2731    /// Failed to read the event from kick EventFd. 
2832HandleEventReadKick ( io:: Error ) , 
2933    /// Failed to handle the event from the backend. 
3034HandleEventBackendHandling ( io:: Error ) , 
35+     /// Failed to clone registry. 
36+ RegistryClone ( io:: Error ) , 
3137} 
3238
33- impl  Display  for  VringEpollError  { 
39+ impl  Display  for  VringPollError  { 
3440    fn  fmt ( & self ,  f :  & mut  Formatter )  -> std:: fmt:: Result  { 
3541        match  self  { 
36-             VringEpollError :: EpollCreateFd ( e)  => write ! ( f,  "cannot create epoll fd : {e}" ) , 
37-             VringEpollError :: EpollWait ( e)  => write ! ( f,  "failed to wait for epoll  event: {e}" ) , 
38-             VringEpollError :: RegisterExitEvent ( e)  => write ! ( f,  "cannot register exit event: {e}" ) , 
39-             VringEpollError :: HandleEventReadKick ( e)  => { 
42+             VringPollError :: PollerCreate ( e)  => write ! ( f,  "cannot create poller : {e}" ) , 
43+             VringPollError :: PollerWait ( e)  => write ! ( f,  "failed to wait for poller  event: {e}" ) , 
44+             VringPollError :: RegisterExitEvent ( e)  => write ! ( f,  "cannot register exit event: {e}" ) , 
45+             VringPollError :: HandleEventReadKick ( e)  => { 
4046                write ! ( f,  "cannot read vring kick event: {e}" ) 
4147            } 
42-             VringEpollError :: HandleEventBackendHandling ( e)  => { 
43-                 write ! ( f,  "failed to handle epoll  event: {e}" ) 
48+             VringPollError :: HandleEventBackendHandling ( e)  => { 
49+                 write ! ( f,  "failed to handle poll  event: {e}" ) 
4450            } 
51+             VringPollError :: RegistryClone ( e)  => write ! ( f,  "cannot clone poller's registry: {e}" ) , 
4552        } 
4653    } 
4754} 
4855
49- impl  std:: error:: Error  for  VringEpollError  { } 
56+ impl  std:: error:: Error  for  VringPollError  { } 
5057
5158/// Result of vring epoll operations. 
52- pub  type  VringEpollResult < T >  = std:: result:: Result < T ,  VringEpollError > ; 
59+ pub  type  VringEpollResult < T >  = std:: result:: Result < T ,  VringPollError > ; 
60+ 
61+ #[ derive( Debug ,  Clone ,  Copy ) ]  
62+ pub  enum  EventSet  { 
63+     Readable , 
64+     Writable , 
65+     All , 
66+ } 
67+ 
68+ impl  EventSet  { 
69+     fn  to_interest ( self )  -> Interest  { 
70+         match  self  { 
71+             EventSet :: Readable  => Interest :: READABLE , 
72+             EventSet :: Writable  => Interest :: WRITABLE , 
73+             EventSet :: All  => Interest :: READABLE  | Interest :: WRITABLE , 
74+         } 
75+     } 
76+ } 
77+ 
78+ fn  event_to_event_set ( evt :  & Event )  -> Option < EventSet >  { 
79+     if  evt. is_readable ( )  && evt. is_writable ( )  { 
80+         return  Some ( EventSet :: All ) ; 
81+     } 
82+     if  evt. is_readable ( )  { 
83+         return  Some ( EventSet :: Readable ) ; 
84+     } 
85+     if  evt. is_writable ( )  { 
86+         return  Some ( EventSet :: Writable ) ; 
87+     } 
88+     None 
89+ } 
5390
5491/// Epoll event handler to manage and process epoll events for registered file descriptor. 
5592/// 
@@ -58,7 +95,11 @@ pub type VringEpollResult<T> = std::result::Result<T, VringEpollError>;
5895/// - remove registered file descriptors from the epoll fd 
5996/// - run the event loop to handle pending events on the epoll fd 
6097pub  struct  VringEpollHandler < T :  VhostUserBackend >  { 
61-     epoll :  Epoll , 
98+     poller :  Mutex < Poll > , 
99+     registry :  Registry , 
100+     // Record the registered fd. 
101+     // Because in mio, consecutive calls to register is unspecified behavior. 
102+     fd_set :  Mutex < HashSet < RawFd > > , 
62103    backend :  T , 
63104    vrings :  Vec < T :: Vring > , 
64105    thread_id :  usize , 
@@ -85,25 +126,35 @@ where
85126        vrings :  Vec < T :: Vring > , 
86127        thread_id :  usize , 
87128    )  -> VringEpollResult < Self >  { 
88-         let  epoll  = Epoll :: new ( ) . map_err ( VringEpollError :: EpollCreateFd ) ?; 
129+         let  poller  = Poll :: new ( ) . map_err ( VringPollError :: PollerCreate ) ?; 
89130        let  exit_event_fd = backend. exit_event ( thread_id) ; 
131+         let  fd_set = Mutex :: new ( HashSet :: new ( ) ) ; 
90132
133+         let  registry = poller
134+             . registry ( ) 
135+             . try_clone ( ) 
136+             . map_err ( VringPollError :: RegistryClone ) ?; 
91137        let  exit_event_fd = if  let  Some ( ( consumer,  notifier) )  = exit_event_fd { 
92138            let  id = backend. num_queues ( ) ; 
93-             epoll
94-                 . ctl ( 
95-                     ControlOperation :: Add , 
96-                     consumer. into_raw_fd ( ) , 
97-                     EpollEvent :: new ( EventSet :: IN ,  id as  u64 ) , 
139+ 
140+             registry
141+                 . register ( 
142+                     & mut  SourceFd ( & consumer. as_raw_fd ( ) ) , 
143+                     Token ( id) , 
144+                     Interest :: READABLE , 
98145                ) 
99-                 . map_err ( VringEpollError :: RegisterExitEvent ) ?; 
146+                 . map_err ( VringPollError :: RegisterExitEvent ) ?; 
147+ 
148+             fd_set. lock ( ) . unwrap ( ) . insert ( consumer. into_raw_fd ( ) ) ; 
100149            Some ( notifier) 
101150        }  else  { 
102151            None 
103152        } ; 
104153
105154        Ok ( VringEpollHandler  { 
106-             epoll, 
155+             poller :  Mutex :: new ( poller) , 
156+             registry, 
157+             fd_set, 
107158            backend, 
108159            vrings, 
109160            thread_id, 
@@ -129,29 +180,37 @@ where
129180/// 
130181/// If the event is triggered after this function has been called, the event will be silently 
131182/// dropped. 
132- pub  fn  unregister_listener ( & self ,  fd :  RawFd ,  ev_type :   EventSet ,   data :  usize )  -> Result < ( ) >  { 
183+ pub  fn  unregister_listener ( & self ,  fd :  RawFd ,  data :  usize )  -> Result < ( ) >  { 
133184        // `data` range [0...num_queues] is reserved for queues and exit event. 
134185        if  data <= self . backend . num_queues ( )  { 
135186            Err ( io:: Error :: from_raw_os_error ( libc:: EINVAL ) ) 
136187        }  else  { 
137-             self . unregister_event ( fd,  ev_type ,  data ) 
188+             self . unregister_event ( fd) 
138189        } 
139190    } 
140191
141192    pub ( crate )  fn  register_event ( & self ,  fd :  RawFd ,  ev_type :  EventSet ,  data :  usize )  -> Result < ( ) >  { 
142-         self . epoll . ctl ( 
143-             ControlOperation :: Add , 
144-             fd, 
145-             EpollEvent :: new ( ev_type,  data as  u64 ) , 
146-         ) 
193+         let  mut  fd_set = self . fd_set . lock ( ) . unwrap ( ) ; 
194+         if  fd_set. contains ( & fd)  { 
195+             return  Err ( io:: Error :: from_raw_os_error ( libc:: EEXIST ) ) ; 
196+         } 
197+         self . registry 
198+             . register ( & mut  SourceFd ( & fd) ,  Token ( data) ,  ev_type. to_interest ( ) ) 
199+             . map_err ( std:: io:: Error :: other) ?; 
200+         fd_set. insert ( fd) ; 
201+         Ok ( ( ) ) 
147202    } 
148203
149-     pub ( crate )  fn  unregister_event ( & self ,  fd :  RawFd ,  ev_type :  EventSet ,  data :  usize )  -> Result < ( ) >  { 
150-         self . epoll . ctl ( 
151-             ControlOperation :: Delete , 
152-             fd, 
153-             EpollEvent :: new ( ev_type,  data as  u64 ) , 
154-         ) 
204+     pub ( crate )  fn  unregister_event ( & self ,  fd :  RawFd )  -> Result < ( ) >  { 
205+         let  mut  fd_set = self . fd_set . lock ( ) . unwrap ( ) ; 
206+         if  !fd_set. contains ( & fd)  { 
207+             return  Err ( io:: Error :: from_raw_os_error ( libc:: ENOENT ) ) ; 
208+         } 
209+         self . registry 
210+             . deregister ( & mut  SourceFd ( & fd) ) 
211+             . map_err ( |e| std:: io:: Error :: other ( format ! ( "Failed to deregister fd {fd}: {e}" ) ) ) ?; 
212+         fd_set. remove ( & fd) ; 
213+         Ok ( ( ) ) 
155214    } 
156215
157216    /// Run the event poll loop to handle all pending events on registered fds. 
@@ -160,41 +219,22 @@ where
160219/// associated with the backend. 
161220pub ( crate )  fn  run ( & self )  -> VringEpollResult < ( ) >  { 
162221        const  EPOLL_EVENTS_LEN :  usize  = 100 ; 
163-         let  mut  events = vec ! [ EpollEvent :: new( EventSet :: empty( ) ,  0 ) ;  EPOLL_EVENTS_LEN ] ; 
164- 
165-         ' epoll:  loop  { 
166-             let  num_events = match  self . epoll . wait ( -1 ,  & mut  events[ ..] )  { 
167-                 Ok ( res)  => res, 
168-                 Err ( e)  => { 
169-                     if  e. kind ( )  == io:: ErrorKind :: Interrupted  { 
170-                         // It's well defined from the epoll_wait() syscall 
171-                         // documentation that the epoll loop can be interrupted 
172-                         // before any of the requested events occurred or the 
173-                         // timeout expired. In both those cases, epoll_wait() 
174-                         // returns an error of type EINTR, but this should not 
175-                         // be considered as a regular error. Instead it is more 
176-                         // appropriate to retry, by calling into epoll_wait(). 
177-                         continue ; 
178-                     } 
179-                     return  Err ( VringEpollError :: EpollWait ( e) ) ; 
180-                 } 
181-             } ; 
182- 
183-             for  event in  events. iter ( ) . take ( num_events)  { 
184-                 let  evset = match  EventSet :: from_bits ( event. events )  { 
185-                     Some ( evset)  => evset, 
186-                     None  => { 
187-                         let  evbits = event. events ; 
188-                         println ! ( "epoll: ignoring unknown event set: 0x{evbits:x}" ) ; 
189-                         continue ; 
190-                     } 
191-                 } ; 
192222
193-                 let  ev_type = event. data ( ) ; 
223+         let  mut  events = Events :: with_capacity ( EPOLL_EVENTS_LEN ) ; 
224+         ' poll:  loop  { 
225+             self . poller 
226+                 . lock ( ) 
227+                 . unwrap ( ) 
228+                 . poll ( & mut  events,  None ) 
229+                 . map_err ( VringPollError :: PollerWait ) ?; 
194230
195-                 // handle_event() returns true if an event is received from the exit event fd. 
196-                 if  self . handle_event ( ev_type as  usize ,  evset) ? { 
197-                     break  ' epoll; 
231+             for  event in  & events { 
232+                 let  token = event. token ( ) ; 
233+ 
234+                 if  let  Some ( evt_set)  = event_to_event_set ( event)  { 
235+                     if  self . handle_event ( token. 0 ,  evt_set) ? { 
236+                         break  ' poll; 
237+                     } 
198238                } 
199239            } 
200240        } 
@@ -211,7 +251,7 @@ where
211251            let  vring = & self . vrings [ device_event] ; 
212252            let  enabled = vring
213253                . read_kick ( ) 
214-                 . map_err ( VringEpollError :: HandleEventReadKick ) ?; 
254+                 . map_err ( VringPollError :: HandleEventReadKick ) ?; 
215255
216256            // If the vring is not enabled, it should not be processed. 
217257            if  !enabled { 
@@ -221,15 +261,15 @@ where
221261
222262        self . backend 
223263            . handle_event ( device_event,  evset,  & self . vrings ,  self . thread_id ) 
224-             . map_err ( VringEpollError :: HandleEventBackendHandling ) ?; 
264+             . map_err ( VringPollError :: HandleEventBackendHandling ) ?; 
225265
226266        Ok ( false ) 
227267    } 
228268} 
229269
230270impl < T :  VhostUserBackend >  AsRawFd  for  VringEpollHandler < T >  { 
231271    fn  as_raw_fd ( & self )  -> RawFd  { 
232-         self . epoll . as_raw_fd ( ) 
272+         self . poller . lock ( ) . unwrap ( ) . as_raw_fd ( ) 
233273    } 
234274} 
235275
@@ -254,29 +294,32 @@ mod tests {
254294
255295        let  ( consumer,  _notifier)  = new_event_consumer_and_notifier ( EventFlag :: empty ( ) ) . unwrap ( ) ; 
256296        handler
257-             . register_listener ( consumer. as_raw_fd ( ) ,  EventSet :: IN ,  3 ) 
297+             . register_listener ( consumer. as_raw_fd ( ) ,  EventSet :: Readable ,  3 ) 
258298            . unwrap ( ) ; 
259299        // Register an already registered fd. 
260300        handler
261-             . register_listener ( consumer. as_raw_fd ( ) ,  EventSet :: IN ,  3 ) 
301+             . register_listener ( consumer. as_raw_fd ( ) ,  EventSet :: Readable ,  3 ) 
262302            . unwrap_err ( ) ; 
263303        // Register an invalid data. 
264304        handler
265-             . register_listener ( consumer. as_raw_fd ( ) ,  EventSet :: IN ,  1 ) 
305+             . register_listener ( consumer. as_raw_fd ( ) ,  EventSet :: Readable ,  1 ) 
266306            . unwrap_err ( ) ; 
267307
268308        handler
269-             . unregister_listener ( consumer. as_raw_fd ( ) ,  EventSet :: IN ,   3 ) 
309+             . unregister_listener ( consumer. as_raw_fd ( ) ,  3 ) 
270310            . unwrap ( ) ; 
271311        // unregister an already unregistered fd. 
272312        handler
273-             . unregister_listener ( consumer. as_raw_fd ( ) ,  EventSet :: IN ,   3 ) 
313+             . unregister_listener ( consumer. as_raw_fd ( ) ,  3 ) 
274314            . unwrap_err ( ) ; 
275315        // unregister an invalid data. 
276316        handler
277-             . unregister_listener ( consumer. as_raw_fd ( ) ,  EventSet :: IN ,   1 ) 
317+             . unregister_listener ( consumer. as_raw_fd ( ) ,  1 ) 
278318            . unwrap_err ( ) ; 
279319        // Check we retrieve the correct file descriptor 
280-         assert_eq ! ( handler. as_raw_fd( ) ,  handler. epoll. as_raw_fd( ) ) ; 
320+         assert_eq ! ( 
321+             handler. as_raw_fd( ) , 
322+             handler. poller. lock( ) . unwrap( ) . as_raw_fd( ) 
323+         ) ; 
281324    } 
282325} 
0 commit comments