99
1010use bitflags:: bitflags;
1111use libc:: { c_int, c_void, MAP_SHARED , _SC_PAGESIZE} ;
12+ use std:: sync:: Arc ;
1213use std:: { io, mem:: size_of, os:: raw:: c_ulong, os:: unix:: io:: AsRawFd , ptr:: null_mut, result} ;
13-
1414use vmm_sys_util:: {
1515 fam:: { Error as FamError , FamStruct , FamStructWrapper } ,
1616 generate_fam_struct_impl,
@@ -26,28 +26,23 @@ use tests::ioctl_with_ref;
2626
2727use crate :: bitmap:: { Bitmap , NewBitmap , BS } ;
2828use crate :: guest_memory:: { FileOffset , GuestAddress } ;
29+ use crate :: mmap:: unix:: MmapRegion as MmapUnix ;
2930use crate :: volatile_memory:: { self , VolatileMemory , VolatileSlice } ;
3031use crate :: {
3132 guest_memory, Address , GuestMemoryRegion , GuestMemoryRegionBytes , GuestRegionCollection ,
32- GuestUsize , MemoryRegionAddress ,
33+ GuestUsize , MemoryRegionAddress , MmapRegionBuilder ,
3334} ;
3435
3536/// Error conditions that may arise when creating a new `MmapRegion` object.
3637#[ derive( Debug , thiserror:: Error ) ]
3738pub enum Error {
38- /// The specified file offset and length cause overflow when added.
39- #[ error( "The specified file offset and length cause overflow when added" ) ]
40- InvalidOffsetLength ,
4139 /// The forbidden `MAP_FIXED` flag was specified.
4240 #[ error( "The forbidden `MAP_FIXED` flag was specified" ) ]
4341 MapFixed ,
44- /// A mapping with offset + length > EOF was attempted.
45- #[ error( "The specified file offset and length is greater then file length" ) ]
46- MappingPastEof ,
4742 /// The `mmap` call returned an error.
4843 #[ error( "{0}" ) ]
4944 Mmap ( io:: Error ) ,
50- /// Invalid file offset.
45+ /// Invalid file offset (non-zero of missing altogether) .
5146 #[ error( "Invalid file offset" ) ]
5247 InvalidFileOffset ,
5348 /// Memory mapped in advance.
@@ -62,6 +57,9 @@ pub enum Error {
6257 /// Unexpected error.
6358 #[ error( "Unexpected error" ) ]
6459 Unexpected ,
60+ /// Error establishing normal unix mapping
61+ #[ error[ "{0}" ] ]
62+ Unix ( #[ from] crate :: mmap:: unix:: Error ) ,
6563}
6664
6765type Result < T > = result:: Result < T , Error > ;
@@ -427,45 +425,6 @@ impl<B: Bitmap> VolatileMemory for MmapRegion<B> {
427425 }
428426}
429427
430- #[ derive( Clone , Debug , PartialEq ) ]
431- struct MmapUnix {
432- addr : * mut u8 ,
433- size : usize ,
434- }
435-
436- impl MmapUnix {
437- fn new ( size : usize , prot : i32 , flags : i32 , fd : i32 , f_offset : u64 ) -> Result < Self > {
438- let addr =
439- // SAFETY: This is safe because we're not allowing MAP_FIXED, and invalid parameters
440- // cannot break Rust safety guarantees (things may change if we're mapping /dev/mem or
441- // some wacky file).
442- unsafe { libc:: mmap ( null_mut ( ) , size, prot, flags, fd, f_offset as libc:: off_t ) } ;
443-
444- if addr == libc:: MAP_FAILED {
445- return Err ( Error :: Mmap ( io:: Error :: last_os_error ( ) ) ) ;
446- }
447-
448- Ok ( Self {
449- addr : addr as * mut u8 ,
450- size,
451- } )
452- }
453-
454- fn addr ( & self ) -> * mut u8 {
455- self . addr
456- }
457- }
458-
459- impl Drop for MmapUnix {
460- fn drop ( & mut self ) {
461- // SAFETY: This is safe because we mmap the area at addr ourselves, and nobody
462- // else is holding a reference to it.
463- unsafe {
464- libc:: munmap ( self . addr as * mut libc:: c_void , self . size ) ;
465- }
466- }
467- }
468-
469428// Bit mask for the vhost-user xen mmap message.
470429bitflags ! {
471430 /// Flags for the Xen mmap message.
@@ -531,21 +490,18 @@ fn pages(size: usize) -> (usize, usize) {
531490 ( num, page_size * num)
532491}
533492
534- fn validate_file ( file_offset : & Option < FileOffset > ) -> Result < ( i32 , u64 ) > {
493+ fn validate_file ( file_offset : Option < FileOffset > ) -> Result < FileOffset > {
535494 let file_offset = match file_offset {
536495 Some ( f) => f,
537496 None => return Err ( Error :: InvalidFileOffset ) ,
538497 } ;
539498
540- let fd = file_offset. file ( ) . as_raw_fd ( ) ;
541- let f_offset = file_offset. start ( ) ;
542-
543499 // We don't allow file offsets with Xen foreign mappings.
544- if f_offset != 0 {
545- return Err ( Error :: InvalidOffsetLength ) ;
500+ if file_offset . start ( ) != 0 {
501+ return Err ( Error :: InvalidFileOffset ) ;
546502 }
547503
548- Ok ( ( fd , f_offset ) )
504+ Ok ( file_offset )
549505}
550506
551507// Xen Foreign memory mapping interface.
@@ -556,27 +512,22 @@ trait MmapXenTrait: std::fmt::Debug {
556512}
557513
558514// Standard Unix memory mapping for testing other crates.
559- #[ derive( Clone , Debug , PartialEq ) ]
515+ #[ derive( Clone , Debug ) ]
560516struct MmapXenUnix ( MmapUnix , GuestAddress ) ;
561517
562518impl MmapXenUnix {
563519 fn new ( range : & MmapRange ) -> Result < Self > {
564- let ( fd, offset) = if let Some ( ref f_off) = range. file_offset {
565- ( f_off. file ( ) . as_raw_fd ( ) , f_off. start ( ) )
566- } else {
567- ( -1 , 0 )
568- } ;
520+ let mut builder = MmapRegionBuilder :: new ( range. size )
521+ . with_mmap_prot ( range. prot . ok_or ( Error :: Unexpected ) ?)
522+ . with_mmap_flags ( range. flags . ok_or ( Error :: Unexpected ) ?) ;
569523
570- Ok ( Self (
571- MmapUnix :: new (
572- range. size ,
573- range. prot . ok_or ( Error :: Unexpected ) ?,
574- range. flags . ok_or ( Error :: Unexpected ) ?,
575- fd,
576- offset,
577- ) ?,
578- range. addr ,
579- ) )
524+ if let Some ( ref file_offset) = range. file_offset {
525+ builder = builder. with_file_offset ( file_offset. clone ( ) ) ;
526+ }
527+
528+ let mmap_unix = builder. build ( ) ?;
529+
530+ Ok ( MmapXenUnix ( mmap_unix, range. addr ) )
580531 }
581532}
582533
@@ -587,7 +538,7 @@ impl MmapXenTrait for MmapXenUnix {
587538 }
588539
589540 fn addr ( & self ) -> * mut u8 {
590- self . 0 . addr ( )
541+ self . 0 . as_ptr ( )
591542 }
592543
593544 fn guest_base ( & self ) -> GuestAddress {
@@ -626,7 +577,7 @@ fn ioctl_privcmd_mmapbatch_v2() -> c_ulong {
626577}
627578
628579// Xen foreign memory specific implementation.
629- #[ derive( Clone , Debug , PartialEq ) ]
580+ #[ derive( Clone , Debug ) ]
630581struct MmapXenForeign {
631582 domid : u32 ,
632583 guest_base : GuestAddress ,
@@ -642,16 +593,15 @@ impl AsRawFd for MmapXenForeign {
642593
643594impl MmapXenForeign {
644595 fn new ( range : & MmapRange ) -> Result < Self > {
645- let ( fd, f_offset) = validate_file ( & range. file_offset ) ?;
646596 let ( count, size) = pages ( range. size ) ;
597+ let file_offset = validate_file ( range. file_offset . clone ( ) ) ?;
598+ let fd = file_offset. file ( ) . as_raw_fd ( ) ;
647599
648- let unix_mmap = MmapUnix :: new (
649- size,
650- range. prot . ok_or ( Error :: Unexpected ) ?,
651- range. flags . ok_or ( Error :: Unexpected ) ? | MAP_SHARED ,
652- fd,
653- f_offset,
654- ) ?;
600+ let unix_mmap = MmapRegionBuilder :: new ( size)
601+ . with_mmap_prot ( range. prot . ok_or ( Error :: Unexpected ) ?)
602+ . with_mmap_flags ( range. flags . ok_or ( Error :: Unexpected ) ? | MAP_SHARED )
603+ . with_file_offset ( file_offset)
604+ . build ( ) ?;
655605
656606 let foreign = Self {
657607 domid : range. mmap_data ,
@@ -701,7 +651,7 @@ impl MmapXenTrait for MmapXenForeign {
701651 }
702652
703653 fn addr ( & self ) -> * mut u8 {
704- self . unix_mmap . addr ( )
654+ self . unix_mmap . as_ptr ( )
705655 }
706656
707657 fn guest_base ( & self ) -> GuestAddress {
@@ -855,12 +805,12 @@ impl AsRawFd for MmapXenGrant {
855805
856806impl MmapXenGrant {
857807 fn new ( range : & MmapRange , mmap_flags : MmapXenFlags ) -> Result < Self > {
858- validate_file ( & range. file_offset ) ?;
808+ let file_offset = validate_file ( range. file_offset . clone ( ) ) ?;
859809
860810 let mut grant = Self {
861811 guest_base : range. addr ,
862812 unix_mmap : None ,
863- file_offset : range . file_offset . as_ref ( ) . unwrap ( ) . clone ( ) ,
813+ file_offset,
864814 flags : range. flags . ok_or ( Error :: Unexpected ) ?,
865815 size : 0 ,
866816 index : 0 ,
@@ -884,7 +834,15 @@ impl MmapXenGrant {
884834 fn mmap_range ( & self , addr : GuestAddress , size : usize , prot : i32 ) -> Result < ( MmapUnix , u64 ) > {
885835 let ( count, size) = pages ( size) ;
886836 let index = self . mmap_ioctl ( addr, count) ?;
887- let unix_mmap = MmapUnix :: new ( size, prot, self . flags , self . as_raw_fd ( ) , index) ?;
837+
838+ let unix_mmap = MmapRegionBuilder :: new ( size)
839+ . with_mmap_prot ( prot)
840+ . with_mmap_flags ( self . flags )
841+ . with_file_offset ( FileOffset :: from_arc (
842+ Arc :: clone ( self . file_offset . arc ( ) ) ,
843+ index,
844+ ) )
845+ . build ( ) ?;
888846
889847 Ok ( ( unix_mmap, index) )
890848 }
@@ -934,7 +892,7 @@ impl MmapXenTrait for MmapXenGrant {
934892
935893 fn addr ( & self ) -> * mut u8 {
936894 if let Some ( ref unix_mmap) = self . unix_mmap {
937- unix_mmap. addr ( )
895+ unix_mmap. as_ptr ( )
938896 } else {
939897 null_mut ( )
940898 }
@@ -983,7 +941,7 @@ impl MmapXenSlice {
983941 let ( unix_mmap, index) = grant. mmap_range ( GuestAddress ( addr) , size, prot) ?;
984942
985943 // SAFETY: We have already mapped the range including offset.
986- let addr = unsafe { unix_mmap. addr ( ) . add ( offset) } ;
944+ let addr = unsafe { unix_mmap. as_ptr ( ) . add ( offset) } ;
987945
988946 Ok ( Self {
989947 grant : Some ( grant) ,
@@ -1085,6 +1043,7 @@ mod tests {
10851043 fn raw_os_error ( & self ) -> i32 {
10861044 match self {
10871045 Error :: Mmap ( e) => e. raw_os_error ( ) . unwrap ( ) ,
1046+ Error :: Unix ( crate :: mmap:: unix:: Error :: Mmap ( e) ) => e. raw_os_error ( ) . unwrap ( ) ,
10881047 _ => i32:: MIN ,
10891048 }
10901049 }
@@ -1183,7 +1142,7 @@ mod tests {
11831142 let mut range = MmapRange :: initialized ( true ) ;
11841143 range. file_offset = Some ( FileOffset :: new ( TempFile :: new ( ) . unwrap ( ) . into_file ( ) , 1 ) ) ;
11851144 let r = MmapXenForeign :: new ( & range) ;
1186- assert ! ( matches!( r. unwrap_err( ) , Error :: InvalidOffsetLength ) ) ;
1145+ assert ! ( matches!( r. unwrap_err( ) , Error :: InvalidFileOffset ) ) ;
11871146
11881147 let mut range = MmapRange :: initialized ( true ) ;
11891148 range. size = 0 ;
@@ -1220,7 +1179,7 @@ mod tests {
12201179 let mut range = MmapRange :: initialized ( true ) ;
12211180 range. file_offset = Some ( FileOffset :: new ( TempFile :: new ( ) . unwrap ( ) . into_file ( ) , 1 ) ) ;
12221181 let r = MmapXenGrant :: new ( & range, MmapXenFlags :: NO_ADVANCE_MAP ) ;
1223- assert ! ( matches!( r. unwrap_err( ) , Error :: InvalidOffsetLength ) ) ;
1182+ assert ! ( matches!( r. unwrap_err( ) , Error :: InvalidFileOffset ) ) ;
12241183
12251184 let mut range = MmapRange :: initialized ( true ) ;
12261185 range. size = 0 ;
0 commit comments