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

Method map_write

block/src/qcow/metadata.rs:523–583  ·  view source on GitHub ↗

Write path mapping. Always called under write lock.

(
        &mut self,
        address: u64,
        backing_data: Option<Vec<u8>>,
    )

Source from the content-addressed store, hash-verified

521
522 /// Write path mapping. Always called under write lock.
523 fn map_write(
524 &mut self,
525 address: u64,
526 backing_data: Option<Vec<u8>>,
527 ) -> io::Result<ClusterWriteMapping> {
528 if address >= self.header.size {
529 return Err(io::Error::from_raw_os_error(EINVAL));
530 }
531
532 let l1_index = self.l1_table_index(address) as usize;
533 let l2_addr_disk = match self.l1_table.get(l1_index) {
534 Some(&addr) => addr,
535 None => return Err(io::Error::from_raw_os_error(EINVAL)),
536 };
537 let l2_index = self.l2_table_index(address) as usize;
538
539 let mut set_refcounts = Vec::new();
540
541 if let Some(new_addr) = self.cache_l2_cluster_alloc(l1_index, l2_addr_disk)? {
542 set_refcounts.push((new_addr, 1));
543 }
544
545 let l2_entry = self.l2_cache.get(l1_index).unwrap()[l2_index];
546 let cluster_addr = if l2_entry_is_compressed(l2_entry) {
547 let decompressed_cluster = self.decompress_l2_cluster(l2_entry)?;
548 let cluster_addr = self.append_data_cluster(None)?;
549 self.update_cluster_addr(l1_index, l2_index, cluster_addr, &mut set_refcounts)?;
550 self.raw_file
551 .file_mut()
552 .seek(io::SeekFrom::Start(cluster_addr))?;
553 let nwritten = io::Write::write(self.raw_file.file_mut(), &decompressed_cluster)?;
554 if nwritten != decompressed_cluster.len() {
555 self.set_corrupt_bit_best_effort();
556 return Err(io::Error::from_raw_os_error(EIO));
557 }
558 self.deallocate_compressed_cluster(l2_entry)?;
559 cluster_addr
560 } else if l2_entry_is_empty(l2_entry) || l2_entry_is_zero(l2_entry) {
561 let cluster_addr = self.append_data_cluster(backing_data)?;
562 self.update_cluster_addr(l1_index, l2_index, cluster_addr, &mut set_refcounts)?;
563 cluster_addr
564 } else {
565 // Already allocated - validate alignment
566 let cluster_addr = l2_entry_std_cluster_addr(l2_entry);
567 if cluster_addr & (self.raw_file.cluster_size() - 1) != 0 {
568 self.set_corrupt_bit_best_effort();
569 return Err(io::Error::from_raw_os_error(EIO));
570 }
571 cluster_addr
572 };
573
574 // Apply deferred refcount updates
575 for (addr, refcount) in set_refcounts {
576 self.set_cluster_refcount_track_freed(addr, refcount)?;
577 }
578
579 let intra_offset = self.raw_file.cluster_offset(address);
580 Ok(ClusterWriteMapping::Allocated {

Callers 2

map_cluster_for_writeMethod · 0.80
deallocate_bytesMethod · 0.80

Calls 15

newFunction · 0.85
l2_entry_is_compressedFunction · 0.85
writeFunction · 0.85
l2_entry_is_emptyFunction · 0.85
l2_entry_is_zeroFunction · 0.85
file_mutMethod · 0.80
cluster_offsetMethod · 0.80
l1_table_indexMethod · 0.45
getMethod · 0.45
l2_table_indexMethod · 0.45

Tested by

no test coverage detected