@@ -115,43 +115,52 @@ impl GuestRegionMmapExt {
115
115
) -> Result < usize , GuestMemoryError > {
116
116
let phys_address = self . get_host_address ( caddr) ?;
117
117
118
- // If and only if we are resuming from a snapshot file, we have a file and it's mapped
119
- // private
120
- if self . inner . file_offset ( ) . is_some ( ) && self . inner . flags ( ) & libc:: MAP_PRIVATE != 0 {
121
- // Mmap a new anonymous region over the present one in order to create a hole
122
- // with zero pages.
123
- // This workaround is (only) needed after resuming from a snapshot file because the
124
- // guest memory is mmaped from file as private. In this case, MADV_DONTNEED on the
125
- // file only drops any anonymous pages in range, but subsequent accesses would read
126
- // whatever page is stored on the backing file. Mmapping anonymous pages ensures it's
127
- // zeroed.
128
- // SAFETY: The address and length are known to be valid.
129
- let ret = unsafe {
130
- libc:: mmap (
131
- phys_address. cast ( ) ,
132
- len,
133
- libc:: PROT_READ | libc:: PROT_WRITE ,
134
- libc:: MAP_FIXED | libc:: MAP_ANONYMOUS | libc:: MAP_PRIVATE ,
135
- -1 ,
136
- 0 ,
137
- )
138
- } ;
139
- if ret == libc:: MAP_FAILED {
140
- let os_error = std:: io:: Error :: last_os_error ( ) ;
141
- error ! ( "discard_range: mmap failed: {:?}" , os_error) ;
142
- return Err ( GuestMemoryError :: IOError ( os_error) ) ;
118
+ match ( self . inner . file_offset ( ) , self . inner . flags ( ) ) {
119
+ // If and only if we are resuming from a snapshot file, we have a file and it's mapped
120
+ // private
121
+ ( Some ( _) , flags) if flags & libc:: MAP_PRIVATE != 0 => {
122
+ // Mmap a new anonymous region over the present one in order to create a hole
123
+ // with zero pages.
124
+ // This workaround is (only) needed after resuming from a snapshot file because the
125
+ // guest memory is mmaped from file as private. In this case, MADV_DONTNEED on the
126
+ // file only drops any anonymous pages in range, but subsequent accesses would read
127
+ // whatever page is stored on the backing file. Mmapping anonymous pages ensures
128
+ // it's zeroed.
129
+ // SAFETY: The address and length are known to be valid.
130
+ let ret = unsafe {
131
+ libc:: mmap (
132
+ phys_address. cast ( ) ,
133
+ len,
134
+ libc:: PROT_READ | libc:: PROT_WRITE ,
135
+ libc:: MAP_FIXED | libc:: MAP_ANONYMOUS | libc:: MAP_PRIVATE ,
136
+ -1 ,
137
+ 0 ,
138
+ )
139
+ } ;
140
+ if ret == libc:: MAP_FAILED {
141
+ let os_error = std:: io:: Error :: last_os_error ( ) ;
142
+ error ! ( "discard_range: mmap failed: {:?}" , os_error) ;
143
+ Err ( GuestMemoryError :: IOError ( os_error) )
144
+ } else {
145
+ Ok ( len)
146
+ }
147
+ }
148
+ // TODO: madvise(MADV_DONTNEED) doesn't actually work with memfd
149
+ // (or in general MAP_SHARED of a fd). In those cases we should use
150
+ // fallocate64(FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE).
151
+ // We keep falling to the madvise branch to keep the previous behaviour.
152
+ ( None , _) | ( Some ( _) , _) => {
153
+ // Madvise the region in order to mark it as not used.
154
+ // SAFETY: The address and length are known to be valid.
155
+ let ret = unsafe { libc:: madvise ( phys_address. cast ( ) , len, libc:: MADV_DONTNEED ) } ;
156
+ if ret < 0 {
157
+ let os_error = std:: io:: Error :: last_os_error ( ) ;
158
+ error ! ( "discard_range: madvise failed: {:?}" , os_error) ;
159
+ Err ( GuestMemoryError :: IOError ( os_error) )
160
+ } else {
161
+ Ok ( len)
162
+ }
143
163
}
144
- }
145
-
146
- // Madvise the region in order to mark it as not used.
147
- // SAFETY: The address and length are known to be valid.
148
- let ret = unsafe { libc:: madvise ( phys_address. cast ( ) , len, libc:: MADV_DONTNEED ) } ;
149
- if ret < 0 {
150
- let os_error = std:: io:: Error :: last_os_error ( ) ;
151
- error ! ( "discard_range: madvise failed: {:?}" , os_error) ;
152
- Err ( GuestMemoryError :: IOError ( os_error) )
153
- } else {
154
- Ok ( len)
155
164
}
156
165
}
157
166
}
0 commit comments