Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: error handling #3

Merged
merged 2 commits into from Jul 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -10,4 +10,4 @@ description = "Rust bindings for Xen's xenctrl library"
license = "GPL-3.0-only"

[dependencies]
xenctrl-sys = { git = "https://github.com/Wenzel/xenctrl-sys" }
xenctrl-sys = { git = "https://github.com/Wenzel/xenctrl-sys.git" }
6 changes: 6 additions & 0 deletions rustfmt.toml
@@ -0,0 +1,6 @@
edition = "2018"
indent_style = "block"
format_strings = true
merge_imports = true
reorder_imports = true
wrap_comments = true
10 changes: 10 additions & 0 deletions src/consts.rs
@@ -0,0 +1,10 @@
pub const PAGE_SHIFT: u32 = xenctrl_sys::XC_PAGE_SHIFT;
pub const PAGE_SIZE: u32 = xenctrl_sys::XC_PAGE_SIZE;
pub const PAGE_MASK: i32 = xenctrl_sys::XC_PAGE_MASK;

pub const CORE_MAGIC: u32 = xenctrl_sys::XC_CORE_MAGIC;
pub const CORE_MAGIC_HVM: u32 = xenctrl_sys::XC_CORE_MAGIC_HVM;

pub const CPUPOOL_POOLID_ANY: u32 = xenctrl_sys::XC_CPUPOOL_POOLID_ANY;

pub const MAX_ERROR_MSG_LEN: u32 = xenctrl_sys::XC_MAX_ERROR_MSG_LEN;
38 changes: 38 additions & 0 deletions src/error.rs
@@ -0,0 +1,38 @@
use std::{
error, ffi,
fmt::{self, Debug, Display, Formatter},
};

use xenctrl_sys::{xc_error_code, xc_error_code_to_desc};

#[derive(Copy, Clone)]
pub struct Error(xc_error_code);

impl Error {
pub fn new(code: xc_error_code) -> Self {
Self(code)
}

pub fn desc(self) -> &'static str {
unsafe {
let desc = xc_error_code_to_desc(self.0 as _);
ffi::CStr::from_ptr(desc).to_str().unwrap()
}
}
}

impl Display for Error {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.desc())
}
}

impl Debug for Error {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.desc())
}
}

impl error::Error for Error {}
141 changes: 84 additions & 57 deletions src/lib.rs
@@ -1,90 +1,117 @@
pub mod error;
pub mod support;
pub mod consts;

#[macro_use]
mod macros;

extern crate xenctrl_sys;
use std::io::Error;
use std::ptr::{null_mut};
use std::os::raw::{c_void, c_ulong};
use std::{
mem,
ptr::{null_mut, NonNull},
};

use xenctrl_sys::{
xc_clear_last_error, xc_domain_maximum_gpfn, xc_domain_pause, xc_domain_unpause, xc_error_code,
xc_get_last_error, xc_interface, xc_interface_close, xc_interface_open, xc_monitor_disable,
xc_monitor_enable, xentoollog_logger,
};

pub const PAGE_SHIFT: u32 = xenctrl_sys::XC_PAGE_SHIFT;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to export these constants as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I forgot this. PR updated.

pub const PAGE_SIZE: u32 = xenctrl_sys::XC_PAGE_SIZE;
use error::Error;
use support::PageInfo;

type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub struct Xc {
handle: *mut xenctrl_sys::xc_interface,
evtchn_port: *mut u32,
pub struct XenControl {
handle: NonNull<xc_interface>,
evtchn_port: u32,
}

impl Xc {

pub fn new() -> Result<Self,Error> {
impl XenControl {
pub fn new(
logger: Option<&mut xentoollog_logger>,
dombuild_logger: Option<&mut xentoollog_logger>,
open_flags: u32,
) -> Result<Self> {
let xc_handle = unsafe {
xenctrl_sys::xc_interface_open(null_mut(), null_mut(), 0)
xc_interface_open(
logger.map_or_else(|| null_mut(), |l| l as *mut _),
dombuild_logger.map_or_else(|| null_mut(), |l| l as *mut _),
open_flags,
)
};
if xc_handle == null_mut() {
return Err(Error::last_os_error());
}
Ok(Xc {
handle: xc_handle,
evtchn_port: null_mut()
})

NonNull::new(xc_handle)
.ok_or_else(|| Error::new(xc_error_code::XC_INTERNAL_ERROR))
.map(|handle| XenControl {
handle,
evtchn_port: 0u32,
})
}

pub fn monitor_enable(&self, domid: u32) -> *mut c_void {
unsafe {
xenctrl_sys::xc_monitor_enable(self.handle, domid, self.evtchn_port)
}
pub fn default() -> Result<Self> {
Self::new(None, None, 0)
}

pub fn monitor_disable(&self, domid: u32) {
pub fn monitor_enable(&mut self, domid: u32) -> Result<&PageInfo> {
let xc = self.handle.as_ptr();
let ring_page = unsafe {
xc_clear_last_error(xc);
xc_monitor_enable(xc, domid, &mut self.evtchn_port as _) as *const PageInfo
};
last_error!(xc, &*ring_page)
}

pub fn monitor_disable(&self, domid: u32) -> Result<()> {
let xc = self.handle.as_ptr();
unsafe {
xenctrl_sys::xc_monitor_disable(self.handle, domid);
xc_clear_last_error(xc);
xc_monitor_disable(xc, domid);
};
last_error!(xc, ())
}

pub fn domain_pause(&self, domid: u32) -> Result<(),&str> {
pub fn domain_pause(&self, domid: u32) -> Result<()> {
let xc = self.handle.as_ptr();
unsafe {
match xenctrl_sys::xc_domain_pause(self.handle, domid) {
0 => Ok(()),
-1 => Err("Fail to pause domain"),
_ => panic!("unexpected value"),
}
}
xc_clear_last_error(xc);
xc_domain_pause(xc, domid);
};
last_error!(xc, ())
}

pub fn domain_unpause(&self, domid: u32) -> Result<(),&str> {
pub fn domain_unpause(&self, domid: u32) -> Result<()> {
let xc = self.handle.as_ptr();
unsafe {
match xenctrl_sys::xc_domain_unpause(self.handle, domid) {
0 => Ok(()),
-1 => Err("Fail to unpause domain"),
_ => panic!("unexpected value"),
}
xc_clear_last_error(xc);
xc_domain_unpause(xc, domid);
}
last_error!(xc, ())
}

pub fn domain_maximum_gpfn(&self, domid: u32) -> Result<u64,&str> {
let mut max_gpfn: c_ulong = 0;
let ptr_max_gpfn: *mut c_ulong = &mut max_gpfn;
let result = unsafe {
xenctrl_sys::xc_domain_maximum_gpfn(self.handle, domid, ptr_max_gpfn)
};
match result {
0 => Ok(max_gpfn as u64),
-1 => Err("Fail to get max gpfn"),
_ => panic!("unexpected value"),
pub fn domain_maximum_gpfn(&self, domid: u32) -> Result<u64> {
let xc = self.handle.as_ptr();
let mut max_gpfn: u64;
unsafe {
max_gpfn = mem::uninitialized();
xc_clear_last_error(xc);
xc_domain_maximum_gpfn(xc, domid, &mut max_gpfn as _);
}
last_error!(xc, max_gpfn)
}

fn close(&mut self) -> Result<(),&str>{
let result = unsafe {
xenctrl_sys::xc_interface_close(self.handle)
};
match result {
0 => Ok(()),
-1 => Err("Fail to close xc interface"),
_ => panic!("unexpected value"),
fn close(&mut self) -> Result<()> {
let xc = self.handle.as_ptr();
unsafe {
xc_clear_last_error(xc);
xc_interface_close(xc);
}
last_error!(xc, ())
}
}

impl Drop for Xc {
impl Drop for XenControl {
fn drop(&mut self) {
self.close().unwrap();
}
Expand Down
11 changes: 11 additions & 0 deletions src/macros.rs
@@ -0,0 +1,11 @@
macro_rules! last_error {
($xc:expr, $ok:expr) => {
unsafe {
let err = xc_get_last_error($xc);
match (*err).code {
xc_error_code::XC_ERROR_NONE => Ok($ok),
code => Err(Error::new(code)),
}
}
};
}
4 changes: 4 additions & 0 deletions src/support.rs
@@ -0,0 +1,4 @@
#[repr(C)]
pub struct PageInfo {
opaque: [u8; 0],
}