mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-24 20:48:55 +00:00
disk: convert to ThisError and sort
BUG=b:197143586 TEST=cargo check --features=composite-disk Change-Id: Ibd06b85b959d28f6cc5948be30220fa268034dcb Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3105077 Reviewed-by: Chirantan Ekbote <chirantan@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
5225377caf
commit
e6ff5376e1
4 changed files with 71 additions and 132 deletions
|
@ -5,7 +5,6 @@
|
|||
// https://android.googlesource.com/platform/system/core/+/7b444f0/libsparse/sparse_format.h
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::{self, Display};
|
||||
use std::fs::File;
|
||||
use std::io::{self, ErrorKind, Read, Seek, SeekFrom};
|
||||
use std::mem;
|
||||
|
@ -17,29 +16,19 @@ use base::{
|
|||
};
|
||||
use data_model::{DataInit, Le16, Le32, VolatileSlice};
|
||||
use remain::sorted;
|
||||
use thiserror::Error;
|
||||
|
||||
#[sorted]
|
||||
#[derive(Debug)]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("invalid magic header for android sparse format")]
|
||||
InvalidMagicHeader,
|
||||
#[error("invalid specification: \"{0}\"")]
|
||||
InvalidSpecification(String),
|
||||
#[error("failed to read specification: \"{0}\"")]
|
||||
ReadSpecificationError(io::Error),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
#[remain::check]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::Error::*;
|
||||
|
||||
#[sorted]
|
||||
match self {
|
||||
InvalidMagicHeader => write!(f, "invalid magic header for android sparse format"),
|
||||
InvalidSpecification(s) => write!(f, "invalid specification: \"{}\"", s),
|
||||
ReadSpecificationError(e) => write!(f, "failed to read specification: \"{}\"", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
pub const SPARSE_HEADER_MAGIC: u32 = 0xed26ff3a;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
use std::cmp::{max, min};
|
||||
use std::collections::HashSet;
|
||||
use std::convert::TryInto;
|
||||
use std::fmt::{self, Display};
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write};
|
||||
use std::ops::Range;
|
||||
|
@ -20,6 +19,7 @@ use data_model::VolatileSlice;
|
|||
use protobuf::Message;
|
||||
use protos::cdisk_spec::{self, ComponentDisk, CompositeDisk, ReadWriteCapability};
|
||||
use remain::sorted;
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gpt::{
|
||||
|
@ -44,62 +44,42 @@ const LINUX_FILESYSTEM_GUID: Uuid = Uuid::from_u128(0x0FC63DAF_8483_4772_8E79_3D
|
|||
const EFI_SYSTEM_PARTITION_GUID: Uuid = Uuid::from_u128(0xC12A7328_F81F_11D2_BA4B_00A0C93EC93B);
|
||||
|
||||
#[sorted]
|
||||
#[derive(Debug)]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("failed to use underlying disk: \"{0}\"")]
|
||||
DiskError(Box<crate::Error>),
|
||||
#[error("duplicate GPT partition label \"{0}\"")]
|
||||
DuplicatePartitionLabel(String),
|
||||
#[error("failed to write GPT header: \"{0}\"")]
|
||||
GptError(gpt::Error),
|
||||
#[error("invalid magic header for composite disk format")]
|
||||
InvalidMagicHeader,
|
||||
#[error("invalid partition path {0:?}")]
|
||||
InvalidPath(PathBuf),
|
||||
#[error("failed to parse specification proto: \"{0}\"")]
|
||||
InvalidProto(protobuf::ProtobufError),
|
||||
#[error("invalid specification: \"{0}\"")]
|
||||
InvalidSpecification(String),
|
||||
#[error("no image files for partition {0:?}")]
|
||||
NoImageFiles(PartitionInfo),
|
||||
#[error("failed to open component file \"{1}\": \"{0}\"")]
|
||||
OpenFile(io::Error, String),
|
||||
#[error("failed to read specification: \"{0}\"")]
|
||||
ReadSpecificationError(io::Error),
|
||||
#[error("Read-write partition {0:?} size is not a multiple of {}.", 1 << PARTITION_SIZE_SHIFT)]
|
||||
UnalignedReadWrite(PartitionInfo),
|
||||
#[error("unknown version {0} in specification")]
|
||||
UnknownVersion(u64),
|
||||
#[error("unsupported component disk type \"{0:?}\"")]
|
||||
UnsupportedComponent(ImageType),
|
||||
#[error("failed to write composite disk header: \"{0}\"")]
|
||||
WriteHeader(io::Error),
|
||||
#[error("failed to write specification proto: \"{0}\"")]
|
||||
WriteProto(protobuf::ProtobufError),
|
||||
#[error("failed to write zero filler: \"{0}\"")]
|
||||
WriteZeroFiller(io::Error),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
#[remain::check]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::Error::*;
|
||||
|
||||
#[sorted]
|
||||
match self {
|
||||
DiskError(e) => write!(f, "failed to use underlying disk: \"{}\"", e),
|
||||
DuplicatePartitionLabel(label) => {
|
||||
write!(f, "duplicate GPT partition label \"{}\"", label)
|
||||
}
|
||||
GptError(e) => write!(f, "failed to write GPT header: \"{}\"", e),
|
||||
InvalidMagicHeader => write!(f, "invalid magic header for composite disk format"),
|
||||
InvalidPath(path) => write!(f, "invalid partition path {:?}", path),
|
||||
InvalidProto(e) => write!(f, "failed to parse specification proto: \"{}\"", e),
|
||||
InvalidSpecification(s) => write!(f, "invalid specification: \"{}\"", s),
|
||||
NoImageFiles(partition) => write!(f, "no image files for partition {:?}", partition),
|
||||
OpenFile(e, p) => write!(f, "failed to open component file \"{}\": \"{}\"", p, e),
|
||||
ReadSpecificationError(e) => write!(f, "failed to read specification: \"{}\"", e),
|
||||
UnalignedReadWrite(partition) => write!(
|
||||
f,
|
||||
"Read-write partition {:?} size is not a multiple of {}.",
|
||||
partition,
|
||||
1 << PARTITION_SIZE_SHIFT
|
||||
),
|
||||
UnknownVersion(v) => write!(f, "unknown version {} in specification", v),
|
||||
UnsupportedComponent(c) => write!(f, "unsupported component disk type \"{:?}\"", c),
|
||||
WriteHeader(e) => write!(f, "failed to write composite disk header: \"{}\"", e),
|
||||
WriteProto(e) => write!(f, "failed to write specification proto: \"{}\"", e),
|
||||
WriteZeroFiller(e) => write!(f, "failed to write zero filler: \"{}\"", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
impl From<gpt::Error> for Error {
|
||||
fn from(e: gpt::Error) -> Self {
|
||||
Self::GptError(e)
|
||||
|
|
|
@ -13,9 +13,9 @@ use base::{
|
|||
use data_model::{VolatileMemory, VolatileSlice};
|
||||
use libc::{EINVAL, ENOSPC, ENOTSUP};
|
||||
use remain::sorted;
|
||||
use thiserror::Error;
|
||||
|
||||
use std::cmp::{max, min};
|
||||
use std::fmt::{self, Display};
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||
use std::mem::size_of;
|
||||
|
@ -28,103 +28,86 @@ use crate::qcow::vec_cache::{CacheMap, Cacheable, VecCache};
|
|||
use crate::{create_disk_file, DiskFile, DiskGetLen};
|
||||
|
||||
#[sorted]
|
||||
#[derive(Debug)]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("backing file io error: {0}")]
|
||||
BackingFileIo(io::Error),
|
||||
#[error("backing file open error: {0}")]
|
||||
BackingFileOpen(Box<crate::Error>),
|
||||
#[error("backing file name is too long: {0} bytes over")]
|
||||
BackingFileTooLong(usize),
|
||||
#[error("compressed blocks not supported")]
|
||||
CompressedBlocksNotSupported,
|
||||
#[error("failed to evict cache: {0}")]
|
||||
EvictingCache(io::Error),
|
||||
#[error("file larger than max of {}: {0}", MAX_QCOW_FILE_SIZE)]
|
||||
FileTooBig(u64),
|
||||
#[error("failed to get file size: {0}")]
|
||||
GettingFileSize(io::Error),
|
||||
#[error("failed to get refcount: {0}")]
|
||||
GettingRefcount(refcount::Error),
|
||||
#[error("failed to parse filename: {0}")]
|
||||
InvalidBackingFileName(str::Utf8Error),
|
||||
#[error("invalid cluster index")]
|
||||
InvalidClusterIndex,
|
||||
#[error("invalid cluster size")]
|
||||
InvalidClusterSize,
|
||||
#[error("invalid index")]
|
||||
InvalidIndex,
|
||||
#[error("invalid L1 table offset")]
|
||||
InvalidL1TableOffset,
|
||||
#[error("invalid L1 table size {0}")]
|
||||
InvalidL1TableSize(u32),
|
||||
#[error("invalid magic")]
|
||||
InvalidMagic,
|
||||
#[error("invalid offset")]
|
||||
InvalidOffset(u64),
|
||||
#[error("invalid refcount table offset")]
|
||||
InvalidRefcountTableOffset,
|
||||
#[error("invalid refcount table size: {0}")]
|
||||
InvalidRefcountTableSize(u64),
|
||||
#[error("no free clusters")]
|
||||
NoFreeClusters,
|
||||
#[error("no refcount clusters")]
|
||||
NoRefcountClusters,
|
||||
#[error("not enough space for refcounts")]
|
||||
NotEnoughSpaceForRefcounts,
|
||||
#[error("failed to open file: {0}")]
|
||||
OpeningFile(io::Error),
|
||||
#[error("failed to open file: {0}")]
|
||||
ReadingHeader(io::Error),
|
||||
#[error("failed to read pointers: {0}")]
|
||||
ReadingPointers(io::Error),
|
||||
#[error("failed to read ref count block: {0}")]
|
||||
ReadingRefCountBlock(refcount::Error),
|
||||
#[error("failed to read ref counts: {0}")]
|
||||
ReadingRefCounts(io::Error),
|
||||
#[error("failed to rebuild ref counts: {0}")]
|
||||
RebuildingRefCounts(io::Error),
|
||||
#[error("refcount table offset past file end")]
|
||||
RefcountTableOffEnd,
|
||||
#[error("too many clusters specified for refcount table")]
|
||||
RefcountTableTooLarge,
|
||||
#[error("failed to seek file: {0}")]
|
||||
SeekingFile(io::Error),
|
||||
#[error("failed to set refcount refcount: {0}")]
|
||||
SettingRefcountRefcount(io::Error),
|
||||
#[error("size too small for number of clusters")]
|
||||
SizeTooSmallForNumberOfClusters,
|
||||
#[error("l1 entry table too large: {0}")]
|
||||
TooManyL1Entries(u64),
|
||||
#[error("ref count table too large: {0}")]
|
||||
TooManyRefcounts(u64),
|
||||
#[error("unsupported refcount order")]
|
||||
UnsupportedRefcountOrder,
|
||||
#[error("unsupported version: {0}")]
|
||||
UnsupportedVersion(u32),
|
||||
#[error("failed to write header: {0}")]
|
||||
WritingHeader(io::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),
|
||||
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),
|
||||
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),
|
||||
WritingHeader(e) => write!(f, "failed to write header: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maximum data size supported.
|
||||
const MAX_QCOW_FILE_SIZE: u64 = 0x01 << 44; // 16 TB.
|
||||
|
||||
|
|
|
@ -2,50 +2,37 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
use std::io;
|
||||
|
||||
use libc::EINVAL;
|
||||
use remain::sorted;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::qcow::qcow_raw_file::QcowRawFile;
|
||||
use crate::qcow::vec_cache::{CacheMap, Cacheable, VecCache};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[sorted]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
/// `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),
|
||||
/// `InvalidIndex` - Address requested isn't within the range of the disk.
|
||||
#[error("address requested is not within the range of the disk")]
|
||||
InvalidIndex,
|
||||
/// `NeedCluster` - Handle this error by reading the cluster and calling the function again.
|
||||
#[error("cluster with addr={0} needs to be read")]
|
||||
NeedCluster(u64),
|
||||
/// `NeedNewCluster` - Handle this error by allocating a cluster and calling the function again.
|
||||
#[error("new cluster needs to be allocated for refcounts")]
|
||||
NeedNewCluster,
|
||||
/// `ReadingRefCounts` - Error reading the file in to the refcount cache.
|
||||
#[error("failed to read the file into the refcount cache: {0}")]
|
||||
ReadingRefCounts(io::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={} needs to be read", addr),
|
||||
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.
|
||||
#[derive(Debug)]
|
||||
pub struct RefCount {
|
||||
|
|
Loading…
Reference in a new issue