dentry.rs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. pub mod dcache;
  2. use core::{
  3. hash::{BuildHasher, BuildHasherDefault, Hasher},
  4. sync::atomic::AtomicPtr,
  5. };
  6. use crate::{
  7. hash::KernelHasher,
  8. io::{ByteBuffer, RawBuffer},
  9. path::{Path, PathComponent},
  10. prelude::*,
  11. rcu::{RCUNode, RCUPointer},
  12. };
  13. use alloc::sync::Arc;
  14. use bindings::{EINVAL, ELOOP, ENOENT, ENOTDIR};
  15. use super::inode::Inode;
  16. struct DentryData {
  17. inode: Arc<dyn Inode>,
  18. flags: u64,
  19. }
  20. pub struct Dentry {
  21. // Const after insertion into dcache
  22. parent: Arc<Dentry>,
  23. name: Arc<[u8]>,
  24. hash: u64,
  25. // Used by the dentry cache
  26. prev: AtomicPtr<Dentry>,
  27. next: AtomicPtr<Dentry>,
  28. // RCU Mutable
  29. data: RCUPointer<DentryData>,
  30. }
  31. const D_DIRECTORY: u64 = 1;
  32. const D_MOUNTPOINT: u64 = 2;
  33. const D_SYMLINK: u64 = 4;
  34. const D_REGULAR: u64 = 8;
  35. impl RCUNode<Dentry> for Dentry {
  36. fn rcu_prev(&self) -> &AtomicPtr<Self> {
  37. &self.prev
  38. }
  39. fn rcu_next(&self) -> &AtomicPtr<Self> {
  40. &self.next
  41. }
  42. }
  43. impl Dentry {
  44. fn rehash(self: &Arc<Self>) -> u64 {
  45. let builder: BuildHasherDefault<KernelHasher> = Default::default();
  46. let mut hasher = builder.build_hasher();
  47. hasher.write_usize(self.parent_addr() as usize);
  48. hasher.write(self.name.as_ref());
  49. hasher.finish()
  50. }
  51. fn find(self: &Arc<Self>, name: &[u8]) -> KResult<Arc<Self>> {
  52. let data = self.data.load();
  53. let data = data.as_ref().ok_or(ENOENT)?;
  54. if data.flags & D_DIRECTORY == 0 {
  55. return Err(ENOTDIR);
  56. }
  57. match name {
  58. b"." => Ok(self.clone()),
  59. b".." => Ok(self.parent.clone()),
  60. _ => {
  61. let dentry = Dentry::create(self.clone(), name);
  62. Ok(dcache::d_find_fast(&dentry).unwrap_or_else(|| {
  63. dcache::d_try_revalidate(&dentry);
  64. dcache::d_add(&dentry);
  65. dentry
  66. }))
  67. }
  68. }
  69. }
  70. }
  71. impl Dentry {
  72. pub fn create(parent: Arc<Dentry>, name: &[u8]) -> Arc<Self> {
  73. let mut val = Arc::new(Self {
  74. parent,
  75. name: Arc::from(name),
  76. hash: 0,
  77. prev: AtomicPtr::default(),
  78. next: AtomicPtr::default(),
  79. data: RCUPointer::empty(),
  80. });
  81. let hash = val.rehash();
  82. let val_mut = Arc::get_mut(&mut val).unwrap();
  83. val_mut.hash = hash;
  84. val
  85. }
  86. /// Check the equality of two denties inside the same dentry cache hash group
  87. /// where `other` is identified by `hash`, `parent` and `name`
  88. ///
  89. fn hash_eq(self: &Arc<Self>, other: &Arc<Self>) -> bool {
  90. self.hash == other.hash
  91. && self.parent_addr() == other.parent_addr()
  92. && self.name == other.name
  93. }
  94. pub fn name(&self) -> &Arc<[u8]> {
  95. &self.name
  96. }
  97. pub fn parent(&self) -> &Arc<Self> {
  98. &self.parent
  99. }
  100. pub fn parent_addr(&self) -> *const Self {
  101. Arc::as_ptr(&self.parent)
  102. }
  103. fn save_data(&self, inode: Arc<dyn Inode>, flags: u64) -> KResult<()> {
  104. let new = DentryData { inode, flags };
  105. let old = self.data.swap(Some(Arc::new(new)));
  106. // Safety: old data is `None`, so it's safe to emit the `drop` call
  107. assert!(old.is_none());
  108. Ok(())
  109. }
  110. pub fn save_reg(&self, file: Arc<dyn Inode>) -> KResult<()> {
  111. self.save_data(file, D_REGULAR)
  112. }
  113. pub fn save_symlink(&self, link: Arc<dyn Inode>) -> KResult<()> {
  114. self.save_data(link, D_SYMLINK)
  115. }
  116. pub fn save_dir(&self, dir: Arc<dyn Inode>) -> KResult<()> {
  117. self.save_data(dir, D_DIRECTORY)
  118. }
  119. pub fn get_inode(&self) -> KResult<Arc<dyn Inode>> {
  120. self.data
  121. .load()
  122. .as_ref()
  123. .ok_or(EINVAL)
  124. .map(|data| data.inode.clone())
  125. }
  126. /// This function is used to get the **borrowed** dentry from a raw pointer
  127. pub fn from_raw(raw: &*const Self) -> BorrowedArc<Self> {
  128. assert!(!raw.is_null());
  129. BorrowedArc::new(raw)
  130. }
  131. pub fn is_directory(&self) -> bool {
  132. let data = self.data.load();
  133. data.as_ref()
  134. .map_or(false, |data| data.flags & D_DIRECTORY != 0)
  135. }
  136. }
  137. #[repr(C)]
  138. pub struct FsContext {
  139. root: *const Dentry,
  140. }
  141. impl Dentry {
  142. fn resolve_directory(
  143. context: &FsContext,
  144. dentry: Arc<Self>,
  145. nrecur: u32,
  146. ) -> KResult<Arc<Self>> {
  147. if nrecur >= 16 {
  148. return Err(ELOOP);
  149. }
  150. let data = dentry.data.load();
  151. let data = data.as_ref().ok_or(ENOENT)?;
  152. match data.flags {
  153. flags if flags & D_REGULAR != 0 => Err(ENOTDIR),
  154. flags if flags & D_DIRECTORY != 0 => Ok(dentry),
  155. flags if flags & D_SYMLINK != 0 => {
  156. let mut buffer = [0u8; 256];
  157. let mut buffer = ByteBuffer::new(&mut buffer);
  158. data.inode.readlink(&mut buffer)?;
  159. let path = Path::new(buffer.data())?;
  160. let dentry = Self::open_recursive(context, &dentry.parent, path, true, nrecur + 1)?;
  161. Self::resolve_directory(context, dentry, nrecur + 1)
  162. }
  163. _ => panic!("Invalid dentry flags"),
  164. }
  165. }
  166. fn open_recursive(
  167. context: &FsContext,
  168. cwd: &Arc<Self>,
  169. path: Path,
  170. follow: bool,
  171. nrecur: u32,
  172. ) -> KResult<Arc<Self>> {
  173. // too many recursive search layers will cause stack overflow
  174. // so we use 16 for now
  175. if nrecur >= 16 {
  176. return Err(ELOOP);
  177. }
  178. let mut cwd = if path.is_absolute() {
  179. Dentry::from_raw(&context.root).clone()
  180. } else {
  181. cwd.clone()
  182. };
  183. let root_dentry = Dentry::from_raw(&context.root);
  184. for item in path.iter() {
  185. if let PathComponent::TrailingEmpty = item {
  186. if cwd.data.load().as_ref().is_none() {
  187. return Ok(cwd);
  188. }
  189. }
  190. cwd = Self::resolve_directory(context, cwd, nrecur)?;
  191. match item {
  192. PathComponent::TrailingEmpty | PathComponent::Current => {} // pass
  193. PathComponent::Parent => {
  194. if !cwd.hash_eq(root_dentry.as_ref()) {
  195. cwd = Self::resolve_directory(context, cwd.parent.clone(), nrecur)?;
  196. }
  197. continue;
  198. }
  199. PathComponent::Name(name) => {
  200. cwd = cwd.find(name)?;
  201. }
  202. }
  203. }
  204. if follow {
  205. let data = cwd.data.load();
  206. if let Some(data) = data.as_ref() {
  207. if data.flags & D_SYMLINK != 0 {
  208. let data = cwd.data.load();
  209. let data = data.as_ref().unwrap();
  210. let mut buffer = [0u8; 256];
  211. let mut buffer = ByteBuffer::new(&mut buffer);
  212. data.inode.readlink(&mut buffer)?;
  213. let path = Path::new(buffer.data())?;
  214. cwd = Self::open_recursive(context, &cwd.parent, path, true, nrecur + 1)?;
  215. }
  216. }
  217. }
  218. Ok(cwd)
  219. }
  220. }
  221. #[no_mangle]
  222. pub extern "C" fn dentry_open(
  223. context_root: *const Dentry,
  224. cwd: *const Dentry, // borrowed
  225. path: *const u8,
  226. path_len: usize,
  227. follow: bool,
  228. ) -> *const Dentry {
  229. match (|| -> KResult<Arc<Dentry>> {
  230. let path = Path::new(unsafe { core::slice::from_raw_parts(path, path_len) })?;
  231. let context = FsContext { root: context_root };
  232. Dentry::open_recursive(&context, Dentry::from_raw(&cwd).as_ref(), path, follow, 0)
  233. })() {
  234. Ok(dentry) => Arc::into_raw(dentry),
  235. Err(err) => (-(err as i32) as usize) as *const Dentry,
  236. }
  237. }
  238. #[no_mangle]
  239. pub extern "C" fn d_path(
  240. dentry: *const Dentry,
  241. root: *const Dentry,
  242. mut buffer: *mut u8,
  243. bufsize: usize,
  244. ) -> i32 {
  245. let mut buffer = RawBuffer::new_from_raw(&mut buffer, bufsize);
  246. match (|| {
  247. let mut dentry = Dentry::from_raw(&dentry).clone();
  248. let root = Dentry::from_raw(&root);
  249. let mut path = vec![];
  250. while Arc::as_ptr(&dentry) != Arc::as_ptr(root.as_ref()) {
  251. if path.len() > 32 {
  252. return Err(ELOOP);
  253. }
  254. path.push(dentry.name().clone());
  255. dentry = dentry.parent().clone();
  256. }
  257. const ERANGE: u32 = 34;
  258. buffer.fill(b"/")?.ok_or(ERANGE)?;
  259. for item in path.iter().rev().map(|name| name.as_ref()) {
  260. buffer.fill(item)?.ok_or(ERANGE)?;
  261. buffer.fill(b"/")?.ok_or(ERANGE)?;
  262. }
  263. buffer.fill(&[0])?.ok_or(ERANGE)?;
  264. Ok(())
  265. })() {
  266. Ok(_) => 0,
  267. Err(err) => -(err as i32),
  268. }
  269. }
  270. #[no_mangle]
  271. pub extern "C" fn r_dget(dentry: *const Dentry) -> *const Dentry {
  272. debug_assert!(!dentry.is_null());
  273. unsafe { Arc::increment_strong_count(dentry) };
  274. dentry
  275. }
  276. #[no_mangle]
  277. pub extern "C" fn r_dput(dentry: *const Dentry) {
  278. debug_assert!(!dentry.is_null());
  279. unsafe { Arc::from_raw(dentry) };
  280. }
  281. #[no_mangle]
  282. pub extern "C" fn r_dentry_is_directory(dentry: *const Dentry) -> bool {
  283. let dentry = Dentry::from_raw(&dentry);
  284. dentry
  285. .data
  286. .load()
  287. .as_ref()
  288. .map_or(false, |data| data.flags & D_DIRECTORY != 0)
  289. }
  290. #[no_mangle]
  291. pub extern "C" fn r_dentry_is_invalid(dentry: *const Dentry) -> bool {
  292. let dentry = Dentry::from_raw(&dentry);
  293. dentry.data.load().is_none()
  294. }