1use mountpoint_s3_client::error::{GetObjectError, ObjectClientError};
4use tracing::Level;
5
6use crate::fs::error_metadata::ErrorMetadata;
7use crate::metablock::InodeError;
8use crate::prefetch::PrefetchReadError;
9use crate::upload::UploadError;
10
11#[macro_export]
38macro_rules! err {
39 ($errno:expr, __source:$source:expr, $level:expr, $metadata:expr, $message:literal, $($args:tt)*) => {
41 Error {
42 errno: $errno,
43 message: format!($message, $($args)*),
44 source: $source,
45 level: $level,
46 metadata: $metadata,
47 }
48 };
49 ($errno:expr, source:$source:expr, $level:expr, metadata:$metadata:expr, $message:literal) => {
51 err!($errno, __source:Some(::anyhow::Error::new($source)), $level, $metadata, $message, )
52 };
53 ($errno:expr, source:$source:expr, $level:expr, $message:literal, $($args:tt)*) => {
55 err!($errno, __source:Some(::anyhow::Error::new($source)), $level, Default::default(), $message, $($args)*)
56 };
57 ($errno:expr, source:$source:expr, $level:expr, $message:literal) => {
58 err!($errno, __source:Some(::anyhow::Error::new($source)), $level, Default::default(), $message,)
59 };
60 ($errno:expr, source:$source:expr, $message:literal, $($args:tt)*) => {
61 err!($errno, __source:Some(::anyhow::Error::new($source)), ::tracing::Level::WARN, Default::default(), $message, $($args)*)
62 };
63 ($errno:expr, source:$source:expr, $message:literal) => {
64 err!($errno, __source:Some(::anyhow::Error::new($source)), ::tracing::Level::WARN, Default::default(), $message,)
65 };
66 ($errno:expr, $message:literal, $($args:tt)*) => {
67 err!($errno, __source:None, ::tracing::Level::WARN, Default::default(), $message, $($args)*)
68 };
69 ($errno:expr, $message:literal) => {
70 err!($errno, __source:None, ::tracing::Level::WARN, Default::default(), $message,)
71 };
72}
73
74#[derive(Debug, thiserror::Error)]
77pub struct Error {
78 pub(crate) errno: libc::c_int,
79 pub(crate) message: String,
80 pub(crate) source: Option<anyhow::Error>,
81 pub(crate) level: Level,
82 pub(crate) metadata: ErrorMetadata,
83}
84
85impl std::fmt::Display for Error {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 if let Some(source) = self.source.as_ref() {
88 write!(f, "{}: {:#}", self.message, source)
90 } else {
91 write!(f, "{}", self.message)
92 }
93 }
94}
95
96impl From<InodeError> for Error {
97 fn from(err: InodeError) -> Self {
98 let errno = err.to_errno();
99 let metadata = err.meta().clone();
100 Error {
101 errno,
102 message: String::from("inode error"),
103 source: Some(anyhow::anyhow!(err)),
104 level: Level::WARN,
106 metadata,
107 }
108 }
109}
110
111impl<E: std::error::Error + Send + Sync + 'static> From<UploadError<E>> for Error {
112 fn from(err: UploadError<E>) -> Self {
113 let errno = err.to_errno();
114 Error {
115 errno,
116 message: String::from("upload error"),
117 source: Some(anyhow::anyhow!(err)),
118 level: Level::WARN,
120 metadata: Default::default(), }
122 }
123}
124
125impl<E: std::error::Error + Send + Sync + 'static> From<PrefetchReadError<E>> for Error {
126 fn from(err: PrefetchReadError<E>) -> Self {
127 match err {
128 PrefetchReadError::GetRequestFailed {
129 source: ObjectClientError::ServiceError(GetObjectError::PreconditionFailed(_)),
130 metadata,
131 } => err!(libc::ESTALE, __source:None, Level::WARN, (*metadata).clone(), "object was mutated remotely",),
132 PrefetchReadError::GetRequestFailed { source, metadata } => {
133 err!(libc::EIO, source:source, Level::WARN, metadata:(*metadata).clone(), "get request failed")
134 }
135 PrefetchReadError::Integrity(e) => err!(libc::EIO, source:e, "integrity error"),
136 PrefetchReadError::PartReadFailed(e) => err!(libc::EIO, source:e, "part read failed"),
137 PrefetchReadError::GetRequestTerminatedUnexpectedly
138 | PrefetchReadError::GetRequestReturnedWrongOffset { .. }
139 | PrefetchReadError::BackpressurePreconditionFailed
140 | PrefetchReadError::ReadWindowIncrement => {
141 err!(libc::EIO, source:err, "get request failed")
142 }
143 }
144 }
145}
146
147pub trait ToErrno {
149 fn to_errno(&self) -> libc::c_int;
150}
151
152impl ToErrno for Error {
153 fn to_errno(&self) -> libc::c_int {
154 self.errno
155 }
156}
157
158impl ToErrno for InodeError {
159 fn to_errno(&self) -> libc::c_int {
160 match self {
161 InodeError::ClientError { .. } => libc::EIO,
162 InodeError::FileDoesNotExist(_, _) => libc::ENOENT,
163 InodeError::InodeDoesNotExist(_) => libc::ENOENT,
164 InodeError::InvalidFileName(_) => libc::EINVAL,
165 InodeError::NotADirectory(_) => libc::ENOTDIR,
166 InodeError::IsDirectory(_) => libc::EISDIR,
167 InodeError::FileAlreadyExists(_) => libc::EEXIST,
168 InodeError::InodeNotWritable(_) => libc::EPERM,
171 InodeError::InodeInvalidWriteStatus(_) => libc::EPERM,
172 InodeError::InodeAlreadyWriting(_) => libc::EPERM,
173 InodeError::InodeNotReadableWhileWriting(_) => libc::EPERM,
174 InodeError::InodeNotWritableWhileReading(_) => libc::EPERM,
175 InodeError::CannotRemoveRemoteDirectory(_) => libc::EPERM,
176 InodeError::DirectoryNotEmpty(_) => libc::ENOTEMPTY,
177 InodeError::UnlinkNotPermittedWhileWriting(_) => libc::EPERM,
178 InodeError::CorruptedMetadata(_) => libc::EIO,
179 InodeError::SetAttrNotPermittedOnRemoteInode(_) => libc::EPERM,
180 InodeError::StaleInode { .. } => libc::ESTALE,
181 InodeError::CannotRenameDirectory(_) => libc::EPERM,
182 InodeError::RenameDestinationExists { .. } => libc::EEXIST,
183 InodeError::RenameNotPermittedWhileWriting(_) => libc::EPERM,
184 InodeError::RenameNotSupported() => libc::ENOSYS,
185 InodeError::NameTooLong(_) => libc::ENAMETOOLONG,
186 #[cfg(feature = "manifest")]
187 InodeError::ManifestError { .. } => libc::EIO,
188 InodeError::OperationNotSupportedOnSyntheticInode { .. } => libc::EIO,
189 InodeError::OutOfOrderReadDir { .. } => libc::EBADF,
190 InodeError::NoSuchDirHandle { .. } => libc::EINVAL,
191 InodeError::FlexibleRetrievalObjectNotAccessible(_) => libc::EACCES,
192 }
193 }
194}
195
196impl<E: std::error::Error> ToErrno for UploadError<E> {
197 fn to_errno(&self) -> libc::c_int {
198 match self {
199 UploadError::PutRequestFailed(_) => libc::EIO,
200 UploadError::UploadAlreadyTerminated => libc::EIO,
201 UploadError::SseCorruptedError(_) => libc::EIO,
202 UploadError::ChecksumComputationFailed(_) => libc::EIO,
203 UploadError::HeadObjectFailed(_) => libc::EIO,
204 UploadError::OutOfOrderWrite { .. } => libc::EINVAL,
205 UploadError::ObjectTooBig { .. } => libc::EFBIG,
206 }
207 }
208}
209
210impl Error {
211 pub fn meta(&self) -> &ErrorMetadata {
212 &self.metadata
213 }
214}