procfs.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. use alloc::{
  2. collections::btree_map::BTreeMap,
  3. sync::{Arc, Weak},
  4. };
  5. use bindings::{EACCES, ENOTDIR, S_IFDIR, S_IFREG};
  6. use core::{ops::ControlFlow, sync::atomic::Ordering};
  7. use itertools::Itertools;
  8. use lazy_static::lazy_static;
  9. use crate::{
  10. io::Buffer,
  11. kernel::{
  12. mem::paging::{Page, PageBuffer},
  13. vfs::{
  14. dentry::Dentry,
  15. inode::{define_struct_inode, AtomicIno, Ino, Inode, InodeData},
  16. mount::{dump_mounts, register_filesystem, Mount, MountCreator},
  17. vfs::Vfs,
  18. DevId,
  19. },
  20. },
  21. prelude::*,
  22. sync::Locked,
  23. };
  24. fn split_len_offset(data: &[u8], len: usize, offset: usize) -> Option<&[u8]> {
  25. let real_data = data.split_at_checked(len).map(|(data, _)| data)?;
  26. real_data.split_at_checked(offset).map(|(_, data)| data)
  27. }
  28. pub trait ProcFsFile: Send + Sync {
  29. fn can_read(&self) -> bool {
  30. false
  31. }
  32. fn can_write(&self) -> bool {
  33. false
  34. }
  35. fn read(&self, _buffer: &mut PageBuffer) -> KResult<usize> {
  36. Err(EACCES)
  37. }
  38. fn write(&self, _buffer: &[u8]) -> KResult<usize> {
  39. Err(EACCES)
  40. }
  41. }
  42. pub enum ProcFsNode {
  43. File(Arc<FileInode>),
  44. Dir(Arc<DirInode>),
  45. }
  46. impl ProcFsNode {
  47. fn unwrap(&self) -> Arc<dyn Inode> {
  48. match self {
  49. ProcFsNode::File(inode) => inode.clone(),
  50. ProcFsNode::Dir(inode) => inode.clone(),
  51. }
  52. }
  53. fn ino(&self) -> Ino {
  54. match self {
  55. ProcFsNode::File(inode) => inode.ino,
  56. ProcFsNode::Dir(inode) => inode.ino,
  57. }
  58. }
  59. }
  60. define_struct_inode! {
  61. pub struct FileInode {
  62. file: Box<dyn ProcFsFile>,
  63. }
  64. }
  65. impl FileInode {
  66. pub fn new(ino: Ino, vfs: Weak<ProcFs>, file: Box<dyn ProcFsFile>) -> Arc<Self> {
  67. let mut mode = S_IFREG;
  68. if file.can_read() {
  69. mode |= 0o444;
  70. }
  71. if file.can_write() {
  72. mode |= 0o200;
  73. }
  74. let inode = Self {
  75. idata: InodeData::new(ino, vfs),
  76. file,
  77. };
  78. inode.idata.mode.store(mode, Ordering::Relaxed);
  79. inode.idata.nlink.store(1, Ordering::Relaxed);
  80. Arc::new(inode)
  81. }
  82. }
  83. impl Inode for FileInode {
  84. fn read(&self, buffer: &mut dyn Buffer, offset: usize) -> KResult<usize> {
  85. if !self.file.can_read() {
  86. return Err(EACCES);
  87. }
  88. let mut page_buffer = PageBuffer::new(Page::alloc_one());
  89. let nread = self.file.read(&mut page_buffer)?;
  90. let data = split_len_offset(page_buffer.as_slice(), nread, offset);
  91. match data {
  92. None => Ok(0),
  93. Some(data) => Ok(buffer.fill(data)?.allow_partial()),
  94. }
  95. }
  96. }
  97. define_struct_inode! {
  98. struct DirInode {
  99. entries: Locked<Vec<(Arc<[u8]>, ProcFsNode)>, ()>,
  100. }
  101. }
  102. impl DirInode {
  103. pub fn new(ino: Ino, vfs: Weak<ProcFs>) -> Arc<Self> {
  104. Self::new_locked(ino, vfs, |inode, rwsem| unsafe {
  105. addr_of_mut_field!(inode, entries).write(Locked::new(vec![], rwsem));
  106. addr_of_mut_field!(inode, mode).write((S_IFDIR | 0o755).into());
  107. addr_of_mut_field!(inode, nlink).write(1.into());
  108. })
  109. }
  110. }
  111. impl Inode for DirInode {
  112. fn lookup(&self, dentry: &Arc<Dentry>) -> KResult<Option<Arc<dyn Inode>>> {
  113. let lock = self.rwsem.lock_shared();
  114. Ok(self
  115. .entries
  116. .access(lock.as_ref())
  117. .iter()
  118. .find_map(|(name, node)| {
  119. name.as_ref()
  120. .eq(dentry.name().as_ref())
  121. .then(|| node.unwrap())
  122. }))
  123. }
  124. fn do_readdir(
  125. &self,
  126. offset: usize,
  127. callback: &mut dyn FnMut(&[u8], Ino) -> KResult<ControlFlow<(), ()>>,
  128. ) -> KResult<usize> {
  129. let lock = self.rwsem.lock_shared();
  130. self.entries
  131. .access(lock.as_ref())
  132. .iter()
  133. .skip(offset)
  134. .map(|(name, node)| callback(name.as_ref(), node.ino()))
  135. .take_while(|result| result.map_or(true, |flow| flow.is_continue()))
  136. .take_while_inclusive(|result| result.is_ok())
  137. .fold_ok(0, |acc, _| acc + 1)
  138. }
  139. }
  140. impl_any!(ProcFs);
  141. pub struct ProcFs {
  142. root_node: Arc<DirInode>,
  143. next_ino: AtomicIno,
  144. }
  145. impl Vfs for ProcFs {
  146. fn io_blksize(&self) -> usize {
  147. 4096
  148. }
  149. fn fs_devid(&self) -> DevId {
  150. 10
  151. }
  152. fn is_read_only(&self) -> bool {
  153. false
  154. }
  155. }
  156. lazy_static! {
  157. static ref ICACHE: Spin<BTreeMap<Ino, ProcFsNode>> = Spin::new(BTreeMap::new());
  158. static ref GLOBAL_PROCFS: Arc<ProcFs> = {
  159. let fs: Arc<ProcFs> = Arc::new_cyclic(|weak: &Weak<ProcFs>| ProcFs {
  160. root_node: DirInode::new(0, weak.clone()),
  161. next_ino: AtomicIno::new(1),
  162. });
  163. fs
  164. };
  165. }
  166. struct ProcFsMountCreator;
  167. impl ProcFsMountCreator {
  168. pub fn get() -> Arc<ProcFs> {
  169. GLOBAL_PROCFS.clone()
  170. }
  171. pub fn get_weak() -> Weak<ProcFs> {
  172. Arc::downgrade(&GLOBAL_PROCFS)
  173. }
  174. }
  175. impl MountCreator for ProcFsMountCreator {
  176. fn create_mount(&self, _source: &str, _flags: u64, mp: &Arc<Dentry>) -> KResult<Mount> {
  177. let vfs = ProcFsMountCreator::get();
  178. let root_inode = vfs.root_node.clone();
  179. Mount::new(mp, vfs, root_inode)
  180. }
  181. }
  182. pub fn root() -> ProcFsNode {
  183. let vfs = ProcFsMountCreator::get();
  184. let root = vfs.root_node.clone();
  185. ProcFsNode::Dir(root)
  186. }
  187. pub fn creat(
  188. parent: &ProcFsNode,
  189. name: Arc<[u8]>,
  190. file: Box<dyn ProcFsFile>,
  191. ) -> KResult<ProcFsNode> {
  192. let parent = match parent {
  193. ProcFsNode::File(_) => return Err(ENOTDIR),
  194. ProcFsNode::Dir(parent) => parent,
  195. };
  196. let fs = ProcFsMountCreator::get();
  197. let ino = fs.next_ino.fetch_add(1, Ordering::Relaxed);
  198. let inode = FileInode::new(ino, Arc::downgrade(&fs), file);
  199. {
  200. let mut lock = parent.idata.rwsem.lock();
  201. parent
  202. .entries
  203. .access_mut(lock.as_mut())
  204. .push((name, ProcFsNode::File(inode.clone())));
  205. }
  206. Ok(ProcFsNode::File(inode))
  207. }
  208. pub fn mkdir(parent: &ProcFsNode, name: &[u8]) -> KResult<ProcFsNode> {
  209. let parent = match parent {
  210. ProcFsNode::File(_) => return Err(ENOTDIR),
  211. ProcFsNode::Dir(parent) => parent,
  212. };
  213. let fs = ProcFsMountCreator::get();
  214. let ino = fs.next_ino.fetch_add(1, Ordering::Relaxed);
  215. let inode = DirInode::new(ino, Arc::downgrade(&fs));
  216. parent
  217. .entries
  218. .access_mut(inode.rwsem.lock().as_mut())
  219. .push((Arc::from(name), ProcFsNode::Dir(inode.clone())));
  220. Ok(ProcFsNode::Dir(inode))
  221. }
  222. struct DumpMountsFile;
  223. impl ProcFsFile for DumpMountsFile {
  224. fn can_read(&self) -> bool {
  225. true
  226. }
  227. fn read(&self, buffer: &mut PageBuffer) -> KResult<usize> {
  228. dump_mounts(buffer);
  229. Ok(buffer.len())
  230. }
  231. }
  232. pub fn init() {
  233. register_filesystem("procfs", Arc::new(ProcFsMountCreator)).unwrap();
  234. creat(
  235. &root(),
  236. Arc::from(b"mounts".as_slice()),
  237. Box::new(DumpMountsFile),
  238. )
  239. .unwrap();
  240. }
  241. pub struct GenericProcFsFile<ReadFn>
  242. where
  243. ReadFn: Send + Sync + Fn(&mut PageBuffer) -> KResult<()>,
  244. {
  245. read_fn: Option<ReadFn>,
  246. }
  247. impl<ReadFn> ProcFsFile for GenericProcFsFile<ReadFn>
  248. where
  249. ReadFn: Send + Sync + Fn(&mut PageBuffer) -> KResult<()>,
  250. {
  251. fn can_read(&self) -> bool {
  252. self.read_fn.is_some()
  253. }
  254. fn read(&self, buffer: &mut PageBuffer) -> KResult<usize> {
  255. self.read_fn.as_ref().ok_or(EACCES)?(buffer).map(|_| buffer.len())
  256. }
  257. }
  258. pub fn populate_root<F>(name: Arc<[u8]>, read_fn: F) -> KResult<()>
  259. where
  260. F: Send + Sync + Fn(&mut PageBuffer) -> KResult<()> + 'static,
  261. {
  262. let root = root();
  263. creat(
  264. &root,
  265. name,
  266. Box::new(GenericProcFsFile {
  267. read_fn: Some(read_fn),
  268. }),
  269. )
  270. .map(|_| ())
  271. }