summaryrefslogtreecommitdiff
path: root/rust/kernel/error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel/error.rs')
-rw-r--r--rust/kernel/error.rs146
1 files changed, 142 insertions, 4 deletions
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index 258b12afdcba..e52793f77196 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -25,13 +25,12 @@ pub mod code {
#[doc = $doc]
)*
pub const $err: super::Error =
- match super::Error::try_from_errno(-(crate::bindings::$err as i32)) {
- Some(err) => err,
- None => panic!("Invalid errno in `declare_err!`"),
- };
+ super::Error::try_from_errno(-(crate::bindings::$err as i32))
+ .expect("Invalid errno in `declare_err!`");
};
}
+ // From `include/uapi/asm-generic/errno-base.h`.
declare_err!(EPERM, "Operation not permitted.");
declare_err!(ENOENT, "No such file or directory.");
declare_err!(ESRCH, "No such process.");
@@ -66,8 +65,110 @@ pub mod code {
declare_err!(EPIPE, "Broken pipe.");
declare_err!(EDOM, "Math argument out of domain of func.");
declare_err!(ERANGE, "Math result not representable.");
+
+ // From `include/uapi/asm-generic/errno.h`.
+ declare_err!(EDEADLK, "Resource deadlock would occur.");
+ declare_err!(ENAMETOOLONG, "File name too long.");
+ declare_err!(ENOLCK, "No record locks available.");
+ declare_err!(ENOSYS, "Invalid system call number.");
+ declare_err!(ENOTEMPTY, "Directory not empty.");
+ declare_err!(ELOOP, "Too many symbolic links encountered.");
+ declare_err!(ENOMSG, "No message of desired type.");
+ declare_err!(EIDRM, "Identifier removed.");
+ declare_err!(ECHRNG, "Channel number out of range.");
+ declare_err!(EL2NSYNC, "Level 2 not synchronized.");
+ declare_err!(EL3HLT, "Level 3 halted.");
+ declare_err!(EL3RST, "Level 3 reset.");
+ declare_err!(ELNRNG, "Link number out of range.");
+ declare_err!(EUNATCH, "Protocol driver not attached.");
+ declare_err!(ENOCSI, "No CSI structure available.");
+ declare_err!(EL2HLT, "Level 2 halted.");
+ declare_err!(EBADE, "Invalid exchange.");
+ declare_err!(EBADR, "Invalid request descriptor.");
+ declare_err!(EXFULL, "Exchange full.");
+ declare_err!(ENOANO, "No anode.");
+ declare_err!(EBADRQC, "Invalid request code.");
+ declare_err!(EBADSLT, "Invalid slot.");
+ declare_err!(EBFONT, "Bad font file format.");
+ declare_err!(ENOSTR, "Device not a stream.");
+ declare_err!(ENODATA, "No data available.");
+ declare_err!(ETIME, "Timer expired.");
+ declare_err!(ENOSR, "Out of streams resources.");
+ declare_err!(ENONET, "Machine is not on the network.");
+ declare_err!(ENOPKG, "Package not installed.");
+ declare_err!(EREMOTE, "Object is remote.");
+ declare_err!(ENOLINK, "Link has been severed.");
+ declare_err!(EADV, "Advertise error.");
+ declare_err!(ESRMNT, "Srmount error.");
+ declare_err!(ECOMM, "Communication error on send.");
+ declare_err!(EPROTO, "Protocol error.");
+ declare_err!(EMULTIHOP, "Multihop attempted.");
+ declare_err!(EDOTDOT, "RFS specific error.");
+ declare_err!(EBADMSG, "Not a data message.");
+ declare_err!(EFSBADCRC, "Bad CRC detected.");
declare_err!(EOVERFLOW, "Value too large for defined data type.");
+ declare_err!(ENOTUNIQ, "Name not unique on network.");
+ declare_err!(EBADFD, "File descriptor in bad state.");
+ declare_err!(EREMCHG, "Remote address changed.");
+ declare_err!(ELIBACC, "Can not access a needed shared library.");
+ declare_err!(ELIBBAD, "Accessing a corrupted shared library.");
+ declare_err!(ELIBSCN, ".lib section in a.out corrupted.");
+ declare_err!(ELIBMAX, "Attempting to link in too many shared libraries.");
+ declare_err!(ELIBEXEC, "Cannot exec a shared library directly.");
+ declare_err!(EILSEQ, "Illegal byte sequence.");
+ declare_err!(ERESTART, "Interrupted system call should be restarted.");
+ declare_err!(ESTRPIPE, "Streams pipe error.");
+ declare_err!(EUSERS, "Too many users.");
+ declare_err!(ENOTSOCK, "Socket operation on non-socket.");
+ declare_err!(EDESTADDRREQ, "Destination address required.");
+ declare_err!(EMSGSIZE, "Message too long.");
+ declare_err!(EPROTOTYPE, "Protocol wrong type for socket.");
+ declare_err!(ENOPROTOOPT, "Protocol not available.");
+ declare_err!(EPROTONOSUPPORT, "Protocol not supported.");
+ declare_err!(ESOCKTNOSUPPORT, "Socket type not supported.");
+ declare_err!(EOPNOTSUPP, "Operation not supported on transport endpoint.");
+ declare_err!(EPFNOSUPPORT, "Protocol family not supported.");
+ declare_err!(EAFNOSUPPORT, "Address family not supported by protocol.");
+ declare_err!(EADDRINUSE, "Address already in use.");
+ declare_err!(EADDRNOTAVAIL, "Cannot assign requested address.");
+ declare_err!(ENETDOWN, "Network is down.");
+ declare_err!(ENETUNREACH, "Network is unreachable.");
+ declare_err!(ENETRESET, "Network dropped connection because of reset.");
+ declare_err!(ECONNABORTED, "Software caused connection abort.");
+ declare_err!(ECONNRESET, "Connection reset by peer.");
+ declare_err!(ENOBUFS, "No buffer space available.");
+ declare_err!(EISCONN, "Transport endpoint is already connected.");
+ declare_err!(ENOTCONN, "Transport endpoint is not connected.");
+ declare_err!(ESHUTDOWN, "Cannot send after transport endpoint shutdown.");
+ declare_err!(ETOOMANYREFS, "Too many references: cannot splice.");
declare_err!(ETIMEDOUT, "Connection timed out.");
+ declare_err!(ECONNREFUSED, "Connection refused.");
+ declare_err!(EHOSTDOWN, "Host is down.");
+ declare_err!(EHOSTUNREACH, "No route to host.");
+ declare_err!(EALREADY, "Operation already in progress.");
+ declare_err!(EINPROGRESS, "Operation now in progress.");
+ declare_err!(ESTALE, "Stale file handle.");
+ declare_err!(EUCLEAN, "Structure needs cleaning.");
+ declare_err!(EFSCORRUPTED, "Filesystem is corrupted.");
+ declare_err!(ENOTNAM, "Not a XENIX named type file.");
+ declare_err!(ENAVAIL, "No XENIX semaphores available.");
+ declare_err!(EISNAM, "Is a named type file.");
+ declare_err!(EREMOTEIO, "Remote I/O error.");
+ declare_err!(EDQUOT, "Quota exceeded.");
+ declare_err!(ENOMEDIUM, "No medium found.");
+ declare_err!(EMEDIUMTYPE, "Wrong medium type.");
+ declare_err!(ECANCELED, "Operation Canceled.");
+ declare_err!(ENOKEY, "Required key not available.");
+ declare_err!(EKEYEXPIRED, "Key has expired.");
+ declare_err!(EKEYREVOKED, "Key has been revoked.");
+ declare_err!(EKEYREJECTED, "Key was rejected by service.");
+ declare_err!(EOWNERDEAD, "Owner died.");
+ declare_err!(ENOTRECOVERABLE, "State not recoverable.");
+ declare_err!(ERFKILL, "Operation not possible due to RF-kill.");
+ declare_err!(EHWPOISON, "Memory page has hardware error.");
+ declare_err!(EFTYPE, "Wrong file type for the intended operation.");
+
+ // From `include/linux/errno.h`.
declare_err!(ERESTARTSYS, "Restart the system call.");
declare_err!(ERESTARTNOINTR, "System call was interrupted by a signal and will be restarted.");
declare_err!(ERESTARTNOHAND, "Restart if no handler.");
@@ -216,36 +317,42 @@ impl fmt::Debug for Error {
}
impl From<AllocError> for Error {
+ #[inline]
fn from(_: AllocError) -> Error {
code::ENOMEM
}
}
impl From<TryFromIntError> for Error {
+ #[inline]
fn from(_: TryFromIntError) -> Error {
code::EINVAL
}
}
impl From<Utf8Error> for Error {
+ #[inline]
fn from(_: Utf8Error) -> Error {
code::EINVAL
}
}
impl From<LayoutError> for Error {
+ #[inline]
fn from(_: LayoutError) -> Error {
code::ENOMEM
}
}
impl From<fmt::Error> for Error {
+ #[inline]
fn from(_: fmt::Error) -> Error {
code::EINVAL
}
}
impl From<core::convert::Infallible> for Error {
+ #[inline]
fn from(e: core::convert::Infallible) -> Error {
match e {}
}
@@ -446,6 +553,9 @@ pub fn to_result(err: crate::ffi::c_int) -> Result {
/// for errors. This function performs the check and converts the "error pointer"
/// to a normal pointer in an idiomatic fashion.
///
+/// Note that a `NULL` pointer is not considered an error pointer, and is returned
+/// as-is, wrapped in [`Ok`].
+///
/// # Examples
///
/// ```ignore
@@ -460,6 +570,34 @@ pub fn to_result(err: crate::ffi::c_int) -> Result {
/// from_err_ptr(unsafe { bindings::devm_platform_ioremap_resource(pdev.to_ptr(), index) })
/// }
/// ```
+///
+/// ```
+/// # use kernel::error::from_err_ptr;
+/// # mod bindings {
+/// # #![expect(clippy::missing_safety_doc)]
+/// # use kernel::prelude::*;
+/// # pub(super) unsafe fn einval_err_ptr() -> *mut kernel::ffi::c_void {
+/// # EINVAL.to_ptr()
+/// # }
+/// # pub(super) unsafe fn null_ptr() -> *mut kernel::ffi::c_void {
+/// # core::ptr::null_mut()
+/// # }
+/// # pub(super) unsafe fn non_null_ptr() -> *mut kernel::ffi::c_void {
+/// # 0x1234 as *mut kernel::ffi::c_void
+/// # }
+/// # }
+/// // SAFETY: ...
+/// let einval_err = from_err_ptr(unsafe { bindings::einval_err_ptr() });
+/// assert_eq!(einval_err, Err(EINVAL));
+///
+/// // SAFETY: ...
+/// let null_ok = from_err_ptr(unsafe { bindings::null_ptr() });
+/// assert_eq!(null_ok, Ok(core::ptr::null_mut()));
+///
+/// // SAFETY: ...
+/// let non_null = from_err_ptr(unsafe { bindings::non_null_ptr() }).unwrap();
+/// assert_ne!(non_null, core::ptr::null_mut());
+/// ```
pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
// CAST: Casting a pointer to `*const crate::ffi::c_void` is always valid.
let const_ptr: *const crate::ffi::c_void = ptr.cast();