filearray.rs 13 KB

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