Skip to content

Commit bbb8b2f

Browse files
authored
Merge pull request #3 from tathanhdinh/error_support_wip
error handling
2 parents 43c50e1 + c5add66 commit bbb8b2f

File tree

7 files changed

+154
-58
lines changed

7 files changed

+154
-58
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ description = "Rust bindings for Xen's xenctrl library"
1010
license = "GPL-3.0-only"
1111

1212
[dependencies]
13-
xenctrl-sys = { git = "https://github.com/Wenzel/xenctrl-sys" }
13+
xenctrl-sys = { git = "https://github.com/Wenzel/xenctrl-sys.git" }

rustfmt.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
edition = "2018"
2+
indent_style = "block"
3+
format_strings = true
4+
merge_imports = true
5+
reorder_imports = true
6+
wrap_comments = true

src/consts.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub const PAGE_SHIFT: u32 = xenctrl_sys::XC_PAGE_SHIFT;
2+
pub const PAGE_SIZE: u32 = xenctrl_sys::XC_PAGE_SIZE;
3+
pub const PAGE_MASK: i32 = xenctrl_sys::XC_PAGE_MASK;
4+
5+
pub const CORE_MAGIC: u32 = xenctrl_sys::XC_CORE_MAGIC;
6+
pub const CORE_MAGIC_HVM: u32 = xenctrl_sys::XC_CORE_MAGIC_HVM;
7+
8+
pub const CPUPOOL_POOLID_ANY: u32 = xenctrl_sys::XC_CPUPOOL_POOLID_ANY;
9+
10+
pub const MAX_ERROR_MSG_LEN: u32 = xenctrl_sys::XC_MAX_ERROR_MSG_LEN;

src/error.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use std::{
2+
error, ffi,
3+
fmt::{self, Debug, Display, Formatter},
4+
};
5+
6+
use xenctrl_sys::{xc_error_code, xc_error_code_to_desc};
7+
8+
#[derive(Copy, Clone)]
9+
pub struct Error(xc_error_code);
10+
11+
impl Error {
12+
pub fn new(code: xc_error_code) -> Self {
13+
Self(code)
14+
}
15+
16+
pub fn desc(self) -> &'static str {
17+
unsafe {
18+
let desc = xc_error_code_to_desc(self.0 as _);
19+
ffi::CStr::from_ptr(desc).to_str().unwrap()
20+
}
21+
}
22+
}
23+
24+
impl Display for Error {
25+
#[inline]
26+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
27+
write!(f, "{}", self.desc())
28+
}
29+
}
30+
31+
impl Debug for Error {
32+
#[inline]
33+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
34+
write!(f, "{}", self.desc())
35+
}
36+
}
37+
38+
impl error::Error for Error {}

src/lib.rs

Lines changed: 84 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,117 @@
1+
pub mod error;
2+
pub mod support;
3+
pub mod consts;
4+
5+
#[macro_use]
6+
mod macros;
7+
18
extern crate xenctrl_sys;
2-
use std::io::Error;
3-
use std::ptr::{null_mut};
4-
use std::os::raw::{c_void, c_ulong};
9+
use std::{
10+
mem,
11+
ptr::{null_mut, NonNull},
12+
};
13+
14+
use xenctrl_sys::{
15+
xc_clear_last_error, xc_domain_maximum_gpfn, xc_domain_pause, xc_domain_unpause, xc_error_code,
16+
xc_get_last_error, xc_interface, xc_interface_close, xc_interface_open, xc_monitor_disable,
17+
xc_monitor_enable, xentoollog_logger,
18+
};
519

6-
pub const PAGE_SHIFT: u32 = xenctrl_sys::XC_PAGE_SHIFT;
7-
pub const PAGE_SIZE: u32 = xenctrl_sys::XC_PAGE_SIZE;
20+
use error::Error;
21+
use support::PageInfo;
22+
23+
type Result<T> = std::result::Result<T, Error>;
824

925
#[derive(Debug)]
10-
pub struct Xc {
11-
handle: *mut xenctrl_sys::xc_interface,
12-
evtchn_port: *mut u32,
26+
pub struct XenControl {
27+
handle: NonNull<xc_interface>,
28+
evtchn_port: u32,
1329
}
1430

15-
impl Xc {
16-
17-
pub fn new() -> Result<Self,Error> {
31+
impl XenControl {
32+
pub fn new(
33+
logger: Option<&mut xentoollog_logger>,
34+
dombuild_logger: Option<&mut xentoollog_logger>,
35+
open_flags: u32,
36+
) -> Result<Self> {
1837
let xc_handle = unsafe {
19-
xenctrl_sys::xc_interface_open(null_mut(), null_mut(), 0)
38+
xc_interface_open(
39+
logger.map_or_else(|| null_mut(), |l| l as *mut _),
40+
dombuild_logger.map_or_else(|| null_mut(), |l| l as *mut _),
41+
open_flags,
42+
)
2043
};
21-
if xc_handle == null_mut() {
22-
return Err(Error::last_os_error());
23-
}
24-
Ok(Xc {
25-
handle: xc_handle,
26-
evtchn_port: null_mut()
27-
})
44+
45+
NonNull::new(xc_handle)
46+
.ok_or_else(|| Error::new(xc_error_code::XC_INTERNAL_ERROR))
47+
.map(|handle| XenControl {
48+
handle,
49+
evtchn_port: 0u32,
50+
})
2851
}
2952

30-
pub fn monitor_enable(&self, domid: u32) -> *mut c_void {
31-
unsafe {
32-
xenctrl_sys::xc_monitor_enable(self.handle, domid, self.evtchn_port)
33-
}
53+
pub fn default() -> Result<Self> {
54+
Self::new(None, None, 0)
3455
}
3556

36-
pub fn monitor_disable(&self, domid: u32) {
57+
pub fn monitor_enable(&mut self, domid: u32) -> Result<&PageInfo> {
58+
let xc = self.handle.as_ptr();
59+
let ring_page = unsafe {
60+
xc_clear_last_error(xc);
61+
xc_monitor_enable(xc, domid, &mut self.evtchn_port as _) as *const PageInfo
62+
};
63+
last_error!(xc, &*ring_page)
64+
}
65+
66+
pub fn monitor_disable(&self, domid: u32) -> Result<()> {
67+
let xc = self.handle.as_ptr();
3768
unsafe {
38-
xenctrl_sys::xc_monitor_disable(self.handle, domid);
69+
xc_clear_last_error(xc);
70+
xc_monitor_disable(xc, domid);
3971
};
72+
last_error!(xc, ())
4073
}
4174

42-
pub fn domain_pause(&self, domid: u32) -> Result<(),&str> {
75+
pub fn domain_pause(&self, domid: u32) -> Result<()> {
76+
let xc = self.handle.as_ptr();
4377
unsafe {
44-
match xenctrl_sys::xc_domain_pause(self.handle, domid) {
45-
0 => Ok(()),
46-
-1 => Err("Fail to pause domain"),
47-
_ => panic!("unexpected value"),
48-
}
49-
}
78+
xc_clear_last_error(xc);
79+
xc_domain_pause(xc, domid);
80+
};
81+
last_error!(xc, ())
5082
}
5183

52-
pub fn domain_unpause(&self, domid: u32) -> Result<(),&str> {
84+
pub fn domain_unpause(&self, domid: u32) -> Result<()> {
85+
let xc = self.handle.as_ptr();
5386
unsafe {
54-
match xenctrl_sys::xc_domain_unpause(self.handle, domid) {
55-
0 => Ok(()),
56-
-1 => Err("Fail to unpause domain"),
57-
_ => panic!("unexpected value"),
58-
}
87+
xc_clear_last_error(xc);
88+
xc_domain_unpause(xc, domid);
5989
}
90+
last_error!(xc, ())
6091
}
6192

62-
pub fn domain_maximum_gpfn(&self, domid: u32) -> Result<u64,&str> {
63-
let mut max_gpfn: c_ulong = 0;
64-
let ptr_max_gpfn: *mut c_ulong = &mut max_gpfn;
65-
let result = unsafe {
66-
xenctrl_sys::xc_domain_maximum_gpfn(self.handle, domid, ptr_max_gpfn)
67-
};
68-
match result {
69-
0 => Ok(max_gpfn as u64),
70-
-1 => Err("Fail to get max gpfn"),
71-
_ => panic!("unexpected value"),
93+
pub fn domain_maximum_gpfn(&self, domid: u32) -> Result<u64> {
94+
let xc = self.handle.as_ptr();
95+
let mut max_gpfn: u64;
96+
unsafe {
97+
max_gpfn = mem::uninitialized();
98+
xc_clear_last_error(xc);
99+
xc_domain_maximum_gpfn(xc, domid, &mut max_gpfn as _);
72100
}
101+
last_error!(xc, max_gpfn)
73102
}
74103

75-
fn close(&mut self) -> Result<(),&str>{
76-
let result = unsafe {
77-
xenctrl_sys::xc_interface_close(self.handle)
78-
};
79-
match result {
80-
0 => Ok(()),
81-
-1 => Err("Fail to close xc interface"),
82-
_ => panic!("unexpected value"),
104+
fn close(&mut self) -> Result<()> {
105+
let xc = self.handle.as_ptr();
106+
unsafe {
107+
xc_clear_last_error(xc);
108+
xc_interface_close(xc);
83109
}
110+
last_error!(xc, ())
84111
}
85112
}
86113

87-
impl Drop for Xc {
114+
impl Drop for XenControl {
88115
fn drop(&mut self) {
89116
self.close().unwrap();
90117
}

src/macros.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
macro_rules! last_error {
2+
($xc:expr, $ok:expr) => {
3+
unsafe {
4+
let err = xc_get_last_error($xc);
5+
match (*err).code {
6+
xc_error_code::XC_ERROR_NONE => Ok($ok),
7+
code => Err(Error::new(code)),
8+
}
9+
}
10+
};
11+
}

src/support.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[repr(C)]
2+
pub struct PageInfo {
3+
opaque: [u8; 0],
4+
}

0 commit comments

Comments
 (0)