use thiserror crate

This commit is contained in:
Bruce Leidl 2023-01-31 13:48:20 -05:00
parent 41d6d10373
commit 8ef4220adf
13 changed files with 211 additions and 297 deletions

View File

@ -7,3 +7,4 @@ edition = "2018"
[dependencies]
libc = "*"
lazy_static="1.4.0"
thiserror = "1.0"

View File

@ -1,79 +1,73 @@
use std::{result, io, fmt};
use std::{result, io};
use crate::netlink;
use thiserror::Error;
#[derive(Debug,Error)]
pub enum Error {
#[error("not running as pid 1")]
Pid1,
#[error("failed to load kernel command line from /proc/cmdline: {0}")]
KernelCmdLine(io::Error),
#[error("Cannot mount rootfs because no phinit.root is set")]
NoRootVar,
#[error("Cannot mount rootfs because no phinit.rootfs is set")]
NoRootFsVar,
#[error("Failed to mount rootfs {0}: {1}")]
RootFsMount(String, io::Error),
#[error("unable to mount procfs: {0}")]
MountProcFS(io::Error),
#[error("failed to mount tmpfs at {0}: {1}")]
MountTmpFS(String, io::Error),
#[error("failed to mount sysfs at /sys: {0}")]
MountSysFS(io::Error),
#[error("failed to mount cgroup at /sys/fs/cgroup: {0}")]
MountCGroup(io::Error),
#[error("failed to mount devtmpfs at /dev: {0}")]
MountDevTmpFS(io::Error),
#[error("failed to mount /dev/pts: {0}")]
MountDevPts(io::Error),
#[error("failed to mount overlayfs: {0}")]
MountOverlay(io::Error),
#[error("failed to move mount from {0} to {1}: {2}")]
MoveMount(String, String, io::Error),
#[error("failed to mount 9p volume {0} at {1}: {2}")]
Mount9P(String, String, io::Error),
#[error("failed to unmount {0}: {1}")]
Umount(String, io::Error),
#[error("failed to mkdir {0}: {1}")]
MkDir(String, io::Error),
#[error("sethostname() failed: {0}")]
SetHostname(io::Error),
#[error("call to setsid() failed: {0}")]
SetSid(io::Error),
#[error("failed to set controlling terminal: {0}")]
SetControllingTty(io::Error),
#[error("failed to pivot_root({0}, {1}): {2}")]
PivotRoot(String, String, io::Error),
#[error("failed to waitpid(): {0}")]
WaitPid(io::Error),
#[error("failed to write /etc/hosts: {0}")]
WriteEtcHosts(io::Error),
#[error("error launching shell: {0}")]
RunShell(io::Error),
#[error("failed to create CString")]
CStringConv,
#[error("failed to chmod: {0}")]
ChmodFailed(io::Error),
#[error("failed to chown: {0}")]
ChownFailed(io::Error),
#[error("unable to execute {0}: {1}")]
LaunchFailed(String, io::Error),
#[error("could not reboot system: {0}")]
RebootFailed(io::Error),
#[error("failed to open log file: {0}")]
OpenLogFailed(io::Error),
#[error("error creating .Xauthority file: {0}")]
XAuthFail(io::Error),
#[error("error writing bashrc file: {0}")]
WriteBashrc(io::Error),
#[error("error configuring network: {0}")]
NetworkConfigure(netlink::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Error::*;
match self {
Pid1 => write!(f, "not running as pid 1"),
KernelCmdLine(err) => write!(f, "failed to load kernel command line from /proc/cmdline: {}", err),
NoRootVar => write!(f, "Cannot mount rootfs because no phinit.root is set"),
NoRootFsVar => write!(f, "Cannot mount rootfs because no phinit.rootfs is set"),
RootFsMount(rootfs, err) => write!(f, "Failed to mount rootfs {}: {}", rootfs, err),
MountProcFS(err) => write!(f, "unable to mount procfs: {}", err),
MountTmpFS(target,err) => write!(f, "failed to mount tmpfs at {}: {}", target, err),
MountSysFS(err) => write!(f, "failed to mount sysfs at /sys: {}", err),
MountCGroup(err) => write!(f, "failed to mount cgroup at /sys/fs/cgroup: {}", err),
MountDevTmpFS(err) => write!(f, "failed to mount devtmpfs at /dev: {}", err),
MountDevPts(err) => write!(f, "failed to mount /dev/pts: {}", err),
MountOverlay(err) => write!(f, "failed to mount overlayfs: {}", err),
MoveMount(from, to, err) => write!(f, "failed to move mount from {} to {}: {}", from, to, err),
Mount9P(tag,target, err) => write!(f, "failed to mount 9p volume {} at {}: {}", tag, target, err),
Umount(target, err) => write!(f, "failed to unmount {}: {}", target, err),
MkDir(target, err) => write!(f, "failed to mkdir {}: {}", target, err),
SetHostname(err) => write!(f, "sethostname() failed: {}", err),
SetSid(err) => write!(f, "call to setsid() failed: {}", err),
SetControllingTty(err) => write!(f, "failed to set controlling terminal: {}", err),
PivotRoot(newroot, putroot, err) => write!(f, "failed to pivot_root({}, {}): {}", newroot, putroot, err),
WaitPid(err) => write!(f, "failed to waitpid(): {}", err),
WriteEtcHosts(err) => write!(f, "failed to write /etc/hosts: {}", err),
RunShell(err) => write!(f, "error launching shell: {}", err),
CStringConv => write!(f, "failed to create CString"),
ChmodFailed(err) => write!(f, "failed to chmod: {}", err),
ChownFailed(err) => write!(f, "failed to chown: {}", err),
LaunchFailed(exec, err) => write!(f, "unable to execute {}: {}", exec, err),
RebootFailed(err) => write!(f, "could not reboot system: {}", err),
OpenLogFailed(err) => write!(f, "failed to open log file: {}", err),
XAuthFail(err) => write!(f, "error creating .Xauthority file: {}", err),
WriteBashrc(err) => write!(f, "error writing bashrc file: {}", err),
NetworkConfigure(err) => write!(f, "error configuring network: {}", err),
}
}
}
pub type Result<T> = result::Result<T, Error>;

View File

@ -2,10 +2,12 @@ use std::cell::Cell;
use std::convert::TryInto;
use std::ffi::CString;
use std::net::Ipv4Addr;
use std::{mem, result, fmt, io};
use std::{mem, result, io};
use std::os::unix::io::RawFd;
use std::path::Path;
use thiserror::Error;
use libc::{
PF_NETLINK, SOCK_RAW, SOCK_CLOEXEC, SOCK_NONBLOCK
};
@ -54,34 +56,26 @@ pub const IFF_UP: u32 = libc::IFF_UP as u32;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
#[derive(Debug,Error)]
pub enum Error {
#[error("failed to create netlink socket: {0}")]
Socket(io::Error),
#[error("failed calling bind() on netlink socket: {0}")]
SocketBind(io::Error),
#[error("failed calling sendto() on netlink socket: {0}")]
SocketSend(io::Error),
#[error("failed calling recv() on netlink socket: {0}")]
SocketRecv(io::Error),
#[error("failed to convert interface name to index: {0}")]
NameToIndex(io::Error),
#[error("error response to netlink request: {0}")]
ErrorResponse(io::Error),
#[error("could not parse response message from netlink")]
UnexpectedResponse,
#[error("failed to transmit entire netlink message")]
ShortSend,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
Socket(e) => write!(f, "failed to create netlink socket: {}", e),
SocketBind(e) => write!(f, "failed calling bind() on netlink socket: {}", e),
SocketSend(e) => write!(f, "failed calling sendto() on netlink socket: {}", e),
SocketRecv(e) => write!(f, "failed calling recv() on netlink socket: {}", e),
NameToIndex(e) => write!(f, "failed to convert interface name to index: {}", e),
ErrorResponse(e) => write!(f, "error response to netlink request: {}", e),
UnexpectedResponse => write!(f, "could not parse response message from netlink"),
ShortSend => write!(f, "failed to transmit entire netlink message"),
}
}
}
pub struct NetlinkSocket {
sock: RawFd,
seq: Cell<u32>,

View File

@ -1,12 +1,14 @@
use std::io::Write;
use std::sync::{RwLock, Arc};
use std::{result, io, fmt, thread};
use std::{result, io, thread};
use crate::{disk, virtio};
use crate::virtio::{VirtioBus, VirtioDeviceOps, VirtQueue, DeviceConfigArea, Chain};
use crate::memory::MemoryManager;
use crate::disk::DiskImage;
use thiserror::Error;
const VIRTIO_BLK_F_RO: u64 = 1 << 5;
const VIRTIO_BLK_F_BLK_SIZE: u64 = 1 << 6;
const VIRTIO_BLK_F_FLUSH: u64 = 1 << 9;
@ -26,34 +28,22 @@ const SECTOR_SIZE: usize = 1 << SECTOR_SHIFT;
const QUEUE_SIZE: usize = 256;
#[derive(Debug,Error)]
enum Error {
IoChainError(io::Error),
#[error("i/o error on virtio chain operation: {0}")]
IoChainError(#[from] io::Error),
#[error("error reading disk image: {0}")]
DiskRead(disk::Error),
#[error("error writing disk image: {0}")]
DiskWrite(disk::Error),
#[error("error flushing disk image: {0}")]
DiskFlush(disk::Error),
#[error("error waiting on virtqueue: {0}")]
VirtQueueWait(virtio::Error),
#[error("virtqueue read descriptor size ({0}) is invalid. Not a multiple of sector size")]
InvalidReadDescriptor(usize),
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Self {
Error::IoChainError(e)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
IoChainError(e) => write!(f, "i/o error on virtio chain operation: {}", e),
DiskRead(e) => write!(f, "error reading disk image: {}", e),
DiskWrite(e) => write!(f, "error writing disk image: {}", e),
DiskFlush(e) => write!(f, "error flushing disk image: {}", e),
VirtQueueWait(e) =>write!(f, "error waiting on virtqueue: {}", e),
InvalidReadDescriptor(sz) => write!(f, "virtqueue read descriptor size ({}) is invalid. Not a multiple of sector size", sz),
}
}
}
type Result<T> = result::Result<T, Error>;
pub struct VirtioBlock<D: DiskImage+'static> {

View File

@ -2,40 +2,35 @@ use crate::virtio::{VirtioDeviceOps, VirtQueue, VirtioBus, Chain};
use crate::memory::MemoryManager;
use crate::{system, virtio};
use std::sync::{RwLock, Arc};
use std::{fmt, result, thread, io};
use std::{result, thread, io};
use crate::system::{EPoll,Event};
use std::io::{Read, Write};
use std::os::unix::io::AsRawFd;
use crate::system::Tap;
use thiserror::Error;
const VIRTIO_ID_NET: u16 = 1;
const MAC_ADDR_LEN: usize = 6;
#[derive(Debug)]
#[derive(Debug,Error)]
pub enum Error {
#[error("Error writing to virtqueue chain: {0}")]
ChainWrite(io::Error),
#[error("Error reading from virtqueue chain: {0}")]
ChainRead(io::Error),
ChainIoEvent(system::Error),
#[error("Error reading from virtqueue ioevent: {0}")]
ChainIoEvent(io::Error),
#[error("Failed to set up Poll: {0}")]
SetupPoll(system::Error),
#[error("Error reading from tap device: {0}")]
TapRead(io::Error),
#[error("Error writing to tap device: {0}")]
TapWrite(io::Error),
#[error("Poll wait returned error: {0}")]
PollWait(system::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
ChainWrite(err) => write!(f, "Error writing to virtqueue chain: {}", err),
ChainRead(err) => write!(f, "Error reading from virtqueue chain: {}", err),
ChainIoEvent(err) => write!(f, "Error reading from virtqueue ioevent: {}", err),
SetupPoll(e) => write!(f, "Failed to set up Poll: {}", e),
TapRead(e) => write!(f, "Error reading from tap device: {}", e),
TapWrite(e) => write!(f, "Error writing to tap device: {}", e),
PollWait(e) => write!(f, "Poll wait returned error: {}", e),
}
}
}
type Result<T> = result::Result<T, Error>;

View File

@ -1,5 +1,7 @@
use std::os::unix::io::RawFd;
use std::{result, io, fmt};
use std::{result, io};
use thiserror::Error;
use crate::system;
use crate::memory::Error as MemError;
@ -80,56 +82,42 @@ pub trait VfdObject {
}
#[derive(Debug)]
#[derive(Debug,Error)]
pub enum Error {
IoEventError(system::Error),
EventFdCreate(system::Error),
ChainIoError(io::Error),
#[error("error reading from ioevent fd: {0}")]
IoEventError(io::Error),
#[error("error creating eventfd: {0}")]
EventFdCreate(io::Error),
#[error("i/o error on virtio chain operation: {0}")]
ChainIoError(#[from] io::Error),
#[error("unexpected virtio wayland command: {0}")]
UnexpectedCommand(u32),
#[error("failed to allocate shared memory: {0}")]
ShmAllocFailed(system::Error),
#[error("failed to register memory with hypervisor: {0}")]
RegisterMemoryFailed(MemError),
#[error("failed to create pipes: {0}")]
CreatePipesFailed(system::Error),
#[error("error reading from socket: {0}")]
SocketReceive(system::ErrnoError),
#[error("error connecting to socket: {0}")]
SocketConnect(io::Error),
#[error("error reading from pipe: {0}")]
PipeReceive(io::Error),
#[error("error writing to vfd: {0}")]
SendVfd(io::Error),
#[error("attempt to send to incorrect vfd type")]
InvalidSendVfd,
#[error("message has too many vfd ids: {0}")]
TooManySendVfds(usize),
#[error("failed creating poll context: {0}")]
FailedPollContextCreate(system::Error),
#[error("failed adding fd to poll context: {0}")]
FailedPollAdd(system::Error),
#[error("error calling dma sync: {0}")]
DmaSync(system::ErrnoError),
#[error("failed creating DMA buf: {0}")]
DmaBuf(MemError),
#[error("failed creating DMA buf: {0}")]
DmaBufSize(system::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
IoEventError(e) => write!(f, "error reading from ioevent fd: {}", e),
EventFdCreate(e) => write!(f, "error creating eventfd: {}", e),
ChainIoError(e) => write!(f, "i/o error on virtio chain operation: {}", e),
UnexpectedCommand(cmd) => write!(f, "unexpected virtio wayland command: {}", cmd),
ShmAllocFailed(e) => write!(f, "failed to allocate shared memory: {}", e),
RegisterMemoryFailed(e) => write!(f, "failed to register memory with hypervisor: {}", e),
CreatePipesFailed(e) => write!(f, "failed to create pipes: {}", e),
SocketReceive(e) => write!(f, "error reading from socket: {}", e),
SocketConnect(e) => write!(f, "error connecting to socket: {}", e),
PipeReceive(e) => write!(f, "error reading from pipe: {}", e),
SendVfd(e) => write!(f, "error writing to vfd: {}", e),
InvalidSendVfd => write!(f, "attempt to send to incorrect vfd type"),
TooManySendVfds(n) => write!(f, "message has too many vfd ids: {}", n),
FailedPollContextCreate(e) => write!(f, "failed creating poll context: {}", e),
FailedPollAdd(e) => write!(f, "failed adding fd to poll context: {}", e),
DmaSync(e) => write!(f, "error calling dma sync: {}", e),
DmaBuf(e) => write!(f, "failed creating DMA buf: {}", e),
DmaBufSize(e) => write!(f, "failed getting DMA buf size: {}", e),
}
}
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Self {
Error::ChainIoError(e)
}
}

View File

@ -1,4 +1,4 @@
use std::{io, error, fmt, result, cmp};
use std::{io, result, cmp};
use std::fs::File;
use std::os::linux::fs::MetadataExt;
use std::io::{SeekFrom, Seek};
@ -12,6 +12,7 @@ mod memory;
pub use raw::RawDiskImage;
pub use realmfs::RealmFSImage;
use std::path::PathBuf;
use thiserror::Error;
const SECTOR_SIZE: usize = 512;
@ -59,36 +60,26 @@ fn generate_disk_image_id(disk_file: &File) -> Vec<u8> {
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
#[derive(Debug,Error)]
pub enum Error {
#[error("attempted write to read-only device")]
ReadOnly,
#[error("disk image {0} does not exist")]
ImageDoesntExit(PathBuf),
#[error("failed to open disk image {0:?}: {1}")]
DiskOpen(PathBuf,io::Error),
#[error("failed to open disk image {0} because the file is too short")]
DiskOpenTooShort(PathBuf),
#[error("error reading from disk image: {0}")]
DiskRead(io::Error),
#[error("error writing to disk image: {0}")]
DiskWrite(io::Error),
#[error("error seeking to offset on disk image: {0}")]
DiskSeek(io::Error),
#[error("attempt to access invalid sector offset {0}")]
BadSectorOffset(u64),
#[error("failed to create memory overlay: {0}")]
MemoryOverlayCreate(system::Error),
#[error("disk not open")]
NotOpen,
}
impl error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Error::*;
match self {
ReadOnly => write!(f, "attempted write to read-only device"),
ImageDoesntExit(path) => write!(f, "disk image {} does not exist", path.display()),
DiskOpen(path, err) => write!(f, "failed to open disk image {}: {}", path.display(), err),
DiskOpenTooShort(path) => write!(f, "failed to open disk image {} because file is too short", path.display()),
DiskRead(err) => write!(f, "error reading from disk image: {}", err),
DiskWrite(err) => write!(f, "error writing to disk image: {}", err),
DiskSeek(err) => write!(f, "error seeking to offset on disk image: {}", err),
BadSectorOffset(sector) => write!(f, "attempt to access invalid sector offset {}", sector),
MemoryOverlayCreate(err) => write!(f, "failed to create memory overlay: {}", err),
NotOpen => write!(f, "disk not open"),
}
}
}

View File

@ -13,41 +13,35 @@ pub use manager::MemoryManager;
pub use drm::{DrmDescriptor,DrmPlaneDescriptor};
use std::{result, fmt, io};
use crate::{system, kvm};
use std::{result, io};
use crate::system;
#[derive(Debug)]
use thiserror::Error;
#[derive(Debug,Error)]
pub enum Error {
#[error("failed to allocate memory for device")]
DeviceMemoryAllocFailed,
#[error("failed to create memory mapping for device memory: {0}")]
MappingFailed(system::Error),
RegisterMemoryFailed(kvm::Error),
UnregisterMemoryFailed(kvm::Error),
#[error("failed to register memory for device memory: {0}")]
RegisterMemoryFailed(kvm_ioctls::Error),
#[error("failed to unregister memory for device memory: {0}")]
UnregisterMemoryFailed(kvm_ioctls::Error),
#[error("failed to open device with libgbm: {0}")]
GbmCreateDevice(system::Error),
#[error("failed to allocate buffer with libgbm: {0}")]
GbmCreateBuffer(system::Error),
#[error("error opening render node: {0}")]
OpenRenderNode(io::Error),
#[error("exporting prime handle to fd failed: {0}")]
PrimeHandleToFD(system::ErrnoError),
#[error("failed to create buffer: {0}")]
CreateBuffer(io::Error),
#[error("no DRM allocator is available")]
NoDrmAllocator,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
DeviceMemoryAllocFailed => write!(f, "failed to allocate memory for device"),
MappingFailed(e) => write!(f, "failed to create memory mapping for device memory: {}", e),
RegisterMemoryFailed(e) => write!(f, "failed to register memory for device memory: {}", e),
UnregisterMemoryFailed(e) => write!(f, "failed to unregister memory for device memory: {}", e),
GbmCreateDevice(e) => write!(f, "failed to open device with libgbm: {}", e),
GbmCreateBuffer(e) => write!(f, "failed to allocate buffer with libgbm: {}", e),
PrimeHandleToFD(err) => write!(f, "exporting prime handle to fd failed: {}", err),
OpenRenderNode(err) => write!(f, "error opening render node: {}", err),
CreateBuffer(err) => write!(f, "failed to create buffer: {}", err),
NoDrmAllocator => write!(f, "no DRM allocator is available"),
}
}
}
pub type Result<T> = result::Result<T, Error>;

View File

@ -1,7 +1,6 @@
#[macro_use]pub mod ioctl;
mod epoll;
mod errno;
mod eventfd;
mod socket;
mod filedesc;
mod memfd;
@ -9,26 +8,34 @@ mod tap;
pub mod netlink;
pub use filedesc::{FileDesc, FileFlags};
pub use eventfd::EventFd;
pub use memfd::MemoryFd;
pub use epoll::{EPoll,Event};
pub use socket::ScmSocket;
pub use netlink::NetlinkSocket;
pub use tap::Tap;
use std::{fmt, result, io};
use std::{result, io};
pub use errno::Error as ErrnoError;
use thiserror::Error;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
#[derive(Debug,Error)]
pub enum Error {
#[error("{0}")]
Errno(errno::Error),
#[error("failed to open /dev/kvm: {0}")]
OpenKvmFailed(errno::Error),
#[error("attempt to access invalid offset into mapping")]
InvalidOffset,
#[error("attempt to access invalid address: {0:16x}")]
InvalidAddress(u64),
#[error("failed to call {0} ioctl: {1}")]
IoctlError(&'static str, errno::Error),
#[error("failed writing to eventfd")]
EventFdWrite,
#[error("failed reading from eventfd")]
EventFdRead,
}
@ -62,22 +69,6 @@ impl Error {
}
}
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
Errno(err) => err.fmt(f),
InvalidOffset => write!(f, "attempt to access invalid offset into mapping"),
InvalidAddress(addr) => write!(f, "attempt to access invalid address: {0:16x}", addr),
OpenKvmFailed(err) => write!(f, "failed to open /dev/kvm: {}", err),
IoctlError(name, err) => write!(f, "failed to call {} ioctl: {}", name, err),
EventFdWrite => write!(f, "failed writing to eventfd"),
EventFdRead => write!(f, "failed reading from eventfd"),
}
}
}
impl From<errno::Error> for Error {
fn from(err: errno::Error) -> Error {
Error::Errno(err)

View File

@ -2,7 +2,7 @@ use std::cell::Cell;
use std::convert::TryInto;
use std::ffi::CString;
use std::net::Ipv4Addr;
use std::{mem, result, fmt, io};
use std::{mem, result, io};
use std::os::unix::io::RawFd;
use std::path::Path;
@ -10,6 +10,8 @@ use libc::{
PF_NETLINK, SOCK_RAW, SOCK_CLOEXEC, SOCK_NONBLOCK
};
use thiserror::Error;
const NETLINK_ROUTE: i32 = 0;
const IFLA_IFNAME: u16 = 3;
@ -54,34 +56,26 @@ pub const IFF_UP: u32 = libc::IFF_UP as u32;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
#[derive(Debug,Error)]
pub enum Error {
#[error("failed to create netlink socket: {0}")]
Socket(io::Error),
#[error("failed calling bind() on netlink socket: {0}")]
SocketBind(io::Error),
#[error("failed calling sendto() on netlink socket: {0}")]
SocketSend(io::Error),
#[error("failed calling recv() on netlink socket: {0}")]
SocketRecv(io::Error),
#[error("failed to convert interface name to index: {0}")]
NameToIndex(io::Error),
#[error("error response to netlink request: {0}")]
ErrorResponse(io::Error),
#[error("could not parse response message from netlink")]
UnexpectedResponse,
#[error("failed to transmit entire netlink message")]
ShortSend,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
Socket(e) => write!(f, "failed to create netlink socket: {}", e),
SocketBind(e) => write!(f, "failed calling bind() on netlink socket: {}", e),
SocketSend(e) => write!(f, "failed calling sendto() on netlink socket: {}", e),
SocketRecv(e) => write!(f, "failed calling recv() on netlink socket: {}", e),
NameToIndex(e) => write!(f, "failed to convert interface name to index: {}", e),
ErrorResponse(e) => write!(f, "error response to netlink request: {}", e),
UnexpectedResponse => write!(f, "could not parse response message from netlink"),
ShortSend => write!(f, "failed to transmit entire netlink message"),
}
}
}
pub struct NetlinkSocket {
sock: RawFd,
seq: Cell<u32>,

View File

@ -16,40 +16,32 @@ pub use self::chain::Chain;
pub use self::device_config::DeviceConfigArea;
use byteorder::{ByteOrder,LittleEndian};
use std::{result, fmt};
use crate::{system, kvm};
use std::result;
use thiserror::Error;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
#[derive(Debug,Error)]
pub enum Error {
CreateEventFd(system::Error),
CreateIoEventFd(kvm::Error),
ReadIoEventFd(system::Error),
IrqFd(kvm::Error),
#[error("failed to create EventFd for VirtQueue: {0}")]
CreateEventFd(std::io::Error),
#[error("failed to create IoEventFd for VirtQueue: {0}")]
CreateIoEventFd(kvm_ioctls::Error),
#[error("failed to read from IoEventFd: {0}")]
ReadIoEventFd(std::io::Error),
#[error("VirtQueue: {0}")]
IrqFd(kvm_ioctls::Error),
#[error("vring not enabled")]
VringNotEnabled,
#[error("vring descriptor table range is invalid 0x{0:x}")]
VringRangeInvalid(u64),
#[error("vring avail ring range range is invalid 0x{0:x}")]
VringAvailInvalid(u64),
#[error("vring used ring range is invalid 0x{0:x}")]
VringUsedInvalid(u64),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
CreateIoEventFd(e) => write!(f, "failed to create IoEventFd for VirtQueue: {}", e),
CreateEventFd(e) => write!(f, "failed to create EventFd for VirtQueue: {}", e),
ReadIoEventFd(e) => write!(f, "failed to read from IoEventFd: {}", e),
IrqFd(e) => write!(f, "VirtQueue: {}", e),
VringNotEnabled => write!(f, "vring is not enabled"),
VringRangeInvalid(addr) => write!(f, "vring descriptor table range is invalid 0x{:x}", addr),
VringAvailInvalid(addr) => write!(f, "vring avail ring range range is invalid 0x{:x}", addr),
VringUsedInvalid(addr) => write!(f, "vring used ring range is invalid 0x{:x}", addr),
}
}
}
pub fn read_config_buffer(config: &[u8], offset: usize, size: usize) -> u64 {
if offset + size > config.len() {
return 0;

View File

@ -1,31 +1,29 @@
use crate::{kvm, system, memory};
use crate::{system, memory};
use crate::system::ErrnoError;
use std::{fmt, result};
use std::result;
use kvm_ioctls::Cap;
use thiserror::Error;
#[derive(Debug)]
#[derive(Debug,Error)]
pub enum Error {
#[error("failed to create memory manager: {0}")]
MemoryManagerCreate(memory::Error),
MemoryRegister(kvm::Error),
#[error("failed to register memory region: {0}")]
MemoryRegister(kvm_ioctls::Error),
#[error("failed to create memory region: {0}")]
MemoryRegionCreate(system::Error),
#[error("error loading kernel: {0}")]
LoadKernel(system::Error),
KvmError(kvm::Error),
#[error("{0}")]
KvmError(kvm_ioctls::Error),
#[error("kernel does not support a required kvm extension: {0:?}")]
KvmMissingExtension(Cap),
#[error("{0}")]
SystemError(system::Error),
#[error("failed to call {0} ioctl: {1}")]
IoctlError(&'static str, ErrnoError),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
MemoryManagerCreate(err) => write!(f, "failed to create memory manager: {}", err),
MemoryRegister(err) => write!(f, "failed to register memory region: {}", err),
MemoryRegionCreate(err) => write!(f, "failed to create memory region: {}", err),
LoadKernel(err) => write!(f, "error loading kernel: {}", err),
KvmError(e) => e.fmt(f),
SystemError(e) => e.fmt(f),
IoctlError(name, err) => write!(f, "failed to call {} ioctl: {}", name, err),
}
}
#[error("error setting up vm: {0}")]
SetupError(kvm_ioctls::Error),
}
pub type Result<T> = result::Result<T, Error>;

View File

@ -1,48 +1,40 @@
use std::{result, io};
use std::fmt;
use crate::{system, kvm, virtio};
use kvm_ioctls::Cap;
use crate::{system, virtio};
use crate::system::netlink;
use crate::vm::arch;
use thiserror::Error;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
#[derive(Error,Debug)]
pub enum Error {
CreateVmFailed(kvm::Error),
#[error("failed to open kvm instance: {0}")]
KvmOpenError(kvm_ioctls::Error),
#[error("failed to create VM file descriptor: {0}")]
VmFdOpenError(kvm_ioctls::Error),
#[error("error on KVM operation: {0}")]
KvmError(kvm_ioctls::Error),
#[error("unexpected KVM version")]
BadVersion,
#[error("kernel does not support a required kvm extension: {0:?}")]
MissingRequiredExtension(Cap),
#[error("error configuring VM: {0}")]
VmSetup(kvm_ioctls::Error),
#[error("memory mapping failed: {0}")]
MappingFailed(system::Error),
#[error("error reading/restoring terminal state: {0}")]
TerminalTermios(io::Error),
IoError(io::Error),
#[error("i/o error: {0}")]
IoError(#[from] io::Error),
#[error("{0}")]
ArchError(arch::Error),
NetworkSetup(netlink::Error),
#[error("error setting up network: {0}")]
NetworkSetup(#[from] netlink::Error),
#[error("setting up boot fs failed: {0}")]
SetupBootFs(io::Error),
#[error("setting up virtio devices failed: {0}")]
SetupVirtio(virtio::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::TerminalTermios(e) => write!(f, "error reading/restoring terminal state: {}", e),
Error::IoError(e) => write!(f, "i/o error: {}", e),
Error::NetworkSetup(e) => write!(f, "error setting up network: {}", e),
Error::CreateVmFailed(e) => write!(f, "call to create vm failed: {}", e),
Error::MappingFailed(e) => write!(f, "memory mapping failed: {}", e),
Error::SetupBootFs(e) => write!(f, "setting up boot fs failed: {}", e),
Error::SetupVirtio(e) => write!(f, "setting up virtio devices failed: {}", e),
Error::ArchError(e) => e.fmt(f),
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error::IoError(err).into()
}
}
impl From<netlink::Error> for Error {
fn from(err: netlink::Error) -> Error {
Error::NetworkSetup(err).into()
}
#[error("failed to create Vcpu: {0}")]
CreateVcpu(kvm_ioctls::Error),
}