1#[macro_use]
16extern crate log;
17#[macro_use]
18extern crate nydus_api;
19
20use std::fmt::{self, Display};
21use std::io;
22use std::str::FromStr;
23use std::sync::mpsc::{RecvError, SendError};
24
25use fuse_backend_rs::api::vfs::VfsError;
26use fuse_backend_rs::transport::Error as FuseTransportError;
27use fuse_backend_rs::Error as FuseError;
28use nydus_api::{ConfigV2, DaemonErrorKind};
29use nydus_rafs::RafsError;
30use serde::{Deserialize, Serialize};
31use serde_json::Error as SerdeError;
32use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
33use versionize_derive::Versionize;
34
35pub mod daemon;
36mod fs_service;
37mod fusedev;
38mod singleton;
39pub mod upgrade;
40
41pub use blob_cache::BlobCacheMgr;
42pub use fs_service::{FsBackendCollection, FsBackendMountCmd, FsBackendUmountCmd, FsService};
43pub use fusedev::{create_fuse_daemon, create_vfs_backend, FusedevDaemon};
44pub use singleton::create_daemon;
45
46#[cfg(target_os = "linux")]
47pub mod blob_cache;
48#[cfg(all(target_os = "linux", feature = "block-device"))]
49pub mod block_device;
50#[cfg(all(target_os = "linux", feature = "block-nbd"))]
51pub mod block_nbd;
52#[cfg(target_os = "linux")]
53mod fs_cache;
54
55#[cfg(target_os = "linux")]
56pub use fs_cache::FsCacheHandler;
57
58#[derive(thiserror::Error, Debug)]
60pub enum Error {
61 #[error("object or filesystem already exists")]
62 AlreadyExists,
63 #[error("invalid argument `{0}`")]
65 InvalidArguments(String),
66 #[error("invalid configuration, {0}")]
67 InvalidConfig(String),
68 #[error("invalid prefetch file list")]
69 InvalidPrefetchList,
70 #[error("object or filesystem doesn't exist")]
71 NotFound,
72 #[error("daemon is not ready yet")]
73 NotReady,
74 #[error("unsupported request or operation")]
75 Unsupported,
76 #[error("failed to serialize/deserialize message, {0}")]
77 Serde(SerdeError),
78 #[error("failed to spawn thread, {0}")]
79 ThreadSpawn(io::Error),
80 #[error("failed to send message to channel, {0}")]
81 ChannelSend(#[from] SendError<crate::daemon::DaemonStateMachineInput>),
82 #[error("failed to receive message from channel, {0}")]
83 ChannelReceive(#[from] RecvError),
84 #[error("failed to upgrade nydusd daemon, {0}")]
85 UpgradeManager(upgrade::UpgradeMgrError),
86 #[error("failed to start service, {0}")]
87 StartService(String),
88 #[error("unexpect state machine transition event `{0:?}`")]
90 UnexpectedEvent(crate::daemon::DaemonStateMachineInput),
91 #[error("failed to wait daemon, {0}")]
92 WaitDaemon(#[source] io::Error),
93
94 #[error("filesystem type mismatch, expect {0}")]
95 FsTypeMismatch(String),
96 #[error("passthroughfs failed to handle request, {0}")]
97 PassthroughFs(#[source] io::Error),
98 #[error("RAFS failed to handle request, {0}")]
99 Rafs(#[from] RafsError),
100 #[error("VFS failed to handle request, {0:?}")]
101 Vfs(#[from] VfsError),
102
103 #[error("failed to create FUSE server, {0}")]
105 CreateFuseServer(io::Error),
106 #[error("FUSE session has been shut down, {0}")]
108 SessionShutdown(FuseTransportError),
109 #[error("FUSE notify error, {0}")]
110 NotifyError(#[from] FuseNotifyError),
111 #[error("failed to walk and notify invalidation: {0}")]
112 WalkNotifyInvalidation(#[from] std::io::Error),
113
114 #[error("failed to handle event other than input event")]
116 HandleEventNotEpollIn,
117 #[error("failed to handle unknown event")]
118 HandleEventUnknownEvent,
119 #[error("fail to walk descriptor chain")]
120 IterateQueue,
121 #[error("invalid Virtio descriptor chain, {0}")]
122 InvalidDescriptorChain(FuseTransportError),
123 #[error("failed to process FUSE request, {0}")]
124 ProcessQueue(#[from] FuseError),
125 #[error("failed to create epoll context, {0}")]
126 Epoll(#[source] io::Error),
127 #[error("vhost-user failed to process request, {0}")]
128 VhostUser(String),
129 #[error("missing memory configuration for virtio queue")]
130 QueueMemoryUnset,
131}
132
133impl From<Error> for io::Error {
134 fn from(e: Error) -> Self {
135 einval!(e)
136 }
137}
138
139impl From<Error> for DaemonErrorKind {
140 fn from(e: Error) -> Self {
141 use Error::*;
142 match e {
143 UpgradeManager(e) => DaemonErrorKind::UpgradeManager(format!("{:?}", e)),
144 NotReady => DaemonErrorKind::NotReady,
145 Unsupported => DaemonErrorKind::Unsupported,
146 Serde(e) => DaemonErrorKind::Serde(e),
147 UnexpectedEvent(e) => DaemonErrorKind::UnexpectedEvent(format!("{:?}", e)),
148 o => DaemonErrorKind::Other(o.to_string()),
149 }
150 }
151}
152
153pub type Result<T> = std::result::Result<T, Error>;
155
156#[derive(thiserror::Error, Debug)]
157pub enum FuseNotifyError {
158 #[error("Session failure error, {0}")]
159 SessionFailure(#[from] FuseTransportError),
160 #[error("Fuse write error, {0}")]
161 FuseWriteError(#[source] FuseError),
162 #[error("Sysfs file open error, {0}")]
163 SysfsOpenError(#[source] io::Error),
164 #[error("Sysfs write error, {0}")]
165 SysfsWriteError(#[source] io::Error),
166}
167
168#[derive(Clone, Debug, Serialize, PartialEq, Deserialize, Versionize)]
170pub enum FsBackendType {
171 Rafs,
173 PassthroughFs,
175}
176
177impl FromStr for FsBackendType {
178 type Err = Error;
179
180 fn from_str(s: &str) -> Result<FsBackendType> {
181 match s {
182 "rafs" => Ok(FsBackendType::Rafs),
183 "passthrough" => Ok(FsBackendType::PassthroughFs),
184 "passthroughfs" => Ok(FsBackendType::PassthroughFs),
185 "passthrough_fs" => Ok(FsBackendType::PassthroughFs),
186 o => Err(Error::InvalidArguments(format!(
187 "only 'rafs' and 'passthrough_fs' are supported, but {} was specified",
188 o
189 ))),
190 }
191 }
192}
193
194impl Display for FsBackendType {
195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196 write!(f, "{:?}", self)
197 }
198}
199
200#[derive(Serialize, Clone, Deserialize)]
202pub struct FsBackendDescriptor {
203 pub backend_type: FsBackendType,
205 pub mountpoint: String,
207 pub mounted_time: time::OffsetDateTime,
209 pub config: Option<ConfigV2>,
211}
212
213pub fn validate_threads_configuration<V: AsRef<str>>(v: V) -> std::result::Result<usize, String> {
215 if let Ok(t) = v.as_ref().parse::<usize>() {
216 if t > 0 && t <= 1024 {
217 Ok(t)
218 } else {
219 Err(format!(
220 "invalid thread number {}, valid range: [1-1024]",
221 t
222 ))
223 }
224 } else {
225 Err(format!(
226 "invalid thread number configuration: {}",
227 v.as_ref()
228 ))
229 }
230}
231
232pub trait ServiceArgs {
234 fn value_of(&self, key: &str) -> Option<&String>;
236
237 fn is_present(&self, key: &str) -> bool;
239}
240
241#[cfg(not(target_os = "linux"))]
242mod blob_cache {
243 use super::*;
244
245 pub struct BlobCacheMgr {}
246
247 impl Default for BlobCacheMgr {
248 fn default() -> Self {
249 Self::new()
250 }
251 }
252
253 impl BlobCacheMgr {
254 pub fn new() -> Self {
255 BlobCacheMgr {}
256 }
257
258 pub fn add_blob_list(&self, _blobs: &nydus_api::BlobCacheList) -> io::Result<()> {
259 unimplemented!()
260 }
261
262 pub fn add_blob_entry(&self, _entry: &nydus_api::BlobCacheEntry) -> Result<()> {
263 unimplemented!()
264 }
265
266 pub fn remove_blob_entry(&self, _param: &nydus_api::BlobCacheObjectId) -> Result<()> {
267 unimplemented!()
268 }
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use super::*;
275
276 #[test]
277 fn test_backend_fs_type() {
278 assert_eq!(
279 FsBackendType::from_str("rafs").unwrap(),
280 FsBackendType::Rafs
281 );
282 assert_eq!(
283 FsBackendType::from_str("passthrough").unwrap(),
284 FsBackendType::PassthroughFs
285 );
286 assert_eq!(
287 FsBackendType::from_str("passthroughfs").unwrap(),
288 FsBackendType::PassthroughFs
289 );
290 assert_eq!(
291 FsBackendType::from_str("passthrough_fs").unwrap(),
292 FsBackendType::PassthroughFs
293 );
294 assert!(FsBackendType::from_str("passthroug").is_err());
295
296 assert_eq!(format!("{}", FsBackendType::Rafs), "Rafs");
297 assert_eq!(format!("{}", FsBackendType::PassthroughFs), "PassthroughFs");
298 }
299
300 #[test]
301 fn test_validate_thread_configuration() {
302 assert_eq!(validate_threads_configuration("1").unwrap(), 1);
303 assert_eq!(validate_threads_configuration("1024").unwrap(), 1024);
304 assert!(validate_threads_configuration("0").is_err());
305 assert!(validate_threads_configuration("-1").is_err());
306 assert!(validate_threads_configuration("1.0").is_err());
307 assert!(validate_threads_configuration("1025").is_err());
308 assert!(validate_threads_configuration("test").is_err());
309 }
310}