xref: /DragonOS/kernel/src/filesystem/overlayfs/mod.rs (revision 7b0ef10895108a0de5ff5ef3d2f93f40cf2e33a5)
1 #![allow(dead_code, unused_variables, unused_imports)]
2 pub mod copy_up;
3 pub mod entry;
4 
5 use super::ramfs::{LockedRamFSInode, RamFSInode};
6 use super::vfs::{self, FileSystem, FileType, FsInfo, IndexNode, Metadata, SuperBlock};
7 use super::vfs::{FSMAKER, ROOT_INODE};
8 use crate::driver::base::device::device_number::DeviceNumber;
9 use crate::driver::base::device::device_number::Major;
10 use crate::filesystem::vfs::{FileSystemMaker, FileSystemMakerData};
11 use crate::libs::spinlock::SpinLock;
12 use alloc::string::String;
13 use alloc::sync::Arc;
14 use alloc::sync::Weak;
15 use alloc::vec::Vec;
16 use entry::{OvlEntry, OvlLayer};
17 use system_error::SystemError;
18 
19 const WHITEOUT_MODE: u64 = 0o020000 | 0o600; // whiteout字符设备文件模式与权限
20 const WHITEOUT_DEV: DeviceNumber = DeviceNumber::new(Major::UNNAMED_MAJOR, 0); // Whiteout 文件设备号
21 const WHITEOUT_FLAG: u64 = 0x1;
22 
23 #[distributed_slice(FSMAKER)]
24 static OVERLAYFSMAKER: FileSystemMaker = FileSystemMaker::new(
25     "overlay",
26     &(OverlayFS::make_overlayfs
27         as fn(
28             Option<&dyn FileSystemMakerData>,
29         ) -> Result<Arc<dyn FileSystem + 'static>, SystemError>),
30 );
31 #[derive(Debug)]
32 pub struct OverlayMountData {
33     upper_dir: String,
34     lower_dirs: Vec<String>,
35     work_dir: String,
36 }
37 
38 impl OverlayMountData {
39     pub fn from_row(raw_data: *const u8) -> Result<Self, SystemError> {
40         if raw_data.is_null() {
41             return Err(SystemError::EINVAL);
42         }
43         let len = (0..)
44             .find(|&i| unsafe { raw_data.add(i).read() } == 0)
45             .ok_or(SystemError::EINVAL)?;
46         let slice = unsafe { core::slice::from_raw_parts(raw_data, len) };
47         let raw_str = core::str::from_utf8(slice).map_err(|_| SystemError::EINVAL)?;
48         let mut data = OverlayMountData {
49             upper_dir: String::new(),
50             lower_dirs: Vec::new(),
51             work_dir: String::new(),
52         };
53 
54         for pair in raw_str.split(',') {
55             let mut parts = pair.split('=');
56             let key = parts.next().ok_or(SystemError::EINVAL)?;
57             let value = parts.next().ok_or(SystemError::EINVAL)?;
58 
59             match key {
60                 "upperdir" => data.upper_dir = value.into(),
61                 "lowerdir" => data.lower_dirs = value.split(':').map(|s| s.into()).collect(),
62                 "workdir" => data.work_dir = value.into(),
63                 _ => return Err(SystemError::EINVAL),
64             }
65         }
66         Ok(data)
67     }
68 }
69 impl FileSystemMakerData for OverlayMountData {
70     fn as_any(&self) -> &dyn core::any::Any {
71         self
72     }
73 }
74 #[derive(Debug)]
75 pub struct OvlSuperBlock {
76     super_block: SuperBlock,
77     pseudo_dev: DeviceNumber, // 虚拟设备号
78     is_lower: bool,
79 }
80 
81 #[derive(Debug)]
82 struct OverlayFS {
83     numlayer: usize,
84     numfs: u32,
85     numdatalayer: usize,
86     layers: Vec<OvlLayer>, // 第0层为读写层,后面是只读层
87     workdir: Arc<OvlInode>,
88     root_inode: Arc<OvlInode>,
89 }
90 
91 #[derive(Debug)]
92 struct OvlInode {
93     redirect: String, // 重定向路径
94     file_type: FileType,
95     flags: SpinLock<u64>,
96     upper_inode: SpinLock<Option<Arc<dyn IndexNode>>>, // 读写层
97     lower_inode: Option<Arc<dyn IndexNode>>,           // 只读层
98     oe: Arc<OvlEntry>,
99     fs: Weak<OverlayFS>,
100 }
101 impl OvlInode {
102     pub fn new(
103         redirect: String,
104         upper: Option<Arc<dyn IndexNode>>,
105         lower_inode: Option<Arc<dyn IndexNode>>,
106     ) -> Self {
107         Self {
108             redirect,
109             file_type: FileType::Dir,
110             flags: SpinLock::new(0),
111             upper_inode: SpinLock::new(upper),
112             lower_inode,
113             oe: Arc::new(OvlEntry::new()),
114             fs: Weak::default(),
115         }
116     }
117 }
118 
119 impl FileSystem for OverlayFS {
120     fn root_inode(&self) -> Arc<dyn IndexNode> {
121         self.root_inode.clone()
122     }
123 
124     fn info(&self) -> vfs::FsInfo {
125         FsInfo {
126             blk_dev_id: 0,
127             max_name_len: 255,
128         }
129     }
130 
131     fn as_any_ref(&self) -> &dyn core::any::Any {
132         self
133     }
134 
135     fn name(&self) -> &str {
136         "overlayfs"
137     }
138 
139     fn super_block(&self) -> SuperBlock {
140         todo!()
141     }
142 }
143 
144 impl OverlayFS {
145     pub fn ovl_upper_mnt(&self) -> Arc<dyn IndexNode> {
146         self.layers[0].mnt.clone()
147     }
148     pub fn make_overlayfs(
149         data: Option<&dyn FileSystemMakerData>,
150     ) -> Result<Arc<dyn FileSystem + 'static>, SystemError> {
151         let mount_data = data
152             .and_then(|d| d.as_any().downcast_ref::<OverlayMountData>())
153             .ok_or(SystemError::EINVAL)?;
154 
155         let upper_inode = ROOT_INODE()
156             .lookup(&mount_data.upper_dir)
157             .map_err(|_| SystemError::EINVAL)?;
158         let upper_layer = OvlLayer {
159             mnt: Arc::new(OvlInode::new(
160                 mount_data.upper_dir.clone(),
161                 Some(upper_inode),
162                 None,
163             )),
164             index: 0,
165             fsid: 0,
166         };
167 
168         let lower_layers: Result<Vec<OvlLayer>, SystemError> = mount_data
169             .lower_dirs
170             .iter()
171             .enumerate()
172             .map(|(i, dir)| {
173                 let lower_inode = ROOT_INODE().lookup(dir).map_err(|_| SystemError::EINVAL)?; // 处理错误
174                 Ok(OvlLayer {
175                     mnt: Arc::new(OvlInode::new(dir.clone(), None, Some(lower_inode))),
176                     index: (i + 1) as u32,
177                     fsid: (i + 1) as u32,
178                 })
179             })
180             .collect();
181 
182         let lower_layers = lower_layers?;
183 
184         let workdir = Arc::new(OvlInode::new(mount_data.work_dir.clone(), None, None));
185 
186         if lower_layers.is_empty() {
187             return Err(SystemError::EINVAL);
188         }
189 
190         let mut layers = Vec::new();
191         layers.push(upper_layer);
192         layers.extend(lower_layers);
193 
194         let root_inode = layers[0].mnt.clone();
195 
196         let fs = OverlayFS {
197             numlayer: layers.len(),
198             numfs: 1,
199             numdatalayer: layers.len() - 1,
200             layers,
201             workdir,
202             root_inode,
203         };
204         Ok(Arc::new(fs))
205     }
206 }
207 
208 impl OvlInode {
209     pub fn ovl_lower_redirect(&self) -> Option<&str> {
210         if self.file_type == FileType::File || self.file_type == FileType::Dir {
211             Some(&self.redirect)
212         } else {
213             None
214         }
215     }
216 
217     pub fn create_whiteout(&self, name: &str) -> Result<(), SystemError> {
218         let whiteout_mode = vfs::syscall::ModeType::S_IFCHR;
219         let mut upper_inode = self.upper_inode.lock();
220         if let Some(ref upper_inode) = *upper_inode {
221             upper_inode.mknod(name, whiteout_mode, WHITEOUT_DEV)?;
222         } else {
223             let new_inode = self
224                 .fs
225                 .upgrade()
226                 .ok_or(SystemError::EROFS)?
227                 .root_inode()
228                 .create(name, FileType::CharDevice, whiteout_mode)?;
229             *upper_inode = Some(new_inode);
230         }
231         let mut flags = self.flags.lock();
232         *flags |= WHITEOUT_FLAG; // 标记为 whiteout
233         Ok(())
234     }
235 
236     fn is_whiteout(&self) -> bool {
237         let flags = self.flags.lock();
238         self.file_type == FileType::CharDevice && (*flags & WHITEOUT_FLAG) != 0
239     }
240 
241     fn has_whiteout(&self, name: &str) -> bool {
242         let upper_inode = self.upper_inode.lock();
243         if let Some(ref upper_inode) = *upper_inode {
244             if let Ok(inode) = upper_inode.find(name) {
245                 if let Some(ovl_inode) = inode.as_any_ref().downcast_ref::<OvlInode>() {
246                     return ovl_inode.is_whiteout();
247                 }
248             }
249         }
250         false
251     }
252 }
253 
254 impl IndexNode for OvlInode {
255     fn read_at(
256         &self,
257         offset: usize,
258         len: usize,
259         buf: &mut [u8],
260         data: crate::libs::spinlock::SpinLockGuard<vfs::FilePrivateData>,
261     ) -> Result<usize, system_error::SystemError> {
262         if let Some(ref upper_inode) = *self.upper_inode.lock() {
263             return upper_inode.read_at(offset, len, buf, data);
264         }
265 
266         if let Some(lower_inode) = &self.lower_inode {
267             return lower_inode.read_at(offset, len, buf, data);
268         }
269 
270         Err(SystemError::ENOENT)
271     }
272 
273     fn write_at(
274         &self,
275         offset: usize,
276         len: usize,
277         buf: &[u8],
278         data: crate::libs::spinlock::SpinLockGuard<vfs::FilePrivateData>,
279     ) -> Result<usize, SystemError> {
280         if (*self.upper_inode.lock()).is_none() {
281             self.copy_up()?;
282         }
283         if let Some(ref upper_inode) = *self.upper_inode.lock() {
284             return upper_inode.write_at(offset, len, buf, data);
285         }
286 
287         Err(SystemError::EROFS)
288     }
289 
290     fn fs(&self) -> Arc<dyn FileSystem> {
291         self.fs.upgrade().unwrap()
292     }
293 
294     fn metadata(&self) -> Result<Metadata, SystemError> {
295         if let Some(ref upper_inode) = *self.upper_inode.lock() {
296             return upper_inode.metadata();
297         }
298 
299         if let Some(ref lower_inode) = self.lower_inode {
300             return lower_inode.metadata();
301         }
302         Ok(Metadata::default())
303     }
304 
305     fn as_any_ref(&self) -> &dyn core::any::Any {
306         self
307     }
308 
309     fn list(&self) -> Result<Vec<String>, system_error::SystemError> {
310         let mut entries: Vec<String> = Vec::new();
311         let upper_inode = self.upper_inode.lock();
312         if let Some(ref upper_inode) = *upper_inode {
313             let upper_entries = upper_inode.list()?;
314             entries.extend(upper_entries);
315         }
316         if let Some(lower_inode) = &self.lower_inode {
317             let lower_entries = lower_inode.list()?;
318             for entry in lower_entries {
319                 if !entries.contains(&entry) && !self.has_whiteout(&entry) {
320                     entries.push(entry);
321                 }
322             }
323         }
324 
325         Ok(entries)
326     }
327 
328     fn mkdir(
329         &self,
330         name: &str,
331         mode: vfs::syscall::ModeType,
332     ) -> Result<Arc<dyn IndexNode>, system_error::SystemError> {
333         if let Some(ref upper_inode) = *self.upper_inode.lock() {
334             upper_inode.mkdir(name, mode)
335         } else {
336             Err(SystemError::EROFS)
337         }
338     }
339 
340     fn rmdir(&self, name: &str) -> Result<(), SystemError> {
341         let upper_inode = self.upper_inode.lock();
342         if let Some(ref upper_inode) = *upper_inode {
343             upper_inode.rmdir(name)?;
344         } else if let Some(lower_inode) = &self.lower_inode {
345             if lower_inode.find(name).is_ok() {
346                 self.create_whiteout(name)?;
347             } else {
348                 return Err(SystemError::ENOENT);
349             }
350         } else {
351             return Err(SystemError::ENOENT);
352         }
353 
354         Ok(())
355     }
356 
357     fn unlink(&self, name: &str) -> Result<(), SystemError> {
358         let upper_inode = self.upper_inode.lock();
359         if let Some(ref upper_inode) = *upper_inode {
360             upper_inode.unlink(name)?;
361         } else if let Some(lower_inode) = &self.lower_inode {
362             if lower_inode.find(name).is_ok() {
363                 self.create_whiteout(name)?;
364             } else {
365                 return Err(SystemError::ENOENT);
366             }
367         } else {
368             return Err(SystemError::ENOENT);
369         }
370 
371         Ok(())
372     }
373 
374     fn link(
375         &self,
376         name: &str,
377         other: &Arc<dyn IndexNode>,
378     ) -> Result<(), system_error::SystemError> {
379         if let Some(ref upper_inode) = *self.upper_inode.lock() {
380             upper_inode.link(name, other)
381         } else {
382             Err(SystemError::EROFS)
383         }
384     }
385 
386     fn create(
387         &self,
388         name: &str,
389         file_type: vfs::FileType,
390         mode: vfs::syscall::ModeType,
391     ) -> Result<Arc<dyn IndexNode>, system_error::SystemError> {
392         if let Some(ref upper_inode) = *self.upper_inode.lock() {
393             upper_inode.create(name, file_type, mode)
394         } else {
395             Err(SystemError::EROFS)
396         }
397     }
398 
399     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, system_error::SystemError> {
400         let upper_inode = self.upper_inode.lock();
401         if let Some(ref upper) = *upper_inode {
402             if let Ok(inode) = upper.find(name) {
403                 return Ok(inode);
404             }
405         }
406         if self.has_whiteout(name) {
407             return Err(SystemError::ENOENT);
408         }
409 
410         if let Some(lower) = &self.lower_inode {
411             if let Ok(inode) = lower.find(name) {
412                 return Ok(inode);
413             }
414         }
415 
416         Err(SystemError::ENOENT)
417     }
418 
419     fn mknod(
420         &self,
421         filename: &str,
422         mode: vfs::syscall::ModeType,
423         dev_t: crate::driver::base::device::device_number::DeviceNumber,
424     ) -> Result<Arc<dyn IndexNode>, system_error::SystemError> {
425         let upper_inode = self.upper_inode.lock();
426         if let Some(ref inode) = *upper_inode {
427             inode.mknod(filename, mode, dev_t)
428         } else {
429             Err(SystemError::EROFS)
430         }
431     }
432 }
433