diff --git a/ph-init/Cargo.toml b/ph-init/Cargo.toml index f5fee4f..bd15856 100644 --- a/ph-init/Cargo.toml +++ b/ph-init/Cargo.toml @@ -7,3 +7,4 @@ edition = "2018" [dependencies] libc = "*" lazy_static="1.4.0" +thiserror = "1.0" diff --git a/ph-init/src/error.rs b/ph-init/src/error.rs index e4d9c98..5dc6492 100644 --- a/ph-init/src/error.rs +++ b/ph-init/src/error.rs @@ -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 = result::Result; \ No newline at end of file diff --git a/ph-init/src/netlink.rs b/ph-init/src/netlink.rs index 1fd0cfb..037f75a 100644 --- a/ph-init/src/netlink.rs +++ b/ph-init/src/netlink.rs @@ -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 = result::Result; -#[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, diff --git a/src/devices/virtio_block.rs b/src/devices/virtio_block.rs index 41c5cd4..c37fe74 100644 --- a/src/devices/virtio_block.rs +++ b/src/devices/virtio_block.rs @@ -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 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 = result::Result; pub struct VirtioBlock { diff --git a/src/devices/virtio_net.rs b/src/devices/virtio_net.rs index 3500c73..9276e1d 100644 --- a/src/devices/virtio_net.rs +++ b/src/devices/virtio_net.rs @@ -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 = result::Result; diff --git a/src/devices/virtio_wl/mod.rs b/src/devices/virtio_wl/mod.rs index f738b6c..2e00d6d 100644 --- a/src/devices/virtio_wl/mod.rs +++ b/src/devices/virtio_wl/mod.rs @@ -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 for Error { - fn from(e: io::Error) -> Self { - Error::ChainIoError(e) - } -} diff --git a/src/disk/mod.rs b/src/disk/mod.rs index 2bb07c5..59dcc0a 100644 --- a/src/disk/mod.rs +++ b/src/disk/mod.rs @@ -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 { pub type Result = result::Result; -#[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"), - } - } } \ No newline at end of file diff --git a/src/memory/mod.rs b/src/memory/mod.rs index fcf77ff..a94fc43 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -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 = result::Result; diff --git a/src/system/mod.rs b/src/system/mod.rs index e7b9356..c53e81e 100644 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -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 = result::Result; -#[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 for Error { fn from(err: errno::Error) -> Error { Error::Errno(err) diff --git a/src/system/netlink.rs b/src/system/netlink.rs index 1fd0cfb..b823186 100644 --- a/src/system/netlink.rs +++ b/src/system/netlink.rs @@ -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 = result::Result; -#[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, diff --git a/src/virtio/mod.rs b/src/virtio/mod.rs index 54bb46b..24ba4ef 100644 --- a/src/virtio/mod.rs +++ b/src/virtio/mod.rs @@ -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 = result::Result; -#[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; diff --git a/src/vm/arch/error.rs b/src/vm/arch/error.rs index 2c46320..a25a658 100644 --- a/src/vm/arch/error.rs +++ b/src/vm/arch/error.rs @@ -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 = result::Result; diff --git a/src/vm/error.rs b/src/vm/error.rs index 0beca8c..1e94d55 100644 --- a/src/vm/error.rs +++ b/src/vm/error.rs @@ -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 = result::Result; -#[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 for Error { - fn from(err: io::Error) -> Error { - Error::IoError(err).into() - } - -} - -impl From for Error { - fn from(err: netlink::Error) -> Error { - Error::NetworkSetup(err).into() - } -} + #[error("failed to create Vcpu: {0}")] + CreateVcpu(kvm_ioctls::Error), +} \ No newline at end of file