MCPcopy Create free account
hub / github.com/cloud-hypervisor/cloud-hypervisor / deallocate_bytes

Method deallocate_bytes

block/src/qcow/metadata.rs:275–333  ·  view source on GitHub ↗

Deallocates a range of bytes. Full clusters are deallocated via metadata. Partial clusters need the caller to write zeros. This method returns a list of actions the caller should take.

(
        &self,
        address: u64,
        length: usize,
        sparse: bool,
        virtual_size: u64,
        cluster_size: u64,
        backing_file: Option<&dyn BackingRead>,
    )

Source from the content-addressed store, hash-verified

273 /// Partial clusters need the caller to write zeros. This method returns a
274 /// list of actions the caller should take.
275 pub(crate) fn deallocate_bytes(
276 &self,
277 address: u64,
278 length: usize,
279 sparse: bool,
280 virtual_size: u64,
281 cluster_size: u64,
282 backing_file: Option<&dyn BackingRead>,
283 ) -> io::Result<Vec<DeallocAction>> {
284 if address.checked_add(length as u64).is_none() {
285 return Ok(Vec::new());
286 }
287 let mut inner = self.inner.write().unwrap();
288 let mut actions = Vec::new();
289
290 let file_end = virtual_size;
291 let remaining_in_file = file_end.saturating_sub(address);
292 let write_count = min(length as u64, remaining_in_file) as usize;
293
294 let mut nwritten = 0usize;
295 while nwritten < write_count {
296 let curr_addr = address + nwritten as u64;
297 let offset_in_cluster = inner.raw_file.cluster_offset(curr_addr) as usize;
298 let count = min(
299 write_count - nwritten,
300 cluster_size as usize - offset_in_cluster,
301 );
302
303 if count == cluster_size as usize {
304 let punch_offset = inner.deallocate_cluster(curr_addr, sparse)?;
305 if let Some(host_offset) = punch_offset {
306 actions.push(DeallocAction::PunchHole {
307 host_offset,
308 length: cluster_size,
309 });
310 }
311 } else {
312 // Partial cluster - COW from backing to preserve non zeroed bytes,
313 // then the caller writes zeros to the partial range.
314 let backing_data = if let Some(backing) = backing_file {
315 let cluster_begin = curr_addr - offset_in_cluster as u64;
316 let mut data = vec![0u8; cluster_size as usize];
317 backing.read_at(cluster_begin, &mut data)?;
318 Some(data)
319 } else {
320 None
321 };
322 let mapping = inner.map_write(curr_addr, backing_data)?;
323 let ClusterWriteMapping::Allocated { offset } = mapping;
324 actions.push(DeallocAction::WriteZeroes {
325 host_offset: offset,
326 length: count,
327 });
328 }
329
330 nwritten += count;
331 }
332 Ok(actions)

Callers 2

punch_holeMethod · 0.45
punch_holeMethod · 0.45

Calls 7

newFunction · 0.85
cluster_offsetMethod · 0.80
map_writeMethod · 0.80
writeMethod · 0.45
deallocate_clusterMethod · 0.45
pushMethod · 0.45
read_atMethod · 0.45

Tested by

no test coverage detected