mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
block: introduce trait BlockBackend
for block types
This commit introduces the trait `BlockBackend` with generic ops including read, write and seek, which can be used for common I/O interfaces for the block types without using `DiskFile` and `AsyncIo`. Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
This commit is contained in:
parent
447cad3861
commit
741d640330
@ -3,6 +3,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::vhd::VhdFooter;
|
use crate::vhd::VhdFooter;
|
||||||
|
use crate::BlockBackend;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Seek, SeekFrom, Write};
|
use std::io::{Read, Seek, SeekFrom, Write};
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
@ -24,10 +25,6 @@ impl FixedVhd {
|
|||||||
position: 0,
|
position: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> u64 {
|
|
||||||
self.size
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for FixedVhd {
|
impl AsRawFd for FixedVhd {
|
||||||
@ -76,6 +73,12 @@ impl Seek for FixedVhd {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockBackend for FixedVhd {
|
||||||
|
fn size(&self) -> std::result::Result<u64, crate::Error> {
|
||||||
|
Ok(self.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clone for FixedVhd {
|
impl Clone for FixedVhd {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -7,6 +7,7 @@ use crate::async_io::{
|
|||||||
};
|
};
|
||||||
use crate::fixed_vhd::FixedVhd;
|
use crate::fixed_vhd::FixedVhd;
|
||||||
use crate::raw_async::RawFileAsync;
|
use crate::raw_async::RawFileAsync;
|
||||||
|
use crate::BlockBackend;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
@ -21,12 +22,12 @@ impl FixedVhdDiskAsync {
|
|||||||
|
|
||||||
impl DiskFile for FixedVhdDiskAsync {
|
impl DiskFile for FixedVhdDiskAsync {
|
||||||
fn size(&mut self) -> DiskFileResult<u64> {
|
fn size(&mut self) -> DiskFileResult<u64> {
|
||||||
Ok(self.0.size())
|
Ok(self.0.size().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
||||||
Ok(Box::new(
|
Ok(Box::new(
|
||||||
FixedVhdAsync::new(self.0.as_raw_fd(), ring_depth, self.0.size())
|
FixedVhdAsync::new(self.0.as_raw_fd(), ring_depth, self.0.size().unwrap())
|
||||||
.map_err(DiskFileError::NewAsyncIo)?,
|
.map_err(DiskFileError::NewAsyncIo)?,
|
||||||
) as Box<dyn AsyncIo>)
|
) as Box<dyn AsyncIo>)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use crate::async_io::{
|
|||||||
};
|
};
|
||||||
use crate::fixed_vhd::FixedVhd;
|
use crate::fixed_vhd::FixedVhd;
|
||||||
use crate::raw_sync::RawFileSync;
|
use crate::raw_sync::RawFileSync;
|
||||||
|
use crate::BlockBackend;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
@ -21,12 +22,12 @@ impl FixedVhdDiskSync {
|
|||||||
|
|
||||||
impl DiskFile for FixedVhdDiskSync {
|
impl DiskFile for FixedVhdDiskSync {
|
||||||
fn size(&mut self) -> DiskFileResult<u64> {
|
fn size(&mut self) -> DiskFileResult<u64> {
|
||||||
Ok(self.0.size())
|
Ok(self.0.size().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
||||||
Ok(Box::new(
|
Ok(Box::new(
|
||||||
FixedVhdSync::new(self.0.as_raw_fd(), self.0.size())
|
FixedVhdSync::new(self.0.as_raw_fd(), self.0.size().unwrap())
|
||||||
.map_err(DiskFileError::NewAsyncIo)?,
|
.map_err(DiskFileError::NewAsyncIo)?,
|
||||||
) as Box<dyn AsyncIo>)
|
) as Box<dyn AsyncIo>)
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,9 @@ pub mod vhdx;
|
|||||||
pub mod vhdx_sync;
|
pub mod vhdx_sync;
|
||||||
|
|
||||||
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult};
|
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult};
|
||||||
|
use crate::fixed_vhd::FixedVhd;
|
||||||
|
use crate::qcow::{QcowFile, RawFile};
|
||||||
|
use crate::vhdx::{Vhdx, VhdxError};
|
||||||
#[cfg(feature = "io_uring")]
|
#[cfg(feature = "io_uring")]
|
||||||
use io_uring::{opcode, IoUring, Probe};
|
use io_uring::{opcode, IoUring, Probe};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
@ -37,6 +40,7 @@ use std::alloc::{alloc_zeroed, dealloc, Layout};
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
||||||
use std::os::linux::fs::MetadataExt;
|
use std::os::linux::fs::MetadataExt;
|
||||||
@ -76,12 +80,22 @@ pub enum Error {
|
|||||||
DescriptorChainTooShort,
|
DescriptorChainTooShort,
|
||||||
#[error("Guest gave us a descriptor that was too short to use")]
|
#[error("Guest gave us a descriptor that was too short to use")]
|
||||||
DescriptorLengthTooSmall,
|
DescriptorLengthTooSmall,
|
||||||
|
#[error("Failed to detect image type: {0}")]
|
||||||
|
DetectImageType(std::io::Error),
|
||||||
|
#[error("Failure in fixed vhd: {0}")]
|
||||||
|
FixedVhdError(std::io::Error),
|
||||||
#[error("Getting a block's metadata fails for any reason")]
|
#[error("Getting a block's metadata fails for any reason")]
|
||||||
GetFileMetadata,
|
GetFileMetadata,
|
||||||
#[error("The requested operation would cause a seek beyond disk end")]
|
#[error("The requested operation would cause a seek beyond disk end")]
|
||||||
InvalidOffset,
|
InvalidOffset,
|
||||||
|
#[error("Failure in qcow: {0}")]
|
||||||
|
QcowError(qcow::Error),
|
||||||
|
#[error("Failure in raw file: {0}")]
|
||||||
|
RawFileError(std::io::Error),
|
||||||
#[error("The requested operation does not support multiple descriptors")]
|
#[error("The requested operation does not support multiple descriptors")]
|
||||||
TooManyDescriptors,
|
TooManyDescriptors,
|
||||||
|
#[error("Failure in vhdx: {0}")]
|
||||||
|
VhdxError(VhdxError),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_device_id(disk_path: &Path) -> result::Result<String, Error> {
|
fn build_device_id(disk_path: &Path) -> result::Result<String, Error> {
|
||||||
@ -739,3 +753,26 @@ pub fn detect_image_type(f: &mut File) -> std::io::Result<ImageType> {
|
|||||||
|
|
||||||
Ok(image_type)
|
Ok(image_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait BlockBackend: Read + Write + Seek + Send + Debug {
|
||||||
|
fn size(&self) -> Result<u64, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inspect the image file type and create an appropriate disk file to match it.
|
||||||
|
pub fn create_disk_file(mut file: File, direct_io: bool) -> Result<Box<dyn BlockBackend>, Error> {
|
||||||
|
let image_type = detect_image_type(&mut file).map_err(Error::DetectImageType)?;
|
||||||
|
|
||||||
|
Ok(match image_type {
|
||||||
|
ImageType::Qcow2 => {
|
||||||
|
Box::new(QcowFile::from(RawFile::new(file, direct_io)).map_err(Error::QcowError)?)
|
||||||
|
as Box<dyn BlockBackend>
|
||||||
|
}
|
||||||
|
ImageType::FixedVhd => {
|
||||||
|
Box::new(FixedVhd::new(file).map_err(Error::FixedVhdError)?) as Box<dyn BlockBackend>
|
||||||
|
}
|
||||||
|
ImageType::Vhdx => {
|
||||||
|
Box::new(Vhdx::new(file).map_err(Error::VhdxError)?) as Box<dyn BlockBackend>
|
||||||
|
}
|
||||||
|
ImageType::Raw => Box::new(RawFile::new(file, direct_io)) as Box<dyn BlockBackend>,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@ use crate::qcow::{
|
|||||||
refcount::RefCount,
|
refcount::RefCount,
|
||||||
vec_cache::{CacheMap, Cacheable, VecCache},
|
vec_cache::{CacheMap, Cacheable, VecCache},
|
||||||
};
|
};
|
||||||
|
use crate::BlockBackend;
|
||||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use libc::{EINVAL, ENOSPC, ENOTSUP};
|
use libc::{EINVAL, ENOSPC, ENOTSUP};
|
||||||
use remain::sorted;
|
use remain::sorted;
|
||||||
@ -1555,6 +1556,12 @@ impl SeekHole for QcowFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockBackend for QcowFile {
|
||||||
|
fn size(&self) -> std::result::Result<u64, crate::Error> {
|
||||||
|
Ok(self.virtual_size())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns an Error if the given offset doesn't align to a cluster boundary.
|
// Returns an Error if the given offset doesn't align to a cluster boundary.
|
||||||
fn offset_is_cluster_boundary(offset: u64, cluster_bits: u32) -> Result<()> {
|
fn offset_is_cluster_boundary(offset: u64, cluster_bits: u32) -> Result<()> {
|
||||||
if offset & ((0x01 << cluster_bits) - 1) != 0 {
|
if offset & ((0x01 << cluster_bits) - 1) != 0 {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
|
use crate::BlockBackend;
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@ -343,6 +344,12 @@ impl SeekHole for RawFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockBackend for RawFile {
|
||||||
|
fn size(&self) -> std::result::Result<u64, crate::Error> {
|
||||||
|
Ok(self.metadata().map_err(crate::Error::RawFileError)?.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clone for RawFile {
|
impl Clone for RawFile {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
RawFile {
|
RawFile {
|
||||||
|
@ -8,6 +8,7 @@ use crate::vhdx::{
|
|||||||
vhdx_io::VhdxIoError,
|
vhdx_io::VhdxIoError,
|
||||||
vhdx_metadata::{DiskSpec, VhdxMetadataError},
|
vhdx_metadata::{DiskSpec, VhdxMetadataError},
|
||||||
};
|
};
|
||||||
|
use crate::BlockBackend;
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use remain::sorted;
|
use remain::sorted;
|
||||||
use std::collections::btree_map::BTreeMap;
|
use std::collections::btree_map::BTreeMap;
|
||||||
@ -208,6 +209,12 @@ impl Seek for Vhdx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockBackend for Vhdx {
|
||||||
|
fn size(&self) -> std::result::Result<u64, crate::Error> {
|
||||||
|
Ok(self.virtual_disk_size())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clone for Vhdx {
|
impl Clone for Vhdx {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Vhdx {
|
Vhdx {
|
||||||
|
Loading…
Reference in New Issue
Block a user