Skip to content

Commit f98e62a

Browse files
committed
Rust: Use a tighter inner type for Error
Use NonZeroI16 as the inner type. This allows Result<()> to fit in 16-bit, instead of 64-bit. Signed-off-by: Fox Chen <foxhlchen@gmail.com>
1 parent bfe9ec6 commit f98e62a

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

rust/kernel/error.rs

+34-19
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{bindings, c_types};
99
use alloc::{alloc::AllocError, collections::TryReserveError};
1010
use core::convert::From;
1111
use core::fmt;
12-
use core::num::TryFromIntError;
12+
use core::num::{NonZeroI32, TryFromIntError};
1313
use core::str::{self, Utf8Error};
1414

1515
/// Generic integer kernel error.
@@ -21,44 +21,49 @@ use core::str::{self, Utf8Error};
2121
///
2222
/// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`).
2323
#[derive(Clone, Copy, PartialEq, Eq)]
24-
pub struct Error(c_types::c_int);
24+
pub struct Error(NonZeroI32);
25+
26+
/// DO NOT use this function outside of Error const initializations.
27+
const fn kernel_const_to_error(val: u32) -> Error {
28+
Error(unsafe { NonZeroI32::new_unchecked(-(val as i32)) })
29+
}
2530

2631
impl Error {
2732
/// Invalid argument.
28-
pub const EINVAL: Self = Error(-(bindings::EINVAL as i32));
33+
pub const EINVAL: Self = kernel_const_to_error(bindings::EINVAL);
2934

3035
/// Out of memory.
31-
pub const ENOMEM: Self = Error(-(bindings::ENOMEM as i32));
36+
pub const ENOMEM: Self = kernel_const_to_error(bindings::ENOMEM);
3237

3338
/// Bad address.
34-
pub const EFAULT: Self = Error(-(bindings::EFAULT as i32));
39+
pub const EFAULT: Self = kernel_const_to_error(bindings::EFAULT);
3540

3641
/// Illegal seek.
37-
pub const ESPIPE: Self = Error(-(bindings::ESPIPE as i32));
42+
pub const ESPIPE: Self = kernel_const_to_error(bindings::ESPIPE);
3843

3944
/// Try again.
40-
pub const EAGAIN: Self = Error(-(bindings::EAGAIN as i32));
45+
pub const EAGAIN: Self = kernel_const_to_error(bindings::EAGAIN);
4146

4247
/// Device or resource busy.
43-
pub const EBUSY: Self = Error(-(bindings::EBUSY as i32));
48+
pub const EBUSY: Self = kernel_const_to_error(bindings::EBUSY);
4449

4550
/// Restart the system call.
46-
pub const ERESTARTSYS: Self = Error(-(bindings::ERESTARTSYS as i32));
51+
pub const ERESTARTSYS: Self = kernel_const_to_error(bindings::ERESTARTSYS);
4752

4853
/// Operation not permitted.
49-
pub const EPERM: Self = Error(-(bindings::EPERM as i32));
54+
pub const EPERM: Self = kernel_const_to_error(bindings::EPERM);
5055

5156
/// No such process.
52-
pub const ESRCH: Self = Error(-(bindings::ESRCH as i32));
57+
pub const ESRCH: Self = kernel_const_to_error(bindings::ESRCH);
5358

5459
/// No such file or directory.
55-
pub const ENOENT: Self = Error(-(bindings::ENOENT as i32));
60+
pub const ENOENT: Self = kernel_const_to_error(bindings::ENOENT);
5661

5762
/// Interrupted system call.
58-
pub const EINTR: Self = Error(-(bindings::EINTR as i32));
63+
pub const EINTR: Self = kernel_const_to_error(bindings::EINTR);
5964

6065
/// Bad file number.
61-
pub const EBADF: Self = Error(-(bindings::EBADF as i32));
66+
pub const EBADF: Self = kernel_const_to_error(bindings::EBADF);
6267

6368
/// Creates an [`Error`] from a kernel error code.
6469
///
@@ -76,7 +81,11 @@ impl Error {
7681

7782
// INVARIANT: the check above ensures the type invariant
7883
// will hold.
79-
Error(errno)
84+
//
85+
// Safety: `errno` must be non zero, which is guaranteed by the check
86+
// above.
87+
let nz_errno = unsafe { NonZeroI32::new_unchecked(errno) };
88+
Error(nz_errno)
8089
}
8190

8291
/// Creates an [`Error`] from a kernel error code.
@@ -87,12 +96,15 @@ impl Error {
8796
pub(crate) unsafe fn from_kernel_errno_unchecked(errno: c_types::c_int) -> Error {
8897
// INVARIANT: the contract ensures the type invariant
8998
// will hold.
90-
Error(errno)
99+
//
100+
// Safety: `errno` must not be zero, which is guaranteed by the contract
101+
// of this function.
102+
Error(unsafe { NonZeroI32::new_unchecked(errno) })
91103
}
92104

93105
/// Returns the kernel error code.
94106
pub fn to_kernel_errno(self) -> c_types::c_int {
95-
self.0
107+
self.0.get()
96108
}
97109
}
98110

@@ -102,11 +114,14 @@ impl fmt::Debug for Error {
102114
fn rust_helper_errname(err: c_types::c_int) -> *const c_types::c_char;
103115
}
104116
// SAFETY: FFI call.
105-
let name = unsafe { rust_helper_errname(-self.0) };
117+
let name = unsafe { rust_helper_errname(-self.to_kernel_errno()) };
106118

107119
if name.is_null() {
108120
// Print out number if no name can be found.
109-
return f.debug_tuple("Error").field(&-self.0).finish();
121+
return f
122+
.debug_tuple("Error")
123+
.field(&-self.to_kernel_errno())
124+
.finish();
110125
}
111126

112127
// SAFETY: `'static` string from C, and is not NULL.

0 commit comments

Comments
 (0)