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

Method file_read

block/src/qcow/mod.rs:1424–1480  ·  view source on GitHub ↗
(
        &mut self,
        address: u64,
        count: usize,
        buf: &mut [u8],
    )

Source from the content-addressed store, hash-verified

1422 }
1423
1424 fn file_read(
1425 &mut self,
1426 address: u64,
1427 count: usize,
1428 buf: &mut [u8],
1429 ) -> std::io::Result<Option<()>> {
1430 let err_inval = std::io::Error::from_raw_os_error(EINVAL);
1431 if address >= self.virtual_size() {
1432 return Err(err_inval);
1433 }
1434
1435 let l1_index = self.l1_table_index(address) as usize;
1436 let l2_addr_disk = *self
1437 .l1_table
1438 .get(l1_index)
1439 .ok_or_else(|| std::io::Error::from_raw_os_error(EINVAL))?;
1440
1441 if l2_addr_disk == 0 {
1442 // Reading from an unallocated cluster will return zeros.
1443 return Ok(None);
1444 }
1445
1446 let l2_index = self.l2_table_index(address) as usize;
1447
1448 self.cache_l2_cluster(l1_index, l2_addr_disk, false)?;
1449
1450 let l2_entry = self.l2_cache.get(l1_index).unwrap()[l2_index];
1451 if l2_entry_is_empty(l2_entry) {
1452 // Reading from an unallocated cluster will return zeros.
1453 return Ok(None);
1454 } else if l2_entry_is_compressed(l2_entry) {
1455 // Compressed cluster.
1456 // Read it, decompress, then return slice from decompressed data.
1457 let mut decompressed_cluster = self.decompress_l2_cluster(l2_entry)?;
1458 decompressed_cluster.resize(self.raw_file.cluster_size() as usize, 0);
1459 let start = self.raw_file.cluster_offset(address) as usize;
1460 let end = start.checked_add(count);
1461 if end.is_none() || end.unwrap() > decompressed_cluster.len() {
1462 return Err(err_inval);
1463 }
1464 buf[..count].copy_from_slice(&decompressed_cluster[start..end.unwrap()]);
1465 } else if l2_entry_is_zero(l2_entry) {
1466 // Cluster with zero flag reads as zeros without accessing disk.
1467 return Ok(None);
1468 } else {
1469 let cluster_addr = l2_entry_std_cluster_addr(l2_entry);
1470 if cluster_addr & (self.raw_file.cluster_size() - 1) != 0 {
1471 self.set_corrupt_bit_best_effort();
1472 return Err(io::Error::from_raw_os_error(EIO));
1473 }
1474 let start = cluster_addr + self.raw_file.cluster_offset(address);
1475 let raw_file = self.raw_file.file_mut();
1476 raw_file.seek(SeekFrom::Start(start))?;
1477 raw_file.read_exact(buf)?;
1478 }
1479 Ok(Some(()))
1480 }
1481

Callers 1

readMethod · 0.80

Calls 15

l2_entry_is_emptyFunction · 0.85
l2_entry_is_compressedFunction · 0.85
l2_entry_is_zeroFunction · 0.85
cluster_offsetMethod · 0.80
file_mutMethod · 0.80
virtual_sizeMethod · 0.45
l1_table_indexMethod · 0.45
getMethod · 0.45
l2_table_indexMethod · 0.45
cache_l2_clusterMethod · 0.45
decompress_l2_clusterMethod · 0.45

Tested by

no test coverage detected