block: qcow: Use thiserror for errors

Added thiserror for missing files in the qcow module.

Signed-off-by: SamrutGadde <samrut.gadde@gmail.com>
This commit is contained in:
SamrutGadde 2024-05-01 18:59:40 -05:00 committed by Bo Chen
parent 193c006669
commit f25315d151
2 changed files with 49 additions and 75 deletions

View File

@ -19,11 +19,11 @@ use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use libc::{EINVAL, ENOSPC, ENOTSUP}; use libc::{EINVAL, ENOSPC, ENOTSUP};
use remain::sorted; use remain::sorted;
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::fmt::{self, Display};
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{self, Read, Seek, SeekFrom, Write}; use std::io::{self, Read, Seek, SeekFrom, Write};
use std::mem::size_of; use std::mem::size_of;
use std::str; use std::str;
use thiserror::Error;
use vmm_sys_util::{ use vmm_sys_util::{
file_traits::FileSetLen, file_traits::FileSync, seek_hole::SeekHole, write_zeroes::PunchHole, file_traits::FileSetLen, file_traits::FileSync, seek_hole::SeekHole, write_zeroes::PunchHole,
write_zeroes::WriteZeroesAt, write_zeroes::WriteZeroesAt,
@ -32,105 +32,92 @@ use vmm_sys_util::{
pub use crate::qcow::raw_file::RawFile; pub use crate::qcow::raw_file::RawFile;
#[sorted] #[sorted]
#[derive(Debug)] #[derive(Debug, Error)]
pub enum Error { pub enum Error {
#[error("Backing file io error: {0}")]
BackingFileIo(io::Error), BackingFileIo(io::Error),
#[error("Backing file open error: {0}")]
BackingFileOpen(Box<crate::Error>), BackingFileOpen(Box<crate::Error>),
#[error("Backing file name is too long: {0} bytes over")]
BackingFileTooLong(usize), BackingFileTooLong(usize),
#[error("Compressed blocks not supported")]
CompressedBlocksNotSupported, CompressedBlocksNotSupported,
#[error("Failed to evict cache: {0}")]
EvictingCache(io::Error), EvictingCache(io::Error),
#[error("File larger than max of {}: {0}", MAX_QCOW_FILE_SIZE)]
FileTooBig(u64), FileTooBig(u64),
#[error("Failed to get file size: {0}")]
GettingFileSize(io::Error), GettingFileSize(io::Error),
#[error("Failed to get refcount: {0}")]
GettingRefcount(refcount::Error), GettingRefcount(refcount::Error),
#[error("Failed to parse filename: {0}")]
InvalidBackingFileName(str::Utf8Error), InvalidBackingFileName(str::Utf8Error),
#[error("Invalid cluster index")]
InvalidClusterIndex, InvalidClusterIndex,
#[error("Invalid cluster size")]
InvalidClusterSize, InvalidClusterSize,
#[error("Invalid index")]
InvalidIndex, InvalidIndex,
#[error("Invalid L1 table offset")]
InvalidL1TableOffset, InvalidL1TableOffset,
#[error("Invalid L1 table size: {0}")]
InvalidL1TableSize(u32), InvalidL1TableSize(u32),
#[error("Invalid magic")]
InvalidMagic, InvalidMagic,
#[error("Invalid offset: {0}")]
InvalidOffset(u64), InvalidOffset(u64),
#[error("Invalid refcount table offset")]
InvalidRefcountTableOffset, InvalidRefcountTableOffset,
#[error("Invalid refcount table size: {0}")]
InvalidRefcountTableSize(u64), InvalidRefcountTableSize(u64),
#[error("No free clusters")]
NoFreeClusters, NoFreeClusters,
#[error("No refcount clusters")]
NoRefcountClusters, NoRefcountClusters,
#[error("Not enough space for refcounts")]
NotEnoughSpaceForRefcounts, NotEnoughSpaceForRefcounts,
#[error("Failed to open file {0}")]
OpeningFile(io::Error), OpeningFile(io::Error),
#[error("Failed to read data: {0}")]
ReadingData(io::Error), ReadingData(io::Error),
#[error("Failed to read header: {0}")]
ReadingHeader(io::Error), ReadingHeader(io::Error),
#[error("Failed to read pointers: {0}")]
ReadingPointers(io::Error), ReadingPointers(io::Error),
#[error("Failed to read ref count block: {0}")]
ReadingRefCountBlock(refcount::Error), ReadingRefCountBlock(refcount::Error),
#[error("Failed to read ref counts: {0}")]
ReadingRefCounts(io::Error), ReadingRefCounts(io::Error),
#[error("Failed to rebuild ref counts: {0}")]
RebuildingRefCounts(io::Error), RebuildingRefCounts(io::Error),
#[error("Refcount table offset past file end")]
RefcountTableOffEnd, RefcountTableOffEnd,
#[error("Too many clusters specified for refcount")]
RefcountTableTooLarge, RefcountTableTooLarge,
#[error("Failed to seek file: {0}")]
SeekingFile(io::Error), SeekingFile(io::Error),
#[error("Failed to set file size: {0}")]
SettingFileSize(io::Error), SettingFileSize(io::Error),
#[error("Failed to set refcount refcount: {0}")]
SettingRefcountRefcount(io::Error), SettingRefcountRefcount(io::Error),
#[error("Size too small for number of clusters")]
SizeTooSmallForNumberOfClusters, SizeTooSmallForNumberOfClusters,
#[error("L1 entry table too large: {0}")]
TooManyL1Entries(u64), TooManyL1Entries(u64),
#[error("Ref count table too large: {0}")]
TooManyRefcounts(u64), TooManyRefcounts(u64),
#[error("Unsupported refcount order")]
UnsupportedRefcountOrder, UnsupportedRefcountOrder,
#[error("Unsupported version: {0}")]
UnsupportedVersion(u32), UnsupportedVersion(u32),
#[error("Failed to write data: {0}")]
WritingData(io::Error), WritingData(io::Error),
#[error("Failed to write header: {0}")]
WritingHeader(io::Error), WritingHeader(io::Error),
} }
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
impl Display for Error {
#[remain::check]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
#[sorted]
match self {
BackingFileIo(e) => write!(f, "backing file io error: {}", e),
BackingFileOpen(e) => write!(f, "backing file open error: {}", *e),
BackingFileTooLong(len) => {
write!(f, "backing file name is too long: {} bytes over", len)
}
CompressedBlocksNotSupported => write!(f, "compressed blocks not supported"),
EvictingCache(e) => write!(f, "failed to evict cache: {e}"),
FileTooBig(size) => write!(f, "file larger than max of {MAX_QCOW_FILE_SIZE}: {size}"),
GettingFileSize(e) => write!(f, "failed to get file size: {e}"),
GettingRefcount(e) => write!(f, "failed to get refcount: {e}"),
InvalidBackingFileName(e) => write!(f, "failed to parse filename: {}", e),
InvalidClusterIndex => write!(f, "invalid cluster index"),
InvalidClusterSize => write!(f, "invalid cluster size"),
InvalidIndex => write!(f, "invalid index"),
InvalidL1TableOffset => write!(f, "invalid L1 table offset"),
InvalidL1TableSize(size) => write!(f, "invalid L1 table size {size}"),
InvalidMagic => write!(f, "invalid magic"),
InvalidOffset(_) => write!(f, "invalid offset"),
InvalidRefcountTableOffset => write!(f, "invalid refcount table offset"),
InvalidRefcountTableSize(size) => write!(f, "invalid refcount table size: {size}"),
NoFreeClusters => write!(f, "no free clusters"),
NoRefcountClusters => write!(f, "no refcount clusters"),
NotEnoughSpaceForRefcounts => write!(f, "not enough space for refcounts"),
OpeningFile(e) => write!(f, "failed to open file: {e}"),
ReadingData(e) => write!(f, "failed to read data: {e}"),
ReadingHeader(e) => write!(f, "failed to read header: {e}"),
ReadingPointers(e) => write!(f, "failed to read pointers: {e}"),
ReadingRefCountBlock(e) => write!(f, "failed to read ref count block: {e}"),
ReadingRefCounts(e) => write!(f, "failed to read ref counts: {e}"),
RebuildingRefCounts(e) => write!(f, "failed to rebuild ref counts: {e}"),
RefcountTableOffEnd => write!(f, "refcount table offset past file end"),
RefcountTableTooLarge => write!(f, "too many clusters specified for refcount table"),
SeekingFile(e) => write!(f, "failed to seek file: {e}"),
SettingFileSize(e) => write!(f, "failed to set file size: {e}"),
SettingRefcountRefcount(e) => write!(f, "failed to set refcount refcount: {e}"),
SizeTooSmallForNumberOfClusters => write!(f, "size too small for number of clusters"),
TooManyL1Entries(count) => write!(f, "l1 entry table too large: {count}"),
TooManyRefcounts(count) => write!(f, "ref count table too large: {count}"),
UnsupportedRefcountOrder => write!(f, "unsupported refcount order"),
UnsupportedVersion(v) => write!(f, "unsupported version: {v}"),
WritingData(e) => write!(f, "failed to write data: {e}"),
WritingHeader(e) => write!(f, "failed to write header: {e}"),
}
}
}
pub enum ImageType { pub enum ImageType {
Raw, Raw,
Qcow2, Qcow2,

View File

@ -4,50 +4,37 @@
// //
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use std::fmt::{self, Display};
use std::io; use std::io;
use libc::EINVAL; use libc::EINVAL;
use thiserror::Error;
use crate::qcow::{ use crate::qcow::{
qcow_raw_file::QcowRawFile, qcow_raw_file::QcowRawFile,
vec_cache::{CacheMap, Cacheable, VecCache}, vec_cache::{CacheMap, Cacheable, VecCache},
}; };
#[derive(Debug)] #[derive(Debug, Error)]
pub enum Error { pub enum Error {
/// `EvictingCache` - Error writing a refblock from the cache to disk. /// `EvictingCache` - Error writing a refblock from the cache to disk.
#[error("Failed to write a refblock from the cache to disk: {0}")]
EvictingRefCounts(io::Error), EvictingRefCounts(io::Error),
/// `InvalidIndex` - Address requested isn't within the range of the disk. /// `InvalidIndex` - Address requested isn't within the range of the disk.
#[error("Address requested is not within the range of the disk")]
InvalidIndex, InvalidIndex,
/// `NeedCluster` - Handle this error by reading the cluster and calling the function again. /// `NeedCluster` - Handle this error by reading the cluster and calling the function again.
#[error("Cluster with addr={0} needs to be read")]
NeedCluster(u64), NeedCluster(u64),
/// `NeedNewCluster` - Handle this error by allocating a cluster and calling the function again. /// `NeedNewCluster` - Handle this error by allocating a cluster and calling the function again.
#[error("New cluster needs to be allocated for refcounts")]
NeedNewCluster, NeedNewCluster,
/// `ReadingRefCounts` - Error reading the file in to the refcount cache. /// `ReadingRefCounts` - Error reading the file in to the refcount cache.
#[error("Failed to read the file into the refcount cache: {0}")]
ReadingRefCounts(io::Error), ReadingRefCounts(io::Error),
} }
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
match self {
EvictingRefCounts(e) => {
write!(f, "failed to write a refblock from the cache to disk: {e}")
}
InvalidIndex => write!(f, "address requested is not within the range of the disk"),
NeedCluster(addr) => write!(f, "cluster with addr={addr} needs to be read"),
NeedNewCluster => write!(f, "new cluster needs to be allocated for refcounts"),
ReadingRefCounts(e) => {
write!(f, "failed to read the file into the refcount cache: {e}")
}
}
}
}
/// Represents the refcount entries for an open qcow file. /// Represents the refcount entries for an open qcow file.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct RefCount { pub struct RefCount {