Skip to content

Commit fb672e0

Browse files
authored
Merge pull request #266 from TheSven73/rust-for-linux-from-kernel-result
rust/kernel: move from_kernel_result! macro to error.rs
2 parents 3729708 + eb4c6e8 commit fb672e0

File tree

2 files changed

+49
-19
lines changed

2 files changed

+49
-19
lines changed

rust/kernel/error.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
use crate::{bindings, c_types};
88
use alloc::{alloc::AllocError, collections::TryReserveError};
9+
use core::convert::From;
910
use core::{num::TryFromIntError, str::Utf8Error};
1011

1112
/// Generic integer kernel error.
@@ -104,3 +105,50 @@ impl From<AllocError> for Error {
104105
Error::ENOMEM
105106
}
106107
}
108+
109+
// # Invariant: `-bindings::MAX_ERRNO` fits in an `i16`.
110+
crate::static_assert!(bindings::MAX_ERRNO <= -(i16::MIN as i32) as u32);
111+
112+
#[doc(hidden)]
113+
pub fn from_kernel_result_helper<T>(r: Result<T>) -> T
114+
where
115+
T: From<i16>,
116+
{
117+
match r {
118+
Ok(v) => v,
119+
// NO-OVERFLOW: negative `errno`s are no smaller than `-bindings::MAX_ERRNO`,
120+
// `-bindings::MAX_ERRNO` fits in an `i16` as per invariant above,
121+
// therefore a negative `errno` always fits in an `i16` and will not overflow.
122+
Err(e) => T::from(e.to_kernel_errno() as i16),
123+
}
124+
}
125+
126+
/// Transforms a [`crate::error::Result<T>`] to a kernel C integer result.
127+
///
128+
/// This is useful when calling Rust functions that return [`crate::error::Result<T>`]
129+
/// from inside `extern "C"` functions that need to return an integer
130+
/// error result.
131+
///
132+
/// `T` should be convertible to an `i16` via `From<i16>`.
133+
///
134+
/// # Examples
135+
///
136+
/// ```rust,no_run
137+
/// unsafe extern "C" fn probe_callback(
138+
/// pdev: *mut bindings::platform_device,
139+
/// ) -> c_types::c_int {
140+
/// from_kernel_result! {
141+
/// let ptr = devm_alloc(pdev)?;
142+
/// rust_helper_platform_set_drvdata(pdev, ptr);
143+
/// Ok(0)
144+
/// }
145+
/// }
146+
/// ```
147+
#[macro_export]
148+
macro_rules! from_kernel_result {
149+
($($tt:tt)*) => {{
150+
$crate::error::from_kernel_result_helper((|| {
151+
$($tt)*
152+
})())
153+
}};
154+
}

rust/kernel/file_operations.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::{
1313
bindings, c_types,
1414
error::{Error, Result},
1515
file::File,
16+
from_kernel_result,
1617
io_buffer::{IoBufferReader, IoBufferWriter},
1718
iov_iter::IovIter,
1819
sync::CondVar,
@@ -78,25 +79,6 @@ pub enum SeekFrom {
7879
Current(i64),
7980
}
8081

81-
fn from_kernel_result<T>(r: Result<T>) -> T
82-
where
83-
T: TryFrom<c_types::c_int>,
84-
T::Error: core::fmt::Debug,
85-
{
86-
match r {
87-
Ok(v) => v,
88-
Err(e) => T::try_from(e.to_kernel_errno()).unwrap(),
89-
}
90-
}
91-
92-
macro_rules! from_kernel_result {
93-
($($tt:tt)*) => {{
94-
from_kernel_result((|| {
95-
$($tt)*
96-
})())
97-
}};
98-
}
99-
10082
unsafe extern "C" fn open_callback<A: FileOpenAdapter, T: FileOpener<A::Arg>>(
10183
inode: *mut bindings::inode,
10284
file: *mut bindings::file,

0 commit comments

Comments
 (0)