filearray.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. use alloc::sync::Arc;
  2. use intrusive_collections::rbtree::Entry;
  3. use intrusive_collections::{
  4. intrusive_adapter, Bound, KeyAdapter, RBTree, RBTreeAtomicLink,
  5. };
  6. use itertools::FoldWhile::{Continue, Done};
  7. use itertools::Itertools;
  8. use posix_types::open::{FDFlags, OpenFlags};
  9. use super::file::{File, InodeFile, Pipe};
  10. use super::types::{Format, Permission};
  11. use super::Spin;
  12. use crate::kernel::constants::{
  13. EBADF, EISDIR, ENOTDIR, ENXIO, F_DUPFD, F_DUPFD_CLOEXEC, F_GETFD, F_GETFL,
  14. F_SETFD, F_SETFL,
  15. };
  16. use crate::kernel::syscall::{FromSyscallArg, SyscallRetVal};
  17. use crate::kernel::task::Thread;
  18. use crate::kernel::vfs::dentry::Dentry;
  19. use crate::kernel::CharDevice;
  20. use crate::prelude::*;
  21. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
  22. pub struct FD(u32);
  23. #[derive(Clone)]
  24. struct OpenFile {
  25. fd: FD,
  26. flags: FDFlags,
  27. file: File,
  28. link: RBTreeAtomicLink,
  29. }
  30. intrusive_adapter!(
  31. OpenFileAdapter = Box<OpenFile>: OpenFile { link: RBTreeAtomicLink }
  32. );
  33. impl<'a> KeyAdapter<'a> for OpenFileAdapter {
  34. type Key = FD;
  35. fn get_key(&self, value: &'a OpenFile) -> Self::Key {
  36. value.fd
  37. }
  38. }
  39. #[derive(Clone)]
  40. struct FDAllocator {
  41. min_avail: FD,
  42. }
  43. struct FileArrayInner {
  44. files: RBTree<OpenFileAdapter>,
  45. fd_alloc: FDAllocator,
  46. }
  47. pub struct FileArray {
  48. inner: Spin<FileArrayInner>,
  49. }
  50. impl OpenFile {
  51. fn new(fd: FD, flags: FDFlags, file: File) -> Box<Self> {
  52. Box::new(Self {
  53. fd,
  54. flags,
  55. file,
  56. link: RBTreeAtomicLink::new(),
  57. })
  58. }
  59. pub fn close_on_exec(&self) -> bool {
  60. self.flags.contains(FDFlags::FD_CLOEXEC)
  61. }
  62. }
  63. impl FDAllocator {
  64. const fn new() -> Self {
  65. Self { min_avail: FD(0) }
  66. }
  67. fn reinit(&mut self) {
  68. self.min_avail = FD(0);
  69. }
  70. fn find_available(
  71. &mut self,
  72. from: FD,
  73. files: &RBTree<OpenFileAdapter>,
  74. ) -> FD {
  75. files
  76. .range(Bound::Included(&from), Bound::Unbounded)
  77. .fold_while(from, |current, OpenFile { fd, .. }| {
  78. if current == *fd {
  79. Continue(FD(current.0 + 1))
  80. } else {
  81. Done(current)
  82. }
  83. })
  84. .into_inner()
  85. }
  86. /// Allocate a new file descriptor starting from `from`.
  87. ///
  88. /// Returned file descriptor should be used immediately.
  89. ///
  90. fn allocate_fd(&mut self, from: FD, files: &RBTree<OpenFileAdapter>) -> FD {
  91. let from = FD::max(from, self.min_avail);
  92. if from == self.min_avail {
  93. let next_min_avail = self.find_available(FD(from.0 + 1), files);
  94. let allocated = self.min_avail;
  95. self.min_avail = next_min_avail;
  96. allocated
  97. } else {
  98. self.find_available(from, files)
  99. }
  100. }
  101. fn release_fd(&mut self, fd: FD) {
  102. if fd < self.min_avail {
  103. self.min_avail = fd;
  104. }
  105. }
  106. fn next_fd(&mut self, files: &RBTree<OpenFileAdapter>) -> FD {
  107. self.allocate_fd(self.min_avail, files)
  108. }
  109. }
  110. impl FileArray {
  111. pub fn new() -> Arc<Self> {
  112. Arc::new(FileArray {
  113. inner: Spin::new(FileArrayInner {
  114. files: RBTree::new(OpenFileAdapter::new()),
  115. fd_alloc: FDAllocator::new(),
  116. }),
  117. })
  118. }
  119. pub fn new_shared(other: &Arc<Self>) -> Arc<Self> {
  120. other.clone()
  121. }
  122. pub fn new_cloned(other: &Self) -> Arc<Self> {
  123. Arc::new(Self {
  124. inner: Spin::new({
  125. let (new_files, new_fd_alloc) = {
  126. let mut new_files = RBTree::new(OpenFileAdapter::new());
  127. let other_inner = other.inner.lock();
  128. for file in other_inner.files.iter() {
  129. let new_file =
  130. OpenFile::new(file.fd, file.flags, file.file.dup());
  131. new_files.insert(new_file);
  132. }
  133. (new_files, other_inner.fd_alloc.clone())
  134. };
  135. FileArrayInner {
  136. files: new_files,
  137. fd_alloc: new_fd_alloc,
  138. }
  139. }),
  140. })
  141. }
  142. /// Acquires the file array lock.
  143. pub fn get(&self, fd: FD) -> Option<File> {
  144. self.inner.lock().get(fd)
  145. }
  146. pub async fn close_all(&self) {
  147. let old_files = {
  148. let mut inner = self.inner.lock();
  149. inner.fd_alloc.reinit();
  150. inner.files.take()
  151. };
  152. for file in old_files.into_iter() {
  153. file.file.close().await;
  154. }
  155. }
  156. pub async fn close(&self, fd: FD) -> KResult<()> {
  157. let file = {
  158. let mut inner = self.inner.lock();
  159. let file = inner.files.find_mut(&fd).remove().ok_or(EBADF)?;
  160. inner.fd_alloc.release_fd(file.fd);
  161. file.file
  162. };
  163. file.close().await;
  164. Ok(())
  165. }
  166. pub async fn on_exec(&self) {
  167. let files_to_close = {
  168. let mut inner = self.inner.lock();
  169. let (files, fd_alloc) = inner.split_borrow();
  170. files.pick(|ofile| {
  171. if ofile.close_on_exec() {
  172. fd_alloc.release_fd(ofile.fd);
  173. true
  174. } else {
  175. false
  176. }
  177. })
  178. };
  179. for open_file in files_to_close.into_iter() {
  180. open_file.file.close().await;
  181. }
  182. }
  183. pub fn dup(&self, old_fd: FD) -> KResult<FD> {
  184. let mut inner = self.inner.lock();
  185. let (files, fd_alloc) = inner.split_borrow();
  186. let old_file = files.get_fd(old_fd).ok_or(EBADF)?;
  187. let new_file_data = old_file.file.dup();
  188. let new_file_flags = old_file.flags;
  189. let new_fd = fd_alloc.next_fd(files);
  190. inner.do_insert(new_fd, new_file_flags, new_file_data);
  191. Ok(new_fd)
  192. }
  193. /// Duplicates the file to a new file descriptor, returning the old file
  194. /// description to be dropped.
  195. fn dup_to_no_close(
  196. &self,
  197. old_fd: FD,
  198. new_fd: FD,
  199. fd_flags: FDFlags,
  200. ) -> KResult<Option<File>> {
  201. let mut inner = self.inner.lock();
  202. let (files, fd_alloc) = inner.split_borrow();
  203. let old_file = files.get_fd(old_fd).ok_or(EBADF)?;
  204. let new_file_data = old_file.file.dup();
  205. match files.entry(&new_fd) {
  206. Entry::Vacant(_) => {
  207. assert_eq!(new_fd, fd_alloc.allocate_fd(new_fd, files));
  208. inner.do_insert(new_fd, fd_flags, new_file_data);
  209. Ok(None)
  210. }
  211. Entry::Occupied(mut entry) => {
  212. let mut file = entry.remove().unwrap();
  213. file.flags = fd_flags;
  214. let old_file =
  215. core::mem::replace(&mut file.file, new_file_data);
  216. entry.insert(file);
  217. Ok(Some(old_file))
  218. }
  219. }
  220. }
  221. pub async fn dup_to(
  222. &self,
  223. old_fd: FD,
  224. new_fd: FD,
  225. flags: OpenFlags,
  226. ) -> KResult<FD> {
  227. if let Some(old_file) =
  228. self.dup_to_no_close(old_fd, new_fd, flags.as_fd_flags())?
  229. {
  230. old_file.close().await;
  231. }
  232. Ok(new_fd)
  233. }
  234. /// # Return
  235. /// `(read_fd, write_fd)`
  236. pub fn pipe(&self, flags: OpenFlags) -> KResult<(FD, FD)> {
  237. let mut inner = self.inner.lock();
  238. let (files, fd_alloc) = inner.split_borrow();
  239. let read_fd = fd_alloc.next_fd(files);
  240. let write_fd = fd_alloc.next_fd(files);
  241. let fdflag = flags.as_fd_flags();
  242. let (read_end, write_end) = Pipe::new(flags);
  243. inner.do_insert(read_fd, fdflag, read_end);
  244. inner.do_insert(write_fd, fdflag, write_end);
  245. Ok((read_fd, write_fd))
  246. }
  247. pub async fn open(
  248. &self,
  249. thread: &Thread,
  250. dentry: &Arc<Dentry>,
  251. flags: OpenFlags,
  252. perm: Permission,
  253. ) -> KResult<FD> {
  254. dentry.open_check(flags, perm).await?;
  255. let fdflag = flags.as_fd_flags();
  256. let inode = dentry.get_inode()?;
  257. match (flags.directory(), inode.format, flags.write()) {
  258. (true, Format::DIR, _) => {}
  259. (true, _, _) => return Err(ENOTDIR),
  260. (false, Format::DIR, true) => return Err(EISDIR),
  261. _ => {}
  262. }
  263. if flags.truncate() && flags.write() && inode.format == Format::REG {
  264. inode.truncate(0).await?;
  265. }
  266. let file = if inode.format == Format::CHR {
  267. let device = CharDevice::get(inode.devid()?).ok_or(ENXIO)?;
  268. device.open(thread, flags).await?
  269. } else {
  270. InodeFile::new(dentry.clone(), flags)
  271. };
  272. let mut inner = self.inner.lock();
  273. let (files, fd_alloc) = inner.split_borrow();
  274. let fd = fd_alloc.next_fd(files);
  275. inner.do_insert(fd, fdflag, file);
  276. Ok(fd)
  277. }
  278. pub fn fcntl(&self, fd: FD, cmd: u32, arg: usize) -> KResult<usize> {
  279. let mut inner = self.inner.lock();
  280. let (files, fd_alloc) = inner.split_borrow();
  281. let mut cursor = files.find_mut(&fd);
  282. let ret = match cmd {
  283. F_DUPFD | F_DUPFD_CLOEXEC => {
  284. let ofile = cursor.get().ok_or(EBADF)?;
  285. let cloexec =
  286. cmd == F_DUPFD_CLOEXEC || ofile.flags.close_on_exec();
  287. let flags = cloexec
  288. .then_some(FDFlags::FD_CLOEXEC)
  289. .unwrap_or(FDFlags::empty());
  290. let new_file_data = ofile.file.dup();
  291. let new_fd = fd_alloc.allocate_fd(FD(arg as u32), files);
  292. inner.do_insert(new_fd, flags, new_file_data);
  293. new_fd.0 as usize
  294. }
  295. F_GETFD => cursor.get().ok_or(EBADF)?.flags.bits() as usize,
  296. F_SETFD => {
  297. let mut ofile = cursor.remove().ok_or(EBADF)?;
  298. ofile.flags = FDFlags::from_bits_truncate(arg as u32);
  299. cursor.insert(ofile);
  300. 0
  301. }
  302. F_GETFL => {
  303. cursor.get().ok_or(EBADF)?.file.get_flags().bits() as usize
  304. }
  305. F_SETFL => {
  306. cursor
  307. .get()
  308. .ok_or(EBADF)?
  309. .file
  310. .set_flags(OpenFlags::from_bits_retain(arg as u32));
  311. 0
  312. }
  313. _ => unimplemented!("fcntl: cmd={}", cmd),
  314. };
  315. Ok(ret)
  316. }
  317. }
  318. impl FileArrayInner {
  319. fn get(&mut self, fd: FD) -> Option<File> {
  320. self.files.get_fd(fd).map(|open| open.file.clone())
  321. }
  322. /// Insert a file description to the file array.
  323. fn do_insert(&mut self, fd: FD, flags: FDFlags, file: File) {
  324. match self.files.entry(&fd) {
  325. Entry::Occupied(_) => {
  326. panic!(
  327. "File descriptor {fd:?} already exists in the file array."
  328. );
  329. }
  330. Entry::Vacant(insert_cursor) => {
  331. insert_cursor.insert(OpenFile::new(fd, flags, file));
  332. }
  333. }
  334. }
  335. fn split_borrow(
  336. &mut self,
  337. ) -> (&mut RBTree<OpenFileAdapter>, &mut FDAllocator) {
  338. let Self { files, fd_alloc } = self;
  339. (files, fd_alloc)
  340. }
  341. }
  342. impl FD {
  343. pub const AT_FDCWD: FD = FD(-100i32 as u32);
  344. }
  345. impl core::fmt::Debug for FD {
  346. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  347. match self {
  348. &Self::AT_FDCWD => f.write_str("FD(AT_FDCWD)"),
  349. FD(no) => f.debug_tuple("FD").field(&no).finish(),
  350. }
  351. }
  352. }
  353. impl FromSyscallArg for FD {
  354. fn from_arg(value: usize) -> Self {
  355. Self(value as u32)
  356. }
  357. }
  358. impl SyscallRetVal for FD {
  359. fn into_retval(self) -> Option<usize> {
  360. Some(self.0 as usize)
  361. }
  362. }
  363. trait FilesExt {
  364. fn get_fd(&self, fd: FD) -> Option<&OpenFile>;
  365. fn pick<P>(&mut self, pred: P) -> Self
  366. where
  367. P: FnMut(&OpenFile) -> bool;
  368. }
  369. impl FilesExt for RBTree<OpenFileAdapter> {
  370. fn get_fd(&self, fd: FD) -> Option<&OpenFile> {
  371. self.find(&fd).get()
  372. }
  373. fn pick<P>(&mut self, mut pred: P) -> Self
  374. where
  375. P: FnMut(&OpenFile) -> bool,
  376. {
  377. let mut picked = RBTree::new(OpenFileAdapter::new());
  378. // TODO: might be better if we start picking from somewhere else
  379. // or using a different approach.
  380. let mut cursor = self.front_mut();
  381. while let Some(open_file) = cursor.get() {
  382. if !pred(open_file) {
  383. cursor.move_next();
  384. continue;
  385. }
  386. picked.insert(cursor.remove().unwrap());
  387. cursor.move_next();
  388. }
  389. picked
  390. }
  391. }