@@ -52,6 +52,16 @@ pub trait VhostUserFrontendReqHandler {
5252 Err ( std:: io:: Error :: from_raw_os_error ( libc:: ENOSYS ) )
5353 }
5454
55+ /// Handle shared memory region mapping requests.
56+ fn shmem_map ( & self , _req : & VhostUserMMap , _fd : & dyn AsRawFd ) -> HandlerResult < u64 > {
57+ Err ( std:: io:: Error :: from_raw_os_error ( libc:: ENOSYS ) )
58+ }
59+
60+ /// Handle shared memory region unmapping requests.
61+ fn shmem_unmap ( & self , _req : & VhostUserMMap ) -> HandlerResult < u64 > {
62+ Err ( std:: io:: Error :: from_raw_os_error ( libc:: ENOSYS ) )
63+ }
64+
5565 // fn handle_iotlb_msg(&mut self, iotlb: VhostUserIotlb);
5666 // fn handle_vring_host_notifier(&mut self, area: VhostUserVringArea, fd: &dyn AsRawFd);
5767}
@@ -84,6 +94,16 @@ pub trait VhostUserFrontendReqHandlerMut {
8494 Err ( std:: io:: Error :: from_raw_os_error ( libc:: ENOSYS ) )
8595 }
8696
97+ /// Handle shared memory region mapping requests.
98+ fn shmem_map ( & mut self , _req : & VhostUserMMap , _fd : & dyn AsRawFd ) -> HandlerResult < u64 > {
99+ Err ( std:: io:: Error :: from_raw_os_error ( libc:: ENOSYS ) )
100+ }
101+
102+ /// Handle shared memory region unmapping requests.
103+ fn shmem_unmap ( & mut self , _req : & VhostUserMMap ) -> HandlerResult < u64 > {
104+ Err ( std:: io:: Error :: from_raw_os_error ( libc:: ENOSYS ) )
105+ }
106+
87107 // fn handle_iotlb_msg(&mut self, iotlb: VhostUserIotlb);
88108 // fn handle_vring_host_notifier(&mut self, area: VhostUserVringArea, fd: RawFd);
89109}
@@ -111,6 +131,14 @@ impl<S: VhostUserFrontendReqHandlerMut> VhostUserFrontendReqHandler for Mutex<S>
111131 ) -> HandlerResult < u64 > {
112132 self . lock ( ) . unwrap ( ) . shared_object_lookup ( uuid, fd)
113133 }
134+
135+ fn shmem_map ( & self , req : & VhostUserMMap , fd : & dyn AsRawFd ) -> HandlerResult < u64 > {
136+ self . lock ( ) . unwrap ( ) . shmem_map ( req, fd)
137+ }
138+
139+ fn shmem_unmap ( & self , req : & VhostUserMMap ) -> HandlerResult < u64 > {
140+ self . lock ( ) . unwrap ( ) . shmem_unmap ( req)
141+ }
114142}
115143
116144/// Server to handle service requests from backends from the backend communication channel.
@@ -241,6 +269,18 @@ impl<S: VhostUserFrontendReqHandler> FrontendReqHandler<S> {
241269 . shared_object_lookup ( & msg, & files. unwrap ( ) [ 0 ] )
242270 . map_err ( Error :: ReqHandlerError )
243271 }
272+ Ok ( BackendReq :: SHMEM_MAP ) => {
273+ let msg = self . extract_msg_body :: < VhostUserMMap > ( & hdr, size, & buf) ?;
274+ self . backend
275+ . shmem_map ( & msg, & files. unwrap ( ) [ 0 ] )
276+ . map_err ( Error :: ReqHandlerError )
277+ }
278+ Ok ( BackendReq :: SHMEM_UNMAP ) => {
279+ let msg = self . extract_msg_body :: < VhostUserMMap > ( & hdr, size, & buf) ?;
280+ self . backend
281+ . shmem_unmap ( & msg)
282+ . map_err ( Error :: ReqHandlerError )
283+ }
244284 _ => Err ( Error :: InvalidMessage ) ,
245285 } ;
246286
@@ -278,7 +318,7 @@ impl<S: VhostUserFrontendReqHandler> FrontendReqHandler<S> {
278318 files : & Option < Vec < File > > ,
279319 ) -> Result < ( ) > {
280320 match hdr. get_code ( ) {
281- Ok ( BackendReq :: SHARED_OBJECT_LOOKUP ) => {
321+ Ok ( BackendReq :: SHARED_OBJECT_LOOKUP | BackendReq :: SHMEM_MAP ) => {
282322 // Expect a single file is passed.
283323 match files {
284324 Some ( files) if files. len ( ) == 1 => Ok ( ( ) ) ,
@@ -366,12 +406,14 @@ mod tests {
366406
367407 struct MockFrontendReqHandler {
368408 shared_objects : HashSet < Uuid > ,
409+ shmem_mappings : HashSet < ( u64 , u64 ) > ,
369410 }
370411
371412 impl MockFrontendReqHandler {
372413 fn new ( ) -> Self {
373414 Self {
374415 shared_objects : HashSet :: new ( ) ,
416+ shmem_mappings : HashSet :: new ( ) ,
375417 }
376418 }
377419 }
@@ -395,6 +437,16 @@ mod tests {
395437 }
396438 Ok ( 1 )
397439 }
440+
441+ fn shmem_map ( & mut self , req : & VhostUserMMap , _fd : & dyn AsRawFd ) -> HandlerResult < u64 > {
442+ assert_eq ! ( { req. shmid } , 0 ) ;
443+ Ok ( !self . shmem_mappings . insert ( ( req. shm_offset , req. len ) ) as u64 )
444+ }
445+
446+ fn shmem_unmap ( & mut self , req : & VhostUserMMap ) -> HandlerResult < u64 > {
447+ assert_eq ! ( { req. shmid } , 0 ) ;
448+ Ok ( !self . shmem_mappings . remove ( & ( req. shm_offset , req. len ) ) as u64 )
449+ }
398450 }
399451
400452 #[ test]
@@ -436,6 +488,13 @@ mod tests {
436488 assert_eq ! ( handler. handle_request( ) . unwrap( ) , 1 ) ;
437489 assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
438490 assert_eq ! ( handler. handle_request( ) . unwrap( ) , 1 ) ;
491+
492+ // Testing shmem map/unmap messages.
493+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
494+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 1 ) ;
495+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
496+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
497+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
439498 } ) ;
440499
441500 backend. set_shared_object_flag ( true ) ;
@@ -456,6 +515,24 @@ mod tests {
456515 . is_ok( ) ) ;
457516 assert ! ( backend. shared_object_remove( & shobj_msg) . is_ok( ) ) ;
458517 assert ! ( backend. shared_object_remove( & shobj_msg) . is_ok( ) ) ;
518+
519+ let ( _, some_fd_to_map) = UnixStream :: pair ( ) . unwrap ( ) ;
520+ let map_request1 = VhostUserMMap {
521+ shm_offset : 0 ,
522+ len : 4096 ,
523+ ..Default :: default ( )
524+ } ;
525+ let map_request2 = VhostUserMMap {
526+ shm_offset : 4096 ,
527+ len : 8192 ,
528+ ..Default :: default ( )
529+ } ;
530+ backend. shmem_map ( & map_request1, & some_fd_to_map) . unwrap ( ) ;
531+ backend. shmem_unmap ( & map_request2) . unwrap ( ) ;
532+ backend. shmem_map ( & map_request2, & some_fd_to_map) . unwrap ( ) ;
533+ backend. shmem_unmap ( & map_request2) . unwrap ( ) ;
534+ backend. shmem_unmap ( & map_request1) . unwrap ( ) ;
535+
459536 // Ensure that the handler thread did not panic.
460537 assert ! ( frontend_handler. join( ) . is_ok( ) ) ;
461538 }
@@ -485,6 +562,13 @@ mod tests {
485562 assert_eq ! ( handler. handle_request( ) . unwrap( ) , 1 ) ;
486563 assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
487564 assert_eq ! ( handler. handle_request( ) . unwrap( ) , 1 ) ;
565+
566+ // Testing shmem map/unmap messages.
567+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
568+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 1 ) ;
569+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
570+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
571+ assert_eq ! ( handler. handle_request( ) . unwrap( ) , 0 ) ;
488572 } ) ;
489573
490574 backend. set_reply_ack_flag ( true ) ;
@@ -506,6 +590,24 @@ mod tests {
506590 . is_err( ) ) ;
507591 assert ! ( backend. shared_object_remove( & shobj_msg) . is_ok( ) ) ;
508592 assert ! ( backend. shared_object_remove( & shobj_msg) . is_err( ) ) ;
593+
594+ let ( _, some_fd_to_map) = UnixStream :: pair ( ) . unwrap ( ) ;
595+ let map_request1 = VhostUserMMap {
596+ shm_offset : 0 ,
597+ len : 4096 ,
598+ ..Default :: default ( )
599+ } ;
600+ let map_request2 = VhostUserMMap {
601+ shm_offset : 4096 ,
602+ len : 8192 ,
603+ ..Default :: default ( )
604+ } ;
605+ backend. shmem_map ( & map_request1, & some_fd_to_map) . unwrap ( ) ;
606+ backend. shmem_unmap ( & map_request2) . unwrap_err ( ) ;
607+ backend. shmem_map ( & map_request2, & some_fd_to_map) . unwrap ( ) ;
608+ backend. shmem_unmap ( & map_request2) . unwrap ( ) ;
609+ backend. shmem_unmap ( & map_request1) . unwrap ( ) ;
610+
509611 // Ensure that the handler thread did not panic.
510612 assert ! ( frontend_handler. join( ) . is_ok( ) ) ;
511613 }
0 commit comments