mount.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. use super::{
  2. dentry::{dcache, Dentry, DROOT},
  3. inode::Inode,
  4. vfs::Vfs,
  5. };
  6. use crate::kernel::constants::{EEXIST, ENODEV, ENOTDIR};
  7. use crate::prelude::*;
  8. use alloc::{collections::btree_map::BTreeMap, string::ToString as _, sync::Arc};
  9. use eonix_sync::LazyLock;
  10. pub const MS_RDONLY: u64 = 1 << 0;
  11. pub const MS_NOSUID: u64 = 1 << 1;
  12. pub const MS_NODEV: u64 = 1 << 2;
  13. pub const MS_NOEXEC: u64 = 1 << 3;
  14. pub const MS_NOATIME: u64 = 1 << 10;
  15. pub const MS_RELATIME: u64 = 1 << 21;
  16. pub const MS_STRICTATIME: u64 = 1 << 24;
  17. pub const MS_LAZYTIME: u64 = 1 << 25;
  18. const MOUNT_FLAGS: [(u64, &str); 6] = [
  19. (MS_NOSUID, ",nosuid"),
  20. (MS_NODEV, ",nodev"),
  21. (MS_NOEXEC, ",noexec"),
  22. (MS_NOATIME, ",noatime"),
  23. (MS_RELATIME, ",relatime"),
  24. (MS_LAZYTIME, ",lazytime"),
  25. ];
  26. static MOUNT_CREATORS: Spin<BTreeMap<String, Arc<dyn MountCreator>>> = Spin::new(BTreeMap::new());
  27. static MOUNTS: Spin<Vec<(Arc<Dentry>, MountPointData)>> = Spin::new(vec![]);
  28. pub struct Mount {
  29. _vfs: Arc<dyn Vfs>,
  30. root: Arc<Dentry>,
  31. }
  32. impl Mount {
  33. pub fn new(mp: &Dentry, vfs: Arc<dyn Vfs>, root_inode: Arc<dyn Inode>) -> KResult<Self> {
  34. let root_dentry = Dentry::create(mp.parent().clone(), &mp.get_name());
  35. root_dentry.save_dir(root_inode)?;
  36. Ok(Self {
  37. _vfs: vfs,
  38. root: root_dentry,
  39. })
  40. }
  41. pub fn root(&self) -> &Arc<Dentry> {
  42. &self.root
  43. }
  44. }
  45. unsafe impl Send for Mount {}
  46. unsafe impl Sync for Mount {}
  47. pub trait MountCreator: Send + Sync {
  48. fn check_signature(&self, first_block: &[u8]) -> KResult<bool>;
  49. fn create_mount(&self, source: &str, flags: u64, mp: &Arc<Dentry>) -> KResult<Mount>;
  50. }
  51. pub fn register_filesystem(fstype: &str, creator: Arc<dyn MountCreator>) -> KResult<()> {
  52. let mut creators = MOUNT_CREATORS.lock();
  53. if !creators.contains_key(fstype) {
  54. creators.insert(fstype.to_string(), creator);
  55. Ok(())
  56. } else {
  57. Err(EEXIST)
  58. }
  59. }
  60. #[allow(dead_code)]
  61. struct MountPointData {
  62. mount: Mount,
  63. source: String,
  64. mountpoint: String,
  65. fstype: String,
  66. flags: u64,
  67. }
  68. pub fn do_mount(
  69. mountpoint: &Arc<Dentry>,
  70. source: &str,
  71. mountpoint_str: &str,
  72. fstype: &str,
  73. flags: u64,
  74. ) -> KResult<()> {
  75. let mut flags = flags;
  76. if flags & MS_NOATIME == 0 {
  77. flags |= MS_RELATIME;
  78. }
  79. if flags & MS_STRICTATIME != 0 {
  80. flags &= !(MS_RELATIME | MS_NOATIME);
  81. }
  82. if !mountpoint.is_directory() {
  83. return Err(ENOTDIR);
  84. }
  85. let creator = {
  86. let creators = { MOUNT_CREATORS.lock() };
  87. creators.get(fstype).ok_or(ENODEV)?.clone()
  88. };
  89. let mount = creator.create_mount(source, flags, mountpoint)?;
  90. let root_dentry = mount.root().clone();
  91. let mpdata = MountPointData {
  92. mount,
  93. source: String::from(source),
  94. mountpoint: String::from(mountpoint_str),
  95. fstype: String::from(fstype),
  96. flags,
  97. };
  98. {
  99. let mut mounts = MOUNTS.lock();
  100. dcache::d_replace(mountpoint, root_dentry);
  101. mounts.push((mountpoint.clone(), mpdata));
  102. }
  103. Ok(())
  104. }
  105. fn mount_opts(flags: u64) -> String {
  106. let mut out = String::new();
  107. if flags & MS_RDONLY != 0 {
  108. out += "ro";
  109. } else {
  110. out += "rw";
  111. }
  112. for (flag, name) in MOUNT_FLAGS {
  113. if flags & flag != 0 {
  114. out += name;
  115. }
  116. }
  117. out
  118. }
  119. pub fn dump_mounts(buffer: &mut dyn core::fmt::Write) {
  120. for (_, mpdata) in MOUNTS.lock().iter() {
  121. dont_check!(writeln!(
  122. buffer,
  123. "{} {} {} {} 0 0",
  124. mpdata.source,
  125. mpdata.mountpoint,
  126. mpdata.fstype,
  127. mount_opts(mpdata.flags)
  128. ))
  129. }
  130. }
  131. impl Dentry {
  132. pub fn root() -> &'static Arc<Dentry> {
  133. static ROOT: LazyLock<Arc<Dentry>> = LazyLock::new(|| {
  134. let source = String::from("(rootfs)");
  135. let fstype = String::from("tmpfs");
  136. let mount_flags = MS_NOATIME;
  137. let creator = MOUNT_CREATORS
  138. .lock()
  139. .get(&fstype)
  140. .cloned()
  141. .expect("tmpfs not registered.");
  142. let mount = creator
  143. .create_mount(&source, mount_flags, &DROOT)
  144. .expect("Failed to create root mount.");
  145. let root_dentry = mount.root().clone();
  146. dcache::d_add(root_dentry.clone());
  147. MOUNTS.lock().push((
  148. DROOT.clone(),
  149. MountPointData {
  150. mount,
  151. source,
  152. mountpoint: String::from("/"),
  153. fstype,
  154. flags: mount_flags,
  155. },
  156. ));
  157. root_dentry
  158. });
  159. &ROOT
  160. }
  161. }