@@ -11,6 +11,7 @@ use std::error;
1111use std:: fs:: File ;
1212use std:: io;
1313use std:: os:: unix:: io:: { AsRawFd , FromRawFd , RawFd } ;
14+ use std:: os:: unix:: prelude:: IntoRawFd ;
1415use std:: result;
1516use std:: sync:: { Arc , Mutex , RwLock } ;
1617use std:: thread;
@@ -29,7 +30,7 @@ use vm_memory::{
2930 GuestAddress , GuestAddressSpace , GuestMemoryAtomic , GuestMemoryMmap , GuestRegionMmap ,
3031 MmapRegion ,
3132} ;
32- use vm_virtio :: Queue ;
33+ use virtio_queue :: Queue ;
3334use vmm_sys_util:: eventfd:: EventFd ;
3435
3536const MAX_MEM_SLOTS : u64 = 32 ;
@@ -618,17 +619,16 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandlerMut for VhostUserHandler<S> {
618619 fn set_mem_table (
619620 & mut self ,
620621 ctx : & [ VhostUserMemoryRegion ] ,
621- fds : & [ RawFd ] ,
622+ files : Vec < File > ,
622623 ) -> VhostUserResult < ( ) > {
623624 // We need to create tuple of ranges from the list of VhostUserMemoryRegion
624625 // that we get from the caller.
625626 let mut regions: Vec < ( GuestAddress , usize , Option < FileOffset > ) > = Vec :: new ( ) ;
626627 let mut mappings: Vec < AddrMapping > = Vec :: new ( ) ;
627628
628- for ( idx , region ) in ctx. iter ( ) . enumerate ( ) {
629+ for ( region , file ) in ctx. iter ( ) . zip ( files ) {
629630 let g_addr = GuestAddress ( region. guest_phys_addr ) ;
630631 let len = region. memory_size as usize ;
631- let file = unsafe { File :: from_raw_fd ( fds[ idx] ) } ;
632632 let f_off = FileOffset :: new ( file, region. mmap_offset ) ;
633633
634634 regions. push ( ( g_addr, len, Some ( f_off) ) ) ;
@@ -764,17 +764,17 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandlerMut for VhostUserHandler<S> {
764764 Ok ( VhostUserVringState :: new ( index, u32:: from ( next_avail) ) )
765765 }
766766
767- fn set_vring_kick ( & mut self , index : u8 , fd : Option < RawFd > ) -> VhostUserResult < ( ) > {
767+ fn set_vring_kick ( & mut self , index : u8 , file : Option < File > ) -> VhostUserResult < ( ) > {
768768 if index as usize >= self . num_queues {
769769 return Err ( VhostUserError :: InvalidParam ) ;
770770 }
771771
772- if let Some ( kick ) = self . vrings [ index as usize ] . write ( ) . unwrap ( ) . kick . take ( ) {
773- // Close file descriptor set by previous operations .
774- let _ = unsafe { libc :: close ( kick . as_raw_fd ( ) ) } ;
775- }
772+ // SAFETY: EventFd requires that it has sole ownership of its fd. So
773+ // does File, so this is safe .
774+ // Ideally, we'd have a generic way to refer to a uniquely-owned fd,
775+ // such as that proposed by Rust RFC #3128.
776776 self . vrings [ index as usize ] . write ( ) . unwrap ( ) . kick =
777- fd . map ( |x | unsafe { EventFd :: from_raw_fd ( x ) } ) ;
777+ file . map ( |f | unsafe { EventFd :: from_raw_fd ( f . into_raw_fd ( ) ) } ) ;
778778
779779 // Quote from vhost-user specification:
780780 // Client must start ring upon receiving a kick (that is, detecting
@@ -802,32 +802,26 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandlerMut for VhostUserHandler<S> {
802802 Ok ( ( ) )
803803 }
804804
805- fn set_vring_call ( & mut self , index : u8 , fd : Option < RawFd > ) -> VhostUserResult < ( ) > {
805+ fn set_vring_call ( & mut self , index : u8 , file : Option < File > ) -> VhostUserResult < ( ) > {
806806 if index as usize >= self . num_queues {
807807 return Err ( VhostUserError :: InvalidParam ) ;
808808 }
809809
810- if let Some ( call) = self . vrings [ index as usize ] . write ( ) . unwrap ( ) . call . take ( ) {
811- // Close file descriptor set by previous operations.
812- let _ = unsafe { libc:: close ( call. as_raw_fd ( ) ) } ;
813- }
810+ // SAFETY: see comment in set_vring_kick()
814811 self . vrings [ index as usize ] . write ( ) . unwrap ( ) . call =
815- fd . map ( |x | unsafe { EventFd :: from_raw_fd ( x ) } ) ;
812+ file . map ( |f | unsafe { EventFd :: from_raw_fd ( f . into_raw_fd ( ) ) } ) ;
816813
817814 Ok ( ( ) )
818815 }
819816
820- fn set_vring_err ( & mut self , index : u8 , fd : Option < RawFd > ) -> VhostUserResult < ( ) > {
817+ fn set_vring_err ( & mut self , index : u8 , file : Option < File > ) -> VhostUserResult < ( ) > {
821818 if index as usize >= self . num_queues {
822819 return Err ( VhostUserError :: InvalidParam ) ;
823820 }
824821
825- if let Some ( err) = self . vrings [ index as usize ] . write ( ) . unwrap ( ) . err . take ( ) {
826- // Close file descriptor set by previous operations.
827- let _ = unsafe { libc:: close ( err. as_raw_fd ( ) ) } ;
828- }
822+ // SAFETY: see comment in set_vring_kick()
829823 self . vrings [ index as usize ] . write ( ) . unwrap ( ) . err =
830- fd . map ( |x | unsafe { EventFd :: from_raw_fd ( x ) } ) ;
824+ file . map ( |f | unsafe { EventFd :: from_raw_fd ( f . into_raw_fd ( ) ) } ) ;
831825
832826 Ok ( ( ) )
833827 }
@@ -887,9 +881,8 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandlerMut for VhostUserHandler<S> {
887881 fn add_mem_region (
888882 & mut self ,
889883 region : & VhostUserSingleMemoryRegion ,
890- fd : RawFd ,
884+ file : File ,
891885 ) -> VhostUserResult < ( ) > {
892- let file = unsafe { File :: from_raw_fd ( fd) } ;
893886 let mmap_region = MmapRegion :: from_file (
894887 FileOffset :: new ( file, region. mmap_offset ) ,
895888 region. memory_size as usize ,
@@ -952,6 +945,20 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandlerMut for VhostUserHandler<S> {
952945
953946 Ok ( ( ) )
954947 }
948+
949+ fn get_inflight_fd (
950+ & mut self ,
951+ _inflight : & vhost:: vhost_user:: message:: VhostUserInflight ,
952+ ) -> VhostUserResult < ( vhost:: vhost_user:: message:: VhostUserInflight , File ) > {
953+ // Assume the backend hasn't negotiated the inflight feature; it
954+ // wouldn't be correct for the backend to do so, as we don't (yet)
955+ // provide a way for it to handle such requests.
956+ Err ( VhostUserError :: InvalidOperation )
957+ }
958+
959+ fn set_inflight_fd ( & mut self , _inflight : & vhost:: vhost_user:: message:: VhostUserInflight , _file : File ) -> VhostUserResult < ( ) > {
960+ Err ( VhostUserError :: InvalidOperation )
961+ }
955962}
956963
957964impl < S : VhostUserBackend > Drop for VhostUserHandler < S > {
0 commit comments