diff options
Diffstat (limited to 'rust/kernel/error.rs')
| -rw-r--r-- | rust/kernel/error.rs | 61 | 
1 files changed, 60 insertions, 1 deletions
| diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 5f4114b30b94..05fcab6abfe6 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -4,16 +4,20 @@  //!  //! C header: [`include/uapi/asm-generic/errno-base.h`](../../../include/uapi/asm-generic/errno-base.h) +use crate::str::CStr; +  use alloc::{      alloc::{AllocError, LayoutError},      collections::TryReserveError,  };  use core::convert::From; +use core::fmt;  use core::num::TryFromIntError;  use core::str::Utf8Error;  /// Contains the C-compatible error codes. +#[rustfmt::skip]  pub mod code {      macro_rules! declare_err {          ($err:tt $(,)? $($doc:expr),+) => { @@ -58,6 +62,25 @@ 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."); +    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."); +    declare_err!(ENOIOCTLCMD, "No ioctl command."); +    declare_err!(ERESTART_RESTARTBLOCK, "Restart by calling sys_restart_syscall."); +    declare_err!(EPROBE_DEFER, "Driver requests probe retry."); +    declare_err!(EOPENSTALE, "Open found a stale dentry."); +    declare_err!(ENOPARAM, "Parameter not supported."); +    declare_err!(EBADHANDLE, "Illegal NFS file handle."); +    declare_err!(ENOTSYNC, "Update synchronization mismatch."); +    declare_err!(EBADCOOKIE, "Cookie is stale."); +    declare_err!(ENOTSUPP, "Operation is not supported."); +    declare_err!(ETOOSMALL, "Buffer or request is too small."); +    declare_err!(ESERVERFAULT, "An untranslatable error occurred."); +    declare_err!(EBADTYPE, "Type not supported by server."); +    declare_err!(EJUKEBOX, "Request initiated, but will not complete before timeout."); +    declare_err!(EIOCBQUEUED, "iocb queued, will get completion event."); +    declare_err!(ERECALLCONFLICT, "Conflict with recalled state."); +    declare_err!(ENOGRACE, "NFS file lock reclaim refused.");  }  /// Generic integer kernel error. @@ -113,6 +136,42 @@ impl Error {          // SAFETY: self.0 is a valid error due to its invariant.          unsafe { bindings::ERR_PTR(self.0.into()) as *mut _ }      } + +    /// Returns a string representing the error, if one exists. +    #[cfg(not(testlib))] +    pub fn name(&self) -> Option<&'static CStr> { +        // SAFETY: Just an FFI call, there are no extra safety requirements. +        let ptr = unsafe { bindings::errname(-self.0) }; +        if ptr.is_null() { +            None +        } else { +            // SAFETY: The string returned by `errname` is static and `NUL`-terminated. +            Some(unsafe { CStr::from_char_ptr(ptr) }) +        } +    } + +    /// Returns a string representing the error, if one exists. +    /// +    /// When `testlib` is configured, this always returns `None` to avoid the dependency on a +    /// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still +    /// run in userspace. +    #[cfg(testlib)] +    pub fn name(&self) -> Option<&'static CStr> { +        None +    } +} + +impl fmt::Debug for Error { +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        match self.name() { +            // Print out number if no name can be found. +            None => f.debug_tuple("Error").field(&-self.0).finish(), +            // SAFETY: These strings are ASCII-only. +            Some(name) => f +                .debug_tuple(unsafe { core::str::from_utf8_unchecked(name) }) +                .finish(), +        } +    }  }  impl From<AllocError> for Error { @@ -177,7 +236,7 @@ impl From<core::convert::Infallible> for Error {  /// Note that even if a function does not return anything when it succeeds,  /// it should still be modeled as returning a `Result` rather than  /// just an [`Error`]. -pub type Result<T = ()> = core::result::Result<T, Error>; +pub type Result<T = (), E = Error> = core::result::Result<T, E>;  /// Converts an integer as returned by a C kernel function to an error if it's negative, and  /// `Ok(())` otherwise. |