file.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. use alloc::collections::btree_map::BTreeMap;
  2. use alloc::sync::Arc;
  3. use super::TmpFs;
  4. use crate::io::{Buffer, Stream};
  5. use crate::kernel::mem::{CachePage, PageCache, PageOffset};
  6. use crate::kernel::timer::Instant;
  7. use crate::kernel::vfs::inode::{Ino, InodeInfo, InodeOps, InodeUse, WriteOffset};
  8. use crate::kernel::vfs::types::{DeviceId, Format, Mode, Permission};
  9. use crate::kernel::vfs::{SbRef, SbUse};
  10. use crate::prelude::KResult;
  11. pub struct FileInode;
  12. impl FileInode {
  13. pub fn new(ino: Ino, sb: SbRef<TmpFs>, size: usize, perm: Permission) -> InodeUse {
  14. let now = Instant::now();
  15. InodeUse::new(
  16. sb,
  17. ino,
  18. Format::REG,
  19. InodeInfo {
  20. size: size as _,
  21. nlink: 1,
  22. uid: 0,
  23. gid: 0,
  24. perm,
  25. atime: now,
  26. ctime: now,
  27. mtime: now,
  28. },
  29. Self,
  30. )
  31. }
  32. }
  33. impl InodeOps for FileInode {
  34. type SuperBlock = TmpFs;
  35. async fn read(
  36. &self,
  37. _: SbUse<Self::SuperBlock>,
  38. inode: &InodeUse,
  39. buffer: &mut dyn Buffer,
  40. offset: usize,
  41. ) -> KResult<usize> {
  42. let _lock = inode.rwsem.read().await;
  43. inode.get_page_cache().read(buffer, offset).await
  44. }
  45. async fn write(
  46. &self,
  47. _: SbUse<Self::SuperBlock>,
  48. inode: &InodeUse,
  49. stream: &mut dyn Stream,
  50. offset: WriteOffset<'_>,
  51. ) -> KResult<usize> {
  52. let _lock = inode.rwsem.write().await;
  53. let mut store_new_end = None;
  54. let offset = match offset {
  55. WriteOffset::Position(offset) => offset,
  56. WriteOffset::End(end) => {
  57. store_new_end = Some(end);
  58. // `info.size` won't change since we are holding the write lock.
  59. inode.info.lock().size as usize
  60. }
  61. };
  62. let page_cache = inode.get_page_cache();
  63. if Arc::strong_count(&page_cache) == 1 {
  64. // XXX: A temporary workaround here. Change this ASAP...
  65. // Prevent the page cache from being dropped during the write.
  66. let _ = Arc::into_raw(page_cache.clone());
  67. }
  68. let wrote = page_cache.write(stream, offset).await?;
  69. let cursor_end = offset + wrote;
  70. if let Some(store_end) = store_new_end {
  71. *store_end = cursor_end;
  72. }
  73. Ok(wrote)
  74. }
  75. async fn truncate(
  76. &self,
  77. _: SbUse<Self::SuperBlock>,
  78. inode: &InodeUse,
  79. length: usize,
  80. ) -> KResult<()> {
  81. let _lock = inode.rwsem.write().await;
  82. let now = Instant::now();
  83. let mut info = inode.info.lock();
  84. info.mtime = now;
  85. info.ctime = now;
  86. info.size = length as u64;
  87. Ok(())
  88. }
  89. async fn chmod(
  90. &self,
  91. _sb: SbUse<Self::SuperBlock>,
  92. inode: &InodeUse,
  93. perm: Permission,
  94. ) -> KResult<()> {
  95. let mut info = inode.info.lock();
  96. info.perm = perm;
  97. info.ctime = Instant::now();
  98. Ok(())
  99. }
  100. async fn read_page(
  101. &self,
  102. _: SbUse<Self::SuperBlock>,
  103. _: &InodeUse,
  104. page: &mut CachePage,
  105. _: PageOffset,
  106. ) -> KResult<()> {
  107. page.as_bytes_mut().fill(0);
  108. Ok(())
  109. }
  110. async fn write_page(
  111. &self,
  112. _: SbUse<Self::SuperBlock>,
  113. _: &InodeUse,
  114. _: &mut CachePage,
  115. _: PageOffset,
  116. ) -> KResult<()> {
  117. // XXX: actually we should refuse to do the writeback.
  118. // think of a way to inform that of the page cache.
  119. Ok(())
  120. }
  121. async fn write_begin<'a>(
  122. &self,
  123. _: SbUse<Self::SuperBlock>,
  124. _: &InodeUse,
  125. page_cache: &PageCache,
  126. pages: &'a mut BTreeMap<PageOffset, CachePage>,
  127. offset: usize,
  128. _: usize,
  129. ) -> KResult<&'a mut CachePage> {
  130. // TODO: Remove dependency on `page_cache`.
  131. page_cache
  132. .get_page_locked(pages, PageOffset::from_byte_floor(offset))
  133. .await
  134. }
  135. async fn write_end(
  136. &self,
  137. _: SbUse<Self::SuperBlock>,
  138. inode: &InodeUse,
  139. _: &PageCache,
  140. _: &mut BTreeMap<PageOffset, CachePage>,
  141. offset: usize,
  142. _: usize,
  143. copied: usize,
  144. ) -> KResult<()> {
  145. let now = Instant::now();
  146. let mut info = inode.info.lock();
  147. info.mtime = now;
  148. info.ctime = now;
  149. info.size = info.size.max((offset + copied) as u64);
  150. Ok(())
  151. }
  152. }
  153. pub struct DeviceInode {
  154. is_block: bool,
  155. devid: DeviceId,
  156. }
  157. impl DeviceInode {
  158. pub fn new(ino: Ino, sb: SbRef<TmpFs>, mode: Mode, devid: DeviceId) -> InodeUse {
  159. let now = Instant::now();
  160. InodeUse::new(
  161. sb,
  162. ino,
  163. mode.format(),
  164. InodeInfo {
  165. size: 0,
  166. nlink: 1,
  167. uid: 0,
  168. gid: 0,
  169. perm: Permission::new(mode.non_format_bits()),
  170. atime: now,
  171. ctime: now,
  172. mtime: now,
  173. },
  174. Self {
  175. is_block: mode.format() == Format::BLK,
  176. devid,
  177. },
  178. )
  179. }
  180. }
  181. impl InodeOps for DeviceInode {
  182. type SuperBlock = TmpFs;
  183. async fn chmod(
  184. &self,
  185. _sb: SbUse<Self::SuperBlock>,
  186. inode: &InodeUse,
  187. perm: Permission,
  188. ) -> KResult<()> {
  189. let mut info = inode.info.lock();
  190. info.perm = perm;
  191. info.ctime = Instant::now();
  192. Ok(())
  193. }
  194. fn devid(&self, _: SbUse<Self::SuperBlock>, _: &InodeUse) -> KResult<DeviceId> {
  195. Ok(self.devid)
  196. }
  197. }
  198. pub struct SymlinkInode {
  199. target: Arc<[u8]>,
  200. }
  201. impl SymlinkInode {
  202. pub fn new(ino: Ino, sb: SbRef<TmpFs>, target: Arc<[u8]>) -> InodeUse {
  203. let now = Instant::now();
  204. InodeUse::new(
  205. sb,
  206. ino,
  207. Format::LNK,
  208. InodeInfo {
  209. size: target.len() as _,
  210. nlink: 1,
  211. uid: 0,
  212. gid: 0,
  213. perm: Permission::new(0o777),
  214. atime: now,
  215. ctime: now,
  216. mtime: now,
  217. },
  218. Self { target },
  219. )
  220. }
  221. }
  222. impl InodeOps for SymlinkInode {
  223. type SuperBlock = TmpFs;
  224. async fn readlink(
  225. &self,
  226. _sb: SbUse<Self::SuperBlock>,
  227. _inode: &InodeUse,
  228. buffer: &mut dyn Buffer,
  229. ) -> KResult<usize> {
  230. buffer
  231. .fill(self.target.as_ref())
  232. .map(|result| result.allow_partial())
  233. }
  234. }