dentry.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. pub mod dcache;
  2. use core::{
  3. hash::{BuildHasher, BuildHasherDefault, Hasher},
  4. ops::ControlFlow,
  5. sync::atomic::{AtomicPtr, Ordering},
  6. };
  7. use crate::{
  8. hash::KernelHasher,
  9. io::{Buffer, ByteBuffer},
  10. kernel::{block::BlockDevice, CharDevice},
  11. path::{Path, PathComponent},
  12. prelude::*,
  13. rcu::{RCUNode, RCUPointer},
  14. };
  15. use alloc::sync::Arc;
  16. use bindings::{
  17. statx, EEXIST, EINVAL, EISDIR, ELOOP, ENOENT, ENOTDIR, EPERM, ERANGE, O_CREAT, O_EXCL,
  18. };
  19. use super::{
  20. inode::{Ino, Inode, Mode, WriteOffset},
  21. s_isblk, s_ischr, s_isdir, s_isreg, DevId, FsContext,
  22. };
  23. struct DentryData {
  24. inode: Arc<dyn Inode>,
  25. flags: u64,
  26. }
  27. /// # Safety
  28. ///
  29. /// We wrap `Dentry` in `Arc` to ensure that the `Dentry` is not dropped while it is still in use.
  30. ///
  31. /// Since a `Dentry` is created and marked as live(some data is saved to it), it keeps alive until
  32. /// the last reference is dropped.
  33. pub struct Dentry {
  34. // Const after insertion into dcache
  35. parent: Arc<Dentry>,
  36. name: Arc<[u8]>,
  37. hash: u64,
  38. // Used by the dentry cache
  39. prev: AtomicPtr<Dentry>,
  40. next: AtomicPtr<Dentry>,
  41. // RCU Mutable
  42. data: RCUPointer<DentryData>,
  43. }
  44. impl core::fmt::Debug for Dentry {
  45. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  46. f.debug_struct("Dentry")
  47. .field("name", &String::from_utf8_lossy(&self.name))
  48. .field("parent", &String::from_utf8_lossy(&self.parent.name))
  49. .finish()
  50. }
  51. }
  52. const D_DIRECTORY: u64 = 1;
  53. #[allow(dead_code)]
  54. const D_MOUNTPOINT: u64 = 2;
  55. const D_SYMLINK: u64 = 4;
  56. const D_REGULAR: u64 = 8;
  57. impl RCUNode<Dentry> for Dentry {
  58. fn rcu_prev(&self) -> &AtomicPtr<Self> {
  59. &self.prev
  60. }
  61. fn rcu_next(&self) -> &AtomicPtr<Self> {
  62. &self.next
  63. }
  64. }
  65. impl Dentry {
  66. fn rehash(self: &Arc<Self>) -> u64 {
  67. let builder: BuildHasherDefault<KernelHasher> = Default::default();
  68. let mut hasher = builder.build_hasher();
  69. hasher.write_usize(self.parent_addr() as usize);
  70. hasher.write(self.name.as_ref());
  71. hasher.finish()
  72. }
  73. fn find(self: &Arc<Self>, name: &[u8]) -> KResult<Arc<Self>> {
  74. let data = self.data.load();
  75. let data = data.as_ref().ok_or(ENOENT)?;
  76. if data.flags & D_DIRECTORY == 0 {
  77. return Err(ENOTDIR);
  78. }
  79. match name {
  80. b"." => Ok(self.clone()),
  81. b".." => Ok(self.parent.clone()),
  82. _ => {
  83. let dentry = Dentry::create(self.clone(), name);
  84. Ok(dcache::d_find_fast(&dentry).unwrap_or_else(|| {
  85. dcache::d_try_revalidate(&dentry);
  86. dcache::d_add(&dentry);
  87. dentry
  88. }))
  89. }
  90. }
  91. }
  92. }
  93. impl Dentry {
  94. pub fn create(parent: Arc<Dentry>, name: &[u8]) -> Arc<Self> {
  95. let mut val = Arc::new(Self {
  96. parent,
  97. name: Arc::from(name),
  98. hash: 0,
  99. prev: AtomicPtr::default(),
  100. next: AtomicPtr::default(),
  101. data: RCUPointer::empty(),
  102. });
  103. let hash = val.rehash();
  104. let val_mut = Arc::get_mut(&mut val).unwrap();
  105. val_mut.hash = hash;
  106. val
  107. }
  108. /// Check the equality of two denties inside the same dentry cache hash group
  109. /// where `other` is identified by `hash`, `parent` and `name`
  110. ///
  111. fn hash_eq(self: &Arc<Self>, other: &Arc<Self>) -> bool {
  112. self.hash == other.hash
  113. && self.parent_addr() == other.parent_addr()
  114. && self.name == other.name
  115. }
  116. pub fn name(&self) -> &Arc<[u8]> {
  117. &self.name
  118. }
  119. pub fn parent(&self) -> &Arc<Self> {
  120. &self.parent
  121. }
  122. pub fn parent_addr(&self) -> *const Self {
  123. Arc::as_ptr(&self.parent)
  124. }
  125. fn save_data(&self, inode: Arc<dyn Inode>, flags: u64) -> KResult<()> {
  126. let new = DentryData { inode, flags };
  127. // TODO!!!: We don't actually need to use `RCUPointer` here
  128. // Safety: this function may only be called from `create`-like functions which requires the
  129. // superblock's write locks to be held, so only one creation can happen at a time and we
  130. // can't get a reference to the old data.
  131. let old = unsafe { self.data.swap(Some(Arc::new(new))) };
  132. assert!(old.is_none());
  133. Ok(())
  134. }
  135. pub fn save_reg(&self, file: Arc<dyn Inode>) -> KResult<()> {
  136. self.save_data(file, D_REGULAR)
  137. }
  138. pub fn save_symlink(&self, link: Arc<dyn Inode>) -> KResult<()> {
  139. self.save_data(link, D_SYMLINK)
  140. }
  141. pub fn save_dir(&self, dir: Arc<dyn Inode>) -> KResult<()> {
  142. self.save_data(dir, D_DIRECTORY)
  143. }
  144. pub fn get_inode(&self) -> KResult<Arc<dyn Inode>> {
  145. self.data
  146. .load()
  147. .as_ref()
  148. .ok_or(ENOENT)
  149. .map(|data| data.inode.clone())
  150. }
  151. pub fn is_directory(&self) -> bool {
  152. let data = self.data.load();
  153. data.as_ref()
  154. .map_or(false, |data| data.flags & D_DIRECTORY != 0)
  155. }
  156. pub fn is_valid(&self) -> bool {
  157. self.data.load().is_some()
  158. }
  159. pub fn open_check(self: &Arc<Self>, flags: u32, mode: Mode) -> KResult<()> {
  160. let data = self.data.load();
  161. let create = flags & O_CREAT != 0;
  162. let excl = flags & O_EXCL != 0;
  163. if data.is_some() {
  164. if create && excl {
  165. return Err(EEXIST);
  166. }
  167. return Ok(());
  168. } else {
  169. if !create {
  170. return Err(ENOENT);
  171. }
  172. let parent = self.parent().get_inode()?;
  173. parent.creat(self, mode as u32)
  174. }
  175. }
  176. }
  177. impl Dentry {
  178. fn resolve_directory(
  179. context: &FsContext,
  180. dentry: Arc<Self>,
  181. nrecur: u32,
  182. ) -> KResult<Arc<Self>> {
  183. if nrecur >= 16 {
  184. return Err(ELOOP);
  185. }
  186. let data = dentry.data.load();
  187. let data = data.as_ref().ok_or(ENOENT)?;
  188. match data.flags {
  189. flags if flags & D_REGULAR != 0 => Err(ENOTDIR),
  190. flags if flags & D_DIRECTORY != 0 => Ok(dentry),
  191. flags if flags & D_SYMLINK != 0 => {
  192. let mut buffer = [0u8; 256];
  193. let mut buffer = ByteBuffer::new(&mut buffer);
  194. data.inode.readlink(&mut buffer)?;
  195. let path = Path::new(buffer.data())?;
  196. let dentry = Self::open_recursive(context, &dentry.parent, path, true, nrecur + 1)?;
  197. Self::resolve_directory(context, dentry, nrecur + 1)
  198. }
  199. _ => panic!("Invalid dentry flags"),
  200. }
  201. }
  202. pub fn open_recursive(
  203. context: &FsContext,
  204. cwd: &Arc<Self>,
  205. path: Path,
  206. follow: bool,
  207. nrecur: u32,
  208. ) -> KResult<Arc<Self>> {
  209. // too many recursive search layers will cause stack overflow
  210. // so we use 16 for now
  211. if nrecur >= 16 {
  212. return Err(ELOOP);
  213. }
  214. let mut cwd = if path.is_absolute() {
  215. context.fsroot.clone()
  216. } else {
  217. cwd.clone()
  218. };
  219. for item in path.iter() {
  220. if let PathComponent::TrailingEmpty = item {
  221. if cwd.data.load().as_ref().is_none() {
  222. return Ok(cwd);
  223. }
  224. }
  225. cwd = Self::resolve_directory(context, cwd, nrecur)?;
  226. match item {
  227. PathComponent::TrailingEmpty | PathComponent::Current => {} // pass
  228. PathComponent::Parent => {
  229. if !cwd.hash_eq(&context.fsroot) {
  230. cwd = Self::resolve_directory(context, cwd.parent.clone(), nrecur)?;
  231. }
  232. continue;
  233. }
  234. PathComponent::Name(name) => {
  235. cwd = cwd.find(name)?;
  236. }
  237. }
  238. }
  239. if follow {
  240. let data = cwd.data.load();
  241. if let Some(data) = data.as_ref() {
  242. if data.flags & D_SYMLINK != 0 {
  243. let data = cwd.data.load();
  244. let data = data.as_ref().unwrap();
  245. let mut buffer = [0u8; 256];
  246. let mut buffer = ByteBuffer::new(&mut buffer);
  247. data.inode.readlink(&mut buffer)?;
  248. let path = Path::new(buffer.data())?;
  249. cwd = Self::open_recursive(context, &cwd.parent, path, true, nrecur + 1)?;
  250. }
  251. }
  252. }
  253. Ok(cwd)
  254. }
  255. pub fn open(context: &FsContext, path: Path, follow_symlinks: bool) -> KResult<Arc<Self>> {
  256. let cwd = context.cwd.lock().clone();
  257. Dentry::open_recursive(context, &cwd, path, follow_symlinks, 0)
  258. }
  259. pub fn open_at(
  260. context: &FsContext,
  261. at: &Arc<Self>,
  262. path: Path,
  263. follow_symlinks: bool,
  264. ) -> KResult<Arc<Self>> {
  265. Dentry::open_recursive(context, at, path, follow_symlinks, 0)
  266. }
  267. pub fn get_path(
  268. self: &Arc<Dentry>,
  269. context: &FsContext,
  270. buffer: &mut dyn Buffer,
  271. ) -> KResult<()> {
  272. let mut dentry = self;
  273. let root = &context.fsroot;
  274. let mut path = vec![];
  275. while Arc::as_ptr(dentry) != Arc::as_ptr(root) {
  276. if path.len() > 32 {
  277. return Err(ELOOP);
  278. }
  279. path.push(dentry.name().clone());
  280. dentry = dentry.parent();
  281. }
  282. buffer.fill(b"/")?.ok_or(ERANGE)?;
  283. for item in path.iter().rev().map(|name| name.as_ref()) {
  284. buffer.fill(item)?.ok_or(ERANGE)?;
  285. buffer.fill(b"/")?.ok_or(ERANGE)?;
  286. }
  287. buffer.fill(&[0])?.ok_or(ERANGE)?;
  288. Ok(())
  289. }
  290. }
  291. impl Dentry {
  292. pub fn read(&self, buffer: &mut dyn Buffer, offset: usize) -> KResult<usize> {
  293. let inode = self.get_inode()?;
  294. // Safety: Changing mode alone will have no effect on the file's contents
  295. match inode.mode.load(Ordering::Relaxed) {
  296. mode if s_isdir(mode) => Err(EISDIR),
  297. mode if s_isreg(mode) => inode.read(buffer, offset),
  298. mode if s_isblk(mode) => {
  299. let device = BlockDevice::get(inode.devid()?)?;
  300. Ok(device.read_some(offset, buffer)?.allow_partial())
  301. }
  302. mode if s_ischr(mode) => {
  303. let device = CharDevice::get(inode.devid()?).ok_or(EPERM)?;
  304. device.read(buffer)
  305. }
  306. _ => Err(EINVAL),
  307. }
  308. }
  309. pub fn write(&self, buffer: &[u8], offset: WriteOffset) -> KResult<usize> {
  310. let inode = self.get_inode()?;
  311. // Safety: Changing mode alone will have no effect on the file's contents
  312. match inode.mode.load(Ordering::Relaxed) {
  313. mode if s_isdir(mode) => Err(EISDIR),
  314. mode if s_isreg(mode) => inode.write(buffer, offset),
  315. mode if s_isblk(mode) => Err(EINVAL), // TODO
  316. mode if s_ischr(mode) => CharDevice::get(inode.devid()?).ok_or(EPERM)?.write(buffer),
  317. _ => Err(EINVAL),
  318. }
  319. }
  320. pub fn readdir<F>(&self, offset: usize, mut callback: F) -> KResult<usize>
  321. where
  322. F: FnMut(&[u8], Ino) -> KResult<ControlFlow<(), ()>>,
  323. {
  324. self.get_inode()?.do_readdir(offset, &mut callback)
  325. }
  326. pub fn mkdir(&self, mode: Mode) -> KResult<()> {
  327. if self.get_inode().is_ok() {
  328. Err(EEXIST)
  329. } else {
  330. self.parent.get_inode().unwrap().mkdir(self, mode)
  331. }
  332. }
  333. pub fn statx(&self, stat: &mut statx, mask: u32) -> KResult<()> {
  334. self.get_inode()?.statx(stat, mask)
  335. }
  336. pub fn truncate(&self, size: usize) -> KResult<()> {
  337. self.get_inode()?.truncate(size)
  338. }
  339. pub fn unlink(self: &Arc<Self>) -> KResult<()> {
  340. if self.get_inode().is_err() {
  341. Err(ENOENT)
  342. } else {
  343. self.parent.get_inode().unwrap().unlink(self)
  344. }
  345. }
  346. pub fn symlink(self: &Arc<Self>, link: &[u8]) -> KResult<()> {
  347. if self.get_inode().is_ok() {
  348. Err(EEXIST)
  349. } else {
  350. self.parent.get_inode().unwrap().symlink(self, link)
  351. }
  352. }
  353. pub fn readlink(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
  354. self.get_inode()?.readlink(buffer)
  355. }
  356. pub fn mknod(&self, mode: Mode, devid: DevId) -> KResult<()> {
  357. if self.get_inode().is_ok() {
  358. Err(EEXIST)
  359. } else {
  360. self.parent.get_inode().unwrap().mknod(self, mode, devid)
  361. }
  362. }
  363. pub fn chmod(&self, mode: Mode) -> KResult<()> {
  364. self.get_inode()?.chmod(mode)
  365. }
  366. }