Skip to content

Commit

Permalink
Merge pull request #266 from TheSven73/rust-for-linux-from-kernel-result
Browse files Browse the repository at this point in the history
rust/kernel: move from_kernel_result! macro to error.rs
  • Loading branch information
alex authored May 19, 2021
2 parents 3729708 + eb4c6e8 commit fb672e0
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 19 deletions.
48 changes: 48 additions & 0 deletions rust/kernel/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use crate::{bindings, c_types};
use alloc::{alloc::AllocError, collections::TryReserveError};
use core::convert::From;
use core::{num::TryFromIntError, str::Utf8Error};

/// Generic integer kernel error.
Expand Down Expand Up @@ -104,3 +105,50 @@ impl From<AllocError> for Error {
Error::ENOMEM
}
}

// # Invariant: `-bindings::MAX_ERRNO` fits in an `i16`.
crate::static_assert!(bindings::MAX_ERRNO <= -(i16::MIN as i32) as u32);

#[doc(hidden)]
pub fn from_kernel_result_helper<T>(r: Result<T>) -> T
where
T: From<i16>,
{
match r {
Ok(v) => v,
// NO-OVERFLOW: negative `errno`s are no smaller than `-bindings::MAX_ERRNO`,
// `-bindings::MAX_ERRNO` fits in an `i16` as per invariant above,
// therefore a negative `errno` always fits in an `i16` and will not overflow.
Err(e) => T::from(e.to_kernel_errno() as i16),
}
}

/// Transforms a [`crate::error::Result<T>`] to a kernel C integer result.
///
/// This is useful when calling Rust functions that return [`crate::error::Result<T>`]
/// from inside `extern "C"` functions that need to return an integer
/// error result.
///
/// `T` should be convertible to an `i16` via `From<i16>`.
///
/// # Examples
///
/// ```rust,no_run
/// unsafe extern "C" fn probe_callback(
/// pdev: *mut bindings::platform_device,
/// ) -> c_types::c_int {
/// from_kernel_result! {
/// let ptr = devm_alloc(pdev)?;
/// rust_helper_platform_set_drvdata(pdev, ptr);
/// Ok(0)
/// }
/// }
/// ```
#[macro_export]
macro_rules! from_kernel_result {
($($tt:tt)*) => {{
$crate::error::from_kernel_result_helper((|| {
$($tt)*
})())
}};
}
20 changes: 1 addition & 19 deletions rust/kernel/file_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{
bindings, c_types,
error::{Error, Result},
file::File,
from_kernel_result,
io_buffer::{IoBufferReader, IoBufferWriter},
iov_iter::IovIter,
sync::CondVar,
Expand Down Expand Up @@ -78,25 +79,6 @@ pub enum SeekFrom {
Current(i64),
}

fn from_kernel_result<T>(r: Result<T>) -> T
where
T: TryFrom<c_types::c_int>,
T::Error: core::fmt::Debug,
{
match r {
Ok(v) => v,
Err(e) => T::try_from(e.to_kernel_errno()).unwrap(),
}
}

macro_rules! from_kernel_result {
($($tt:tt)*) => {{
from_kernel_result((|| {
$($tt)*
})())
}};
}

unsafe extern "C" fn open_callback<A: FileOpenAdapter, T: FileOpener<A::Arg>>(
inode: *mut bindings::inode,
file: *mut bindings::file,
Expand Down

0 comments on commit fb672e0

Please sign in to comment.