block: qcow: Move RawBacking to qcow/backing module

Move the raw backing file reader into the new qcow/backing module
so it can be shared between qcow_sync and the upcoming qcow_async
backend.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-03-20 16:03:24 +01:00
committed by Rob Bradford
parent 81f43f96c3
commit e345299f4d
3 changed files with 42 additions and 27 deletions

40
block/src/qcow/backing.rs Normal file
View File

@@ -0,0 +1,40 @@
// Copyright © 2021 Intel Corporation
//
// Copyright 2026 The Cloud Hypervisor Authors. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
//! Thread safe backing file readers for QCOW2 images.
use std::io;
use std::os::fd::{AsRawFd, OwnedFd};
use crate::qcow::metadata::BackingRead;
use crate::qcow_common::pread_exact;
/// Raw backing file using pread64 on a duplicated fd.
pub(crate) struct RawBacking {
pub(crate) fd: OwnedFd,
pub(crate) virtual_size: u64,
}
// SAFETY: The only I/O operation is pread64 which is position independent
// and safe for concurrent use from multiple threads.
unsafe impl Sync for RawBacking {}
impl BackingRead for RawBacking {
fn read_at(&self, address: u64, buf: &mut [u8]) -> io::Result<()> {
if address >= self.virtual_size {
buf.fill(0);
return Ok(());
}
let available = (self.virtual_size - address) as usize;
if available >= buf.len() {
pread_exact(self.fd.as_raw_fd(), buf, address)
} else {
pread_exact(self.fd.as_raw_fd(), &mut buf[..available], address)?;
buf[available..].fill(0);
Ok(())
}
}
}

View File

@@ -4,6 +4,7 @@
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
pub(crate) mod backing;
mod decoder;
mod header;
pub(crate) mod metadata;

View File

@@ -15,6 +15,7 @@ use vmm_sys_util::write_zeroes::{PunchHole, WriteZeroesAt};
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFileError};
use crate::disk_file;
use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp};
use crate::qcow::backing::RawBacking;
use crate::qcow::metadata::{
BackingRead, ClusterReadMapping, ClusterWriteMapping, DeallocAction, QcowMetadata,
};
@@ -26,33 +27,6 @@ use crate::qcow_common::{
gather_from_iovecs, pread_exact, pwrite_all, scatter_to_iovecs, zero_fill_iovecs,
};
/// Raw backing file using pread64 on a duplicated fd.
struct RawBacking {
fd: OwnedFd,
virtual_size: u64,
}
// SAFETY: The only I/O operation is pread64 which is position independent
// and safe for concurrent use from multiple threads.
unsafe impl Sync for RawBacking {}
impl BackingRead for RawBacking {
fn read_at(&self, address: u64, buf: &mut [u8]) -> io::Result<()> {
if address >= self.virtual_size {
buf.fill(0);
return Ok(());
}
let available = (self.virtual_size - address) as usize;
if available >= buf.len() {
pread_exact(self.fd.as_raw_fd(), buf, address)
} else {
pread_exact(self.fd.as_raw_fd(), &mut buf[..available], address)?;
buf[available..].fill(0);
Ok(())
}
}
}
/// QCOW2 backing file with RwLock metadata and pread64 data reads.
///
/// Read only because backing files never receive writes. Nested backing