ext4.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. use core::sync::atomic::{AtomicU32, AtomicU64, Ordering};
  2. use crate::kernel::mem::{PageCache, PageCacheBackend};
  3. use crate::{
  4. io::{Buffer, ByteBuffer, Stream},
  5. kernel::{
  6. block::BlockDevice,
  7. constants::{EEXIST, EINVAL, EIO, ENOSYS, S_IFDIR, S_IFREG},
  8. timer::Instant,
  9. vfs::{
  10. dentry::{dcache, Dentry},
  11. inode::{
  12. define_struct_inode, AtomicNlink, Ino, Inode, InodeData, Mode, RenameData,
  13. WriteOffset,
  14. },
  15. mount::{register_filesystem, Mount, MountCreator},
  16. s_isdir, s_isreg,
  17. vfs::Vfs,
  18. DevId, FsContext,
  19. },
  20. },
  21. path::Path,
  22. prelude::*,
  23. };
  24. use alloc::sync::Weak;
  25. use alloc::{
  26. collections::btree_map::{BTreeMap, Entry},
  27. sync::Arc,
  28. };
  29. use another_ext4::{
  30. Block, BlockDevice as Ext4BlockDeviceTrait, Ext4, FileType, InodeMode, PBlockId,
  31. };
  32. use eonix_runtime::task::Task;
  33. use eonix_sync::RwLock;
  34. pub struct Ext4BlockDevice {
  35. device: Arc<BlockDevice>,
  36. }
  37. impl Ext4BlockDevice {
  38. pub fn new(device: Arc<BlockDevice>) -> Self {
  39. Self { device }
  40. }
  41. }
  42. impl Ext4BlockDeviceTrait for Ext4BlockDevice {
  43. fn read_block(&self, block_id: PBlockId) -> Block {
  44. let mut buffer = [0u8; 4096];
  45. let mut byte_buffer = ByteBuffer::new(buffer.as_mut_slice());
  46. let _ = self
  47. .device
  48. .read_some((block_id as usize) * 4096, &mut byte_buffer)
  49. .expect("Failed to read from block device");
  50. Block {
  51. id: block_id,
  52. data: buffer,
  53. }
  54. }
  55. fn write_block(&self, block: &another_ext4::Block) {
  56. let _ = self
  57. .device
  58. .write_some((block.id as usize) * 4096, &block.data);
  59. }
  60. }
  61. impl_any!(Ext4Fs);
  62. struct Ext4Fs {
  63. inner: Ext4,
  64. device: Arc<BlockDevice>,
  65. icache: RwLock<BTreeMap<Ino, Ext4Inode>>,
  66. }
  67. impl Vfs for Ext4Fs {
  68. fn io_blksize(&self) -> usize {
  69. 4096
  70. }
  71. fn fs_devid(&self) -> DevId {
  72. self.device.devid()
  73. }
  74. fn is_read_only(&self) -> bool {
  75. true
  76. }
  77. }
  78. impl Ext4Fs {
  79. fn try_get(&self, icache: &BTreeMap<Ino, Ext4Inode>, ino: u64) -> Option<Arc<dyn Inode>> {
  80. icache.get(&ino).cloned().map(Ext4Inode::into_inner)
  81. }
  82. fn modify_inode_stat(&self, ino: u32, size: Option<u64>, mtime: u32) {
  83. let _ = self
  84. .inner
  85. .setattr(ino, None, None, None, size, None, Some(mtime), None, None);
  86. }
  87. fn create_inode_stat(&self, parent: u32, child: u32, mtime: u32) {
  88. let _ = self.inner.setattr(
  89. parent,
  90. None,
  91. None,
  92. None,
  93. None,
  94. None,
  95. Some(mtime),
  96. None,
  97. None,
  98. );
  99. let _ = self
  100. .inner
  101. .setattr(child, None, None, None, None, None, Some(mtime), None, None);
  102. }
  103. fn chmod_stat(&self, ino: u32, new_mode: u16, ctime: u32) {
  104. let _ = self.inner.setattr(
  105. ino,
  106. Some(InodeMode::from_bits_retain(new_mode.try_into().unwrap())),
  107. None,
  108. None,
  109. None,
  110. None,
  111. None,
  112. Some(ctime),
  113. None,
  114. );
  115. }
  116. fn get_or_insert(
  117. &self,
  118. icache: &mut BTreeMap<Ino, Ext4Inode>,
  119. mut idata: InodeData,
  120. ) -> Arc<dyn Inode> {
  121. match icache.entry(idata.ino) {
  122. Entry::Occupied(occupied) => occupied.get().clone().into_inner(),
  123. Entry::Vacant(vacant) => {
  124. let mode = *idata.mode.get_mut();
  125. if s_isreg(mode) {
  126. vacant
  127. .insert(Ext4Inode::File(FileInode::with_idata(idata)))
  128. .clone()
  129. .into_inner()
  130. } else if s_isdir(mode) {
  131. vacant
  132. .insert(Ext4Inode::Dir(Arc::new(DirInode { idata })))
  133. .clone()
  134. .into_inner()
  135. } else {
  136. println_warn!("ext4: Unsupported inode type: {mode:#o}");
  137. vacant
  138. .insert(Ext4Inode::File(FileInode::with_idata(idata)))
  139. .clone()
  140. .into_inner()
  141. }
  142. }
  143. }
  144. }
  145. }
  146. impl Ext4Fs {
  147. pub fn create(device: Arc<BlockDevice>) -> KResult<(Arc<Self>, Arc<dyn Inode>)> {
  148. let ext4_device = Ext4BlockDevice::new(device.clone());
  149. let ext4 = Ext4::load(Arc::new(ext4_device)).unwrap();
  150. let ext4fs = Arc::new(Self {
  151. inner: ext4,
  152. device,
  153. icache: RwLock::new(BTreeMap::new()),
  154. });
  155. let root_inode = {
  156. let mut icache = Task::block_on(ext4fs.icache.write());
  157. let root_inode = ext4fs.inner.read_root_inode();
  158. ext4fs.get_or_insert(
  159. &mut icache,
  160. InodeData {
  161. ino: root_inode.id as Ino,
  162. size: AtomicU64::new(root_inode.inode.size()),
  163. nlink: AtomicNlink::new(root_inode.inode.link_count() as u64),
  164. uid: AtomicU32::new(root_inode.inode.uid()),
  165. gid: AtomicU32::new(root_inode.inode.gid()),
  166. mode: AtomicU32::new(root_inode.inode.mode().bits() as u32),
  167. atime: Spin::new(Instant::new(
  168. root_inode.inode.atime() as _,
  169. root_inode.inode.atime_extra() as _,
  170. )),
  171. ctime: Spin::new(Instant::new(
  172. root_inode.inode.ctime() as _,
  173. root_inode.inode.ctime_extra() as _,
  174. )),
  175. mtime: Spin::new(Instant::new(
  176. root_inode.inode.mtime() as _,
  177. root_inode.inode.mtime_extra() as _,
  178. )),
  179. rwsem: RwLock::new(()),
  180. vfs: Arc::downgrade(&ext4fs) as _,
  181. },
  182. )
  183. };
  184. Ok((ext4fs, root_inode))
  185. }
  186. }
  187. #[derive(Clone)]
  188. enum Ext4Inode {
  189. File(Arc<FileInode>),
  190. Dir(Arc<DirInode>),
  191. }
  192. impl Ext4Inode {
  193. fn into_inner(self) -> Arc<dyn Inode> {
  194. match self {
  195. Ext4Inode::File(inode) => inode,
  196. Ext4Inode::Dir(inode) => inode,
  197. }
  198. }
  199. }
  200. define_struct_inode! {
  201. struct FileInode {
  202. page_cache: PageCache,
  203. }
  204. }
  205. define_struct_inode! {
  206. struct DirInode;
  207. }
  208. impl FileInode {
  209. fn with_idata(idata: InodeData) -> Arc<Self> {
  210. let inode = Arc::new_cyclic(|weak_self: &Weak<FileInode>| Self {
  211. idata,
  212. page_cache: PageCache::new(weak_self.clone()),
  213. });
  214. inode
  215. }
  216. pub fn new(ino: Ino, vfs: Weak<dyn Vfs>, mode: Mode) -> Arc<Self> {
  217. Arc::new_cyclic(|weak_self: &Weak<FileInode>| Self {
  218. idata: {
  219. let inode_data = InodeData::new(ino, vfs);
  220. inode_data
  221. .mode
  222. .store(S_IFREG | (mode & 0o777), Ordering::Relaxed);
  223. inode_data.nlink.store(1, Ordering::Relaxed);
  224. inode_data
  225. },
  226. page_cache: PageCache::new(weak_self.clone()),
  227. })
  228. }
  229. }
  230. impl PageCacheBackend for FileInode {
  231. fn read_page(&self, page: &mut crate::kernel::mem::CachePage, offset: usize) -> KResult<usize> {
  232. self.read_direct(page, offset)
  233. }
  234. fn write_page(&self, page: &crate::kernel::mem::CachePage, offset: usize) -> KResult<usize> {
  235. todo!()
  236. }
  237. fn size(&self) -> usize {
  238. self.size.load(Ordering::Relaxed) as usize
  239. }
  240. }
  241. impl Inode for FileInode {
  242. fn page_cache(&self) -> Option<&PageCache> {
  243. Some(&self.page_cache)
  244. }
  245. fn read(&self, buffer: &mut dyn Buffer, offset: usize) -> KResult<usize> {
  246. Task::block_on(self.page_cache.read(buffer, offset))
  247. }
  248. fn read_direct(&self, buffer: &mut dyn Buffer, offset: usize) -> KResult<usize> {
  249. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  250. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  251. let mut temp_buf = vec![0u8; buffer.total()];
  252. match ext4fs.inner.read(self.ino as u32, offset, &mut temp_buf) {
  253. Ok(bytes_read) => {
  254. let _ = buffer.fill(&temp_buf[..bytes_read])?;
  255. Ok(buffer.wrote())
  256. }
  257. Err(e) => Err(e.code() as u32),
  258. }
  259. }
  260. fn write(&self, stream: &mut dyn Stream, offset: WriteOffset) -> KResult<usize> {
  261. let _lock = Task::block_on(self.rwsem.write());
  262. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  263. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  264. let mut temp_buf = vec![0u8; 4096];
  265. let mut total_written = 0;
  266. let mut store_new_end = None;
  267. let offset = match offset {
  268. WriteOffset::Position(offset) => offset,
  269. // TODO: here need to add some operate
  270. WriteOffset::End(end) => {
  271. store_new_end = Some(end);
  272. self.size.load(Ordering::Relaxed) as usize
  273. }
  274. };
  275. while let Some(data) = stream.poll_data(&mut temp_buf)? {
  276. let written = ext4fs
  277. .inner
  278. .write(self.ino as u32, offset + total_written, data)
  279. .unwrap();
  280. total_written += written;
  281. if written < data.len() {
  282. break;
  283. }
  284. }
  285. if let Some(store_end) = store_new_end {
  286. *store_end = offset + total_written;
  287. }
  288. let mtime = Instant::now();
  289. *self.mtime.lock() = mtime;
  290. let new_size = (offset + total_written) as u64;
  291. self.size
  292. .store(offset as u64 + total_written as u64, Ordering::Relaxed);
  293. ext4fs.modify_inode_stat(
  294. self.ino as u32,
  295. Some(new_size),
  296. mtime.since_epoch().as_secs() as u32,
  297. );
  298. Ok(total_written)
  299. }
  300. fn chmod(&self, mode: Mode) -> KResult<()> {
  301. let _lock = Task::block_on(self.rwsem.write());
  302. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  303. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  304. let old_mode = self.mode.load(Ordering::Relaxed);
  305. let new_mode = (old_mode & !0o777) | (mode & 0o777);
  306. let now = Instant::now();
  307. ext4fs.chmod_stat(
  308. self.ino as u32,
  309. new_mode as u16,
  310. now.since_epoch().as_secs() as u32,
  311. );
  312. // SAFETY: `rwsem` has done the synchronization
  313. self.mode.store(new_mode, Ordering::Relaxed);
  314. *self.ctime.lock() = now;
  315. Ok(())
  316. }
  317. // TODO
  318. fn truncate(&self, length: usize) -> KResult<()> {
  319. Ok(())
  320. }
  321. }
  322. impl DirInode {
  323. fn new(ino: Ino, vfs: Weak<dyn Vfs>, mode: Mode) -> Arc<Self> {
  324. Arc::new_cyclic(|_| DirInode {
  325. idata: {
  326. let inode_data = InodeData::new(ino, vfs);
  327. inode_data
  328. .mode
  329. .store(S_IFDIR | (mode & 0o777), Ordering::Relaxed);
  330. inode_data.nlink.store(2, Ordering::Relaxed);
  331. inode_data.size.store(4096, Ordering::Relaxed);
  332. inode_data
  333. },
  334. })
  335. }
  336. fn update_time(&self, time: Instant) {
  337. *self.ctime.lock() = time;
  338. *self.mtime.lock() = time;
  339. }
  340. fn update_child_time(&self, child: &dyn Inode, time: Instant) {
  341. self.update_time(time);
  342. *child.ctime.lock() = time;
  343. *child.mtime.lock() = time;
  344. }
  345. fn link_file(&self) {
  346. self.size.fetch_add(1, Ordering::Relaxed);
  347. }
  348. fn link_dir(&self) {
  349. self.nlink.fetch_add(1, Ordering::Relaxed);
  350. self.size.fetch_add(1, Ordering::Relaxed);
  351. }
  352. fn unlink_dir(&self) {
  353. self.nlink.fetch_sub(1, Ordering::Relaxed);
  354. }
  355. }
  356. impl Inode for DirInode {
  357. fn lookup(&self, dentry: &Arc<Dentry>) -> KResult<Option<Arc<dyn Inode>>> {
  358. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  359. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  360. let name = dentry.get_name();
  361. let name = String::from_utf8_lossy(&name);
  362. let lookup_result = ext4fs.inner.lookup(self.ino as u32, &name);
  363. // TODO: wtf
  364. //const EXT4_ERROR_ENOENT: Ext4Error_ = Ext4Error_::new(ErrCode::ENOENT);
  365. let attr = match lookup_result {
  366. Ok(inode_id) => ext4fs.inner.getattr(inode_id).unwrap(),
  367. //Err(EXT4_ERROR_ENOENT) => return Ok(None),
  368. Err(error) => return Err(error.code() as u32),
  369. };
  370. // Fast path: if the inode is already in the cache, return it.
  371. if let Some(inode) = ext4fs.try_get(&Task::block_on(ext4fs.icache.read()), attr.ino as u64)
  372. {
  373. return Ok(Some(inode));
  374. }
  375. let file_type_bits = match attr.ftype {
  376. FileType::RegularFile => InodeMode::FILE.bits(),
  377. FileType::Directory => InodeMode::DIRECTORY.bits(),
  378. FileType::CharacterDev => InodeMode::CHARDEV.bits(),
  379. FileType::BlockDev => InodeMode::BLOCKDEV.bits(),
  380. FileType::Fifo => InodeMode::FIFO.bits(),
  381. FileType::Socket => InodeMode::SOCKET.bits(),
  382. FileType::SymLink => InodeMode::SOFTLINK.bits(),
  383. FileType::Unknown => 0,
  384. };
  385. let perm_bits = attr.perm.bits() & InodeMode::PERM_MASK.bits();
  386. let mode = file_type_bits | perm_bits;
  387. // Create a new inode based on the attributes.
  388. let mut icache = Task::block_on(ext4fs.icache.write());
  389. let inode = ext4fs.get_or_insert(
  390. &mut icache,
  391. InodeData {
  392. ino: attr.ino as Ino,
  393. size: AtomicU64::new(attr.size),
  394. nlink: AtomicNlink::new(attr.links as _),
  395. uid: AtomicU32::new(attr.uid),
  396. gid: AtomicU32::new(attr.gid),
  397. mode: AtomicU32::new(mode as u32),
  398. atime: Spin::new(Instant::new(attr.atime as _, 0)),
  399. ctime: Spin::new(Instant::new(attr.ctime as _, 0)),
  400. mtime: Spin::new(Instant::new(attr.mtime as _, 0)),
  401. rwsem: RwLock::new(()),
  402. vfs: self.vfs.clone(),
  403. },
  404. );
  405. Ok(Some(inode))
  406. }
  407. fn do_readdir(
  408. &self,
  409. offset: usize,
  410. callback: &mut dyn FnMut(&[u8], Ino) -> KResult<core::ops::ControlFlow<(), ()>>,
  411. ) -> KResult<usize> {
  412. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  413. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  414. let entries = ext4fs
  415. .inner
  416. .listdir(self.ino as u32)
  417. .map_err(|err| err.code() as u32)?;
  418. let entries_to_process = if offset < entries.len() {
  419. &entries[offset..]
  420. } else {
  421. &entries[0..0]
  422. };
  423. let mut current_offset = 0;
  424. for entry in entries_to_process {
  425. let name_string = entry.name();
  426. let name = name_string.as_bytes();
  427. let inode = entry.inode() as Ino;
  428. if callback(name, inode)?.is_break() {
  429. break;
  430. }
  431. current_offset += 1;
  432. }
  433. Ok(current_offset)
  434. }
  435. fn creat(&self, at: &Arc<Dentry>, mode: Mode) -> KResult<()> {
  436. let _lock = Task::block_on(self.rwsem.write());
  437. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  438. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  439. let name = at.get_name();
  440. let name = String::from_utf8_lossy(&name);
  441. let new_ino = ext4fs
  442. .inner
  443. .create(
  444. self.ino as u32,
  445. &name,
  446. InodeMode::from_bits_retain((mode | S_IFREG) as u16),
  447. )
  448. .unwrap();
  449. let file = FileInode::new(new_ino as u64, self.vfs.clone(), mode);
  450. let now = Instant::now();
  451. self.update_child_time(file.as_ref(), now);
  452. self.link_file();
  453. ext4fs.create_inode_stat(self.ino as u32, new_ino, now.since_epoch().as_secs() as u32);
  454. at.save_reg(file)
  455. }
  456. fn mkdir(&self, at: &Dentry, mode: Mode) -> KResult<()> {
  457. let _lock = Task::block_on(self.rwsem.write());
  458. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  459. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  460. let name = at.get_name();
  461. let name = String::from_utf8_lossy(&name);
  462. let new_ino = ext4fs
  463. .inner
  464. .mkdir(
  465. self.ino as u32,
  466. &name,
  467. InodeMode::from_bits_retain((mode | S_IFDIR) as u16),
  468. )
  469. .unwrap();
  470. let new_dir = DirInode::new(new_ino as u64, self.vfs.clone(), mode);
  471. let now = Instant::now();
  472. self.update_child_time(new_dir.as_ref(), now);
  473. self.link_dir();
  474. ext4fs.create_inode_stat(self.ino as u32, new_ino, now.since_epoch().as_secs() as u32);
  475. at.save_dir(new_dir)
  476. }
  477. fn unlink(&self, at: &Arc<Dentry>) -> KResult<()> {
  478. let _dir_lock = Task::block_on(self.rwsem.write());
  479. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  480. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  481. let file = at.get_inode()?;
  482. let name = at.get_name();
  483. let name = String::from_utf8_lossy(&name);
  484. let _file_lock = Task::block_on(file.rwsem.write());
  485. if file.is_dir() {
  486. let _ = ext4fs.inner.rmdir(self.ino as u32, &name);
  487. self.unlink_dir();
  488. } else {
  489. let _ = ext4fs.inner.unlink(self.ino as u32, &name);
  490. }
  491. let now = Instant::now();
  492. self.update_time(now);
  493. ext4fs.modify_inode_stat(self.ino as u32, None, now.since_epoch().as_secs() as u32);
  494. dcache::d_remove(at);
  495. Ok(())
  496. }
  497. fn chmod(&self, mode: Mode) -> KResult<()> {
  498. let _lock = Task::block_on(self.rwsem.write());
  499. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  500. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  501. let old_mode = self.mode.load(Ordering::Relaxed);
  502. let new_mode = (old_mode & !0o777) | (mode & 0o777);
  503. let now = Instant::now();
  504. ext4fs.chmod_stat(
  505. self.ino as u32,
  506. new_mode as u16,
  507. now.since_epoch().as_secs() as u32,
  508. );
  509. // SAFETY: `rwsem` has done the synchronization
  510. self.mode.store(new_mode, Ordering::Relaxed);
  511. *self.ctime.lock() = now;
  512. Ok(())
  513. }
  514. fn rename(&self, rename_data: RenameData) -> KResult<()> {
  515. let RenameData {
  516. old_dentry,
  517. new_dentry,
  518. new_parent,
  519. is_exchange,
  520. no_replace,
  521. vfs,
  522. } = rename_data;
  523. if is_exchange {
  524. println_warn!("Ext4Fs does not support exchange rename for now");
  525. return Err(ENOSYS);
  526. }
  527. // TODO: may need another lock
  528. let _lock = Task::block_on(self.rwsem.write());
  529. let vfs = self.vfs.upgrade().ok_or(EIO)?;
  530. let ext4fs = vfs.as_any().downcast_ref::<Ext4Fs>().unwrap();
  531. let old_file = old_dentry.get_inode()?;
  532. let new_file = new_dentry.get_inode();
  533. if no_replace && new_file.is_ok() {
  534. return Err(EEXIST);
  535. }
  536. let name = old_dentry.name();
  537. let name = core::str::from_utf8(&*name).map_err(|_| EINVAL)?;
  538. let new_name = new_dentry.name();
  539. let new_name = core::str::from_utf8(&*new_name).map_err(|_| EINVAL)?;
  540. ext4fs
  541. .inner
  542. .rename(self.ino as u32, name, new_parent.ino as u32, new_name)
  543. .map_err(|err| err.code() as u32)?;
  544. // TODO: may need more operations
  545. let now = Instant::now();
  546. *old_file.ctime.lock() = now;
  547. *self.mtime.lock() = now;
  548. let same_parent = Arc::as_ptr(&new_parent) == &raw const *self;
  549. if !same_parent {
  550. *new_parent.mtime.lock() = now;
  551. if old_file.is_dir() {
  552. self.nlink.fetch_sub(1, Ordering::Relaxed);
  553. new_parent.nlink.fetch_add(1, Ordering::Relaxed);
  554. }
  555. }
  556. if let Ok(replaced_file) = new_dentry.get_inode() {
  557. if !no_replace {
  558. *replaced_file.ctime.lock() = now;
  559. replaced_file.nlink.fetch_sub(1, Ordering::Relaxed);
  560. }
  561. }
  562. Task::block_on(dcache::d_exchange(old_dentry, new_dentry));
  563. Ok(())
  564. }
  565. }
  566. struct Ext4MountCreator;
  567. impl MountCreator for Ext4MountCreator {
  568. fn check_signature(&self, mut first_block: &[u8]) -> KResult<bool> {
  569. match first_block.split_off(1080..) {
  570. Some([0x53, 0xef, ..]) => Ok(true), // Superblock signature
  571. Some(..) => Ok(false),
  572. None => Err(EIO),
  573. }
  574. }
  575. fn create_mount(&self, source: &str, _flags: u64, mp: &Arc<Dentry>) -> KResult<Mount> {
  576. let source = source.as_bytes();
  577. let path = Path::new(source)?;
  578. let device_dentry =
  579. Dentry::open_recursive(&FsContext::global(), Dentry::root(), path, true, 0)?;
  580. let devid = device_dentry.get_inode()?.devid()?;
  581. let device = BlockDevice::get(devid)?;
  582. let (ext4fs, root_inode) = Ext4Fs::create(device)?;
  583. Mount::new(mp, ext4fs, root_inode)
  584. }
  585. }
  586. pub fn init() {
  587. register_filesystem("ext4", Arc::new(Ext4MountCreator)).unwrap();
  588. }