ext4.rs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. use core::sync::atomic::Ordering;
  2. use alloc::{collections::btree_map::BTreeMap, sync::{Arc, Weak}};
  3. use ext4_rs::{Ext4, InodeFileType};
  4. use ext4_rs::BlockDevice as Ext4BlockDeviceTrait;
  5. use crate::{
  6. io::{Buffer, ByteBuffer},
  7. kernel::{
  8. block::{make_device, BlockDevice},
  9. constants::{EIO, S_IFDIR, S_IFREG},
  10. vfs::{
  11. dentry::Dentry,
  12. inode::{define_struct_inode, Ino, Inode, InodeData},
  13. mount::{register_filesystem, Mount, MountCreator},
  14. vfs::Vfs,
  15. DevId,
  16. },
  17. }, prelude::*
  18. };
  19. pub struct Ext4BlockDevice {
  20. device: Arc<BlockDevice>,
  21. }
  22. impl Ext4BlockDevice {
  23. pub fn new(device: Arc<BlockDevice>) -> Self {
  24. Self {
  25. device,
  26. }
  27. }
  28. }
  29. impl Ext4BlockDeviceTrait for Ext4BlockDevice {
  30. fn read_offset(&self, offset: usize) -> Vec<u8> {
  31. let mut buffer = vec![0u8; 4096];
  32. let mut byte_buffer = ByteBuffer::new(buffer.as_mut_slice());
  33. match self.device.read_some(offset, &mut byte_buffer) {
  34. Ok(fill_result) => {
  35. buffer
  36. }
  37. Err(_) => {
  38. vec![0u8; 4096]
  39. }
  40. }
  41. }
  42. fn write_offset(&self, offset: usize, data: &[u8]) {
  43. todo!()
  44. }
  45. }
  46. impl_any!(Ext4Fs);
  47. struct Ext4Fs {
  48. inner: Ext4,
  49. device: Arc<BlockDevice>,
  50. icache: BTreeMap<Ino, Ext4Inode>,
  51. weak: Weak<Ext4Fs>,
  52. }
  53. impl Vfs for Ext4Fs {
  54. fn io_blksize(&self) -> usize {
  55. 4096
  56. }
  57. fn fs_devid(&self) -> DevId {
  58. self.device.devid()
  59. }
  60. fn is_read_only(&self) -> bool {
  61. true
  62. }
  63. }
  64. impl Ext4Fs {
  65. fn get_or_alloc_inode(&self, ino: Ino, is_directory: bool, size: u32) -> Arc<dyn Inode> {
  66. self.icache
  67. .get(&ino)
  68. .cloned()
  69. .map(Ext4Inode::unwrap)
  70. .unwrap_or_else(|| {
  71. if is_directory {
  72. DirInode::new(ino, self.weak.clone(), size)
  73. } else {
  74. FileInode::new(ino, self.weak.clone(), size)
  75. }
  76. })
  77. }
  78. }
  79. impl Ext4Fs {
  80. pub fn create(device: DevId) -> KResult<(Arc<Self>, Arc<dyn Inode>)> {
  81. let device = BlockDevice::get(device)?;
  82. let ext4_device = Ext4BlockDevice::new(device.clone());
  83. let ext4 = Ext4::open(Arc::new(ext4_device));
  84. let mut ext4fs = Arc::new_cyclic(|weak: &Weak<Ext4Fs>| Self {
  85. inner: ext4,
  86. device,
  87. icache: BTreeMap::new(),
  88. weak: weak.clone(),
  89. });
  90. let root_inode_ref = ext4fs.inner.get_inode_ref(2);
  91. let root_inode = DirInode::new(root_inode_ref.inode_num as Ino, ext4fs.weak.clone(), root_inode_ref.inode.size() as u32);
  92. Ok((ext4fs, root_inode))
  93. }
  94. }
  95. #[allow(dead_code)]
  96. #[derive(Clone)]
  97. enum Ext4Inode {
  98. File(Arc<FileInode>),
  99. Dir(Arc<DirInode>),
  100. }
  101. impl Ext4Inode {
  102. fn unwrap(self) -> Arc<dyn Inode> {
  103. match self {
  104. Ext4Inode::File(inode) => inode,
  105. Ext4Inode::Dir(inode) => inode,
  106. }
  107. }
  108. }
  109. define_struct_inode! {
  110. struct FileInode;
  111. }
  112. impl FileInode {
  113. pub fn new(ino: Ino, weak: Weak<dyn Vfs>, size: u32) -> Arc<Self> {
  114. let inode = Arc::new(Self {
  115. idata: InodeData::new(ino, weak),
  116. });
  117. inode.nlink.store(1, Ordering::Relaxed);
  118. inode.mode.store(S_IFREG | 0o644, Ordering::Relaxed);
  119. inode.size.store(size as u64, Ordering::Relaxed);
  120. inode
  121. }
  122. }
  123. impl Inode for FileInode {
  124. fn read(&self, buffer: &mut dyn Buffer, offset: usize) -> KResult<usize> {
  125. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  126. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  127. let mut temp_buf = vec![0u8; buffer.total()];
  128. match ext4fs.inner.read_at(self.ino.try_into().unwrap(), offset, &mut temp_buf) {
  129. Ok(bytes_read) => {
  130. buffer.fill(&temp_buf[..bytes_read]).map_err(|_| EIO)?;
  131. Ok(bytes_read)
  132. }
  133. Err(e) => Err(e.error() as u32),
  134. }
  135. }
  136. }
  137. define_struct_inode! {
  138. struct DirInode;
  139. }
  140. impl DirInode {
  141. pub fn new(ino: Ino, weak: Weak<dyn Vfs>, size: u32) -> Arc<Self> {
  142. let inode = Arc::new(Self {
  143. idata: InodeData::new(ino, weak),
  144. });
  145. inode.nlink.store(2, Ordering::Relaxed);
  146. inode.mode.store(S_IFDIR | 0o644, Ordering::Relaxed);
  147. inode.size.store(size as u64, Ordering::Relaxed);
  148. inode
  149. }
  150. }
  151. impl Inode for DirInode {
  152. fn lookup(&self, dentry: &Arc<Dentry>) -> KResult<Option<Arc<dyn Inode>>> {
  153. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  154. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  155. let name = str::from_utf8(&**dentry.name()).unwrap();
  156. match ext4fs.inner.fuse_lookup(self.ino, name) {
  157. Ok(attr) => {
  158. let new_ino = attr.ino as Ino;
  159. let is_dir = attr.kind == InodeFileType::S_IFDIR;
  160. let size = attr.size;
  161. let inode = ext4fs.get_or_alloc_inode(new_ino, is_dir, size as u32);
  162. Ok(Some(inode))
  163. }
  164. Err(e) => Err(e.error() as u32),
  165. }
  166. }
  167. fn do_readdir(
  168. &self,
  169. offset: usize,
  170. callback: &mut dyn FnMut(&[u8], Ino) -> KResult<core::ops::ControlFlow<(), ()>>,
  171. ) -> KResult<usize> {
  172. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  173. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  174. let entries = ext4fs.inner.fuse_readdir(self.ino as u64, 0, offset as i64)
  175. .map_err(|_| EIO)?;
  176. let mut current_offset = 0;
  177. for entry in entries {
  178. let name_len = entry.name_len as usize;
  179. let name = &entry.name[..name_len];
  180. let ino = entry.inode as Ino;
  181. let inode_ref = ext4fs.inner.get_inode_ref(entry.inode);
  182. let is_dir = inode_ref.inode.is_dir();
  183. let size = inode_ref.inode.size();
  184. ext4fs.get_or_alloc_inode(ino, is_dir, size as u32);
  185. if callback(name, ino)?.is_break() {
  186. break;
  187. }
  188. current_offset += 1;
  189. }
  190. Ok(current_offset)
  191. }
  192. }
  193. struct Ext4MountCreator;
  194. impl MountCreator for Ext4MountCreator {
  195. fn create_mount(&self, _source: &str, _flags: u64, mp: &Arc<Dentry>) -> KResult<Mount> {
  196. // TODO: temporarily the second disk, should generate from _source
  197. let (ext4fs, root_inode) =
  198. Ext4Fs::create(make_device(8, 0))?;
  199. Mount::new(mp, ext4fs, root_inode)
  200. }
  201. }
  202. pub fn init() {
  203. register_filesystem("ext4", Arc::new(Ext4MountCreator)).unwrap();
  204. }