| 249 | } |
| 250 | |
| 251 | fn punch_hole(&mut self, offset: u64, length: u64, user_data: u64) -> AsyncIoResult<()> { |
| 252 | let virtual_size = self.metadata.virtual_size(); |
| 253 | let cluster_size = self.cluster_size; |
| 254 | |
| 255 | let result = self |
| 256 | .metadata |
| 257 | .deallocate_bytes( |
| 258 | offset, |
| 259 | length as usize, |
| 260 | self.sparse, |
| 261 | virtual_size, |
| 262 | cluster_size, |
| 263 | self.backing_file.as_deref(), |
| 264 | ) |
| 265 | .map_err(AsyncIoError::PunchHole); |
| 266 | |
| 267 | match result { |
| 268 | Ok(actions) => { |
| 269 | for action in actions { |
| 270 | match action { |
| 271 | DeallocAction::PunchHole { |
| 272 | host_offset, |
| 273 | length, |
| 274 | } => { |
| 275 | let _ = self.data_file.file_mut().punch_hole(host_offset, length); |
| 276 | } |
| 277 | DeallocAction::WriteZeroes { |
| 278 | host_offset, |
| 279 | length, |
| 280 | } => { |
| 281 | let _ = self |
| 282 | .data_file |
| 283 | .file_mut() |
| 284 | .write_zeroes_at(host_offset, length); |
| 285 | } |
| 286 | } |
| 287 | } |
| 288 | self.completion_list.push_back((user_data, 0)); |
| 289 | self.eventfd.write(1).unwrap(); |
| 290 | Ok(()) |
| 291 | } |
| 292 | Err(e) => { |
| 293 | let errno = if let AsyncIoError::PunchHole(ref io_err) = e { |
| 294 | -io_err.raw_os_error().unwrap_or(libc::EIO) |
| 295 | } else { |
| 296 | -libc::EIO |
| 297 | }; |
| 298 | self.completion_list.push_back((user_data, errno)); |
| 299 | self.eventfd.write(1).unwrap(); |
| 300 | Ok(()) |
| 301 | } |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | fn write_zeroes(&mut self, offset: u64, length: u64, user_data: u64) -> AsyncIoResult<()> { |
| 306 | // For QCOW2 write_zeroes uses cluster deallocation, same as punch_hole. |