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

Method cow_write_sync

block/src/qcow_async.rs:477–547  ·  view source on GitHub ↗

Write iovec data cluster-by-cluster with COW from backing file.

(
        address: u64,
        iovecs: &[libc::iovec],
        metadata: &QcowMetadata,
        data_file: &QcowRawFile,
        backing_file: &Option<Arc<dyn BackingRead>>,
        alignment: usize,

Source from the content-addressed store, hash-verified

475
476 /// Write iovec data cluster-by-cluster with COW from backing file.
477 fn cow_write_sync(
478 address: u64,
479 iovecs: &[libc::iovec],
480 metadata: &QcowMetadata,
481 data_file: &QcowRawFile,
482 backing_file: &Option<Arc<dyn BackingRead>>,
483 alignment: usize,
484 cluster_size: u64,
485 ) -> AsyncIoResult<()> {
486 let total_len: usize = iovecs.iter().map(|v| v.iov_len).sum();
487 let mut buf_offset = 0usize;
488
489 while buf_offset < total_len {
490 let curr_addr = address + buf_offset as u64;
491 let intra_offset = curr_addr & (cluster_size - 1);
492 let remaining_in_cluster = (cluster_size - intra_offset) as usize;
493 let count = min(total_len - buf_offset, remaining_in_cluster);
494
495 let backing_data = if let Some(backing) = backing_file
496 .as_ref()
497 .filter(|_| intra_offset != 0 || count < cluster_size as usize)
498 {
499 let cluster_begin = curr_addr - intra_offset;
500 let mut data = vec![0u8; cluster_size as usize];
501 backing
502 .read_at(cluster_begin, &mut data)
503 .map_err(AsyncIoError::WriteVectored)?;
504 Some(data)
505 } else {
506 None
507 };
508
509 let mapping = metadata
510 .map_cluster_for_write(curr_addr, backing_data)
511 .map_err(AsyncIoError::WriteVectored)?;
512
513 match mapping {
514 ClusterWriteMapping::Allocated {
515 offset: host_offset,
516 } => {
517 if alignment > 0 {
518 // O_DIRECT, gather directly into aligned buffer.
519 let mut abuf = AlignedBuf::new(count, alignment)
520 .map_err(AsyncIoError::WriteVectored)?;
521 // SAFETY: iovecs point to valid guest memory buffers
522 unsafe {
523 gather_from_iovecs_into(iovecs, buf_offset, abuf.as_mut_slice(count));
524 }
525 aligned_pwrite(
526 data_file.as_raw_fd(),
527 abuf.as_slice(count),
528 host_offset,
529 alignment,
530 )
531 .map_err(AsyncIoError::WriteVectored)?;
532 } else {
533 // No O_DIRECT, plain buffer is fine.
534 let mut buf = vec![0u8; count];

Callers

nothing calls this directly

Calls 11

newFunction · 0.85
gather_from_iovecs_intoFunction · 0.85
aligned_pwriteFunction · 0.85
pwrite_allFunction · 0.85
iterMethod · 0.80
map_cluster_for_writeMethod · 0.80
as_mut_sliceMethod · 0.80
as_sliceMethod · 0.80
mapMethod · 0.45
read_atMethod · 0.45
as_raw_fdMethod · 0.45

Tested by

no test coverage detected