inode.rs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. use core::any::Any;
  2. use alloc::{
  3. collections::btree_map::{BTreeMap, Entry},
  4. sync::{Arc, Weak},
  5. };
  6. use bindings::{
  7. statx, EEXIST, EINVAL, EIO, STATX_ATIME, STATX_BLOCKS, STATX_CTIME,
  8. STATX_GID, STATX_INO, STATX_MODE, STATX_MTIME, STATX_NLINK, STATX_SIZE,
  9. STATX_TYPE, STATX_UID, S_IFMT,
  10. };
  11. use super::{
  12. dentry::Dentry, s_isblk, s_ischr, vfs::Vfs, DevId, ReadDirCallback,
  13. TimeSpec,
  14. };
  15. use crate::prelude::*;
  16. pub type Ino = u64;
  17. pub type ISize = u64;
  18. pub type Nlink = u64;
  19. pub type Uid = u32;
  20. pub type Gid = u32;
  21. pub type Mode = u32;
  22. #[repr(C)]
  23. pub struct InodeData {
  24. pub ino: Ino,
  25. pub size: ISize,
  26. pub nlink: Nlink,
  27. pub atime: TimeSpec,
  28. pub mtime: TimeSpec,
  29. pub ctime: TimeSpec,
  30. pub uid: Uid,
  31. pub gid: Gid,
  32. pub mode: Mode,
  33. }
  34. impl InodeData {
  35. pub fn new(ino: Ino) -> Self {
  36. Self {
  37. ino,
  38. size: 0,
  39. nlink: 0,
  40. atime: TimeSpec::new(),
  41. mtime: TimeSpec::new(),
  42. ctime: TimeSpec::new(),
  43. uid: 0,
  44. gid: 0,
  45. mode: 0,
  46. }
  47. }
  48. }
  49. #[allow(unused_variables)]
  50. pub trait Inode {
  51. fn idata(&self) -> &Mutex<InodeData>;
  52. fn vfs_weak(&self) -> Weak<Mutex<dyn Vfs>>;
  53. fn vfs_strong(&self) -> Option<Arc<Mutex<dyn Vfs>>>;
  54. fn as_any(&self) -> &dyn Any;
  55. fn readdir(
  56. &self,
  57. offset: usize,
  58. callback: &mut ReadDirCallback,
  59. ) -> KResult<usize>;
  60. fn statx(&self, stat: &mut statx, mask: u32) -> KResult<()> {
  61. let (fsdev, io_blksize) = {
  62. let vfs = self.vfs_strong().ok_or(EIO)?;
  63. let vfs = vfs.lock();
  64. (vfs.fs_devid(), vfs.io_blksize())
  65. };
  66. let devid = self.devid();
  67. let idata = self.idata().lock();
  68. if mask & STATX_NLINK != 0 {
  69. stat.stx_nlink = idata.nlink as _;
  70. stat.stx_mask |= STATX_NLINK;
  71. }
  72. if mask & STATX_ATIME != 0 {
  73. stat.stx_atime.tv_nsec = idata.atime.nsec as _;
  74. stat.stx_atime.tv_sec = idata.atime.sec as _;
  75. stat.stx_mask |= STATX_ATIME;
  76. }
  77. if mask & STATX_MTIME != 0 {
  78. stat.stx_mtime.tv_nsec = idata.mtime.nsec as _;
  79. stat.stx_mtime.tv_sec = idata.mtime.sec as _;
  80. stat.stx_mask |= STATX_MTIME;
  81. }
  82. if mask & STATX_CTIME != 0 {
  83. stat.stx_ctime.tv_nsec = idata.ctime.nsec as _;
  84. stat.stx_ctime.tv_sec = idata.ctime.sec as _;
  85. stat.stx_mask |= STATX_CTIME;
  86. }
  87. if mask & STATX_SIZE != 0 {
  88. stat.stx_size = idata.size as _;
  89. stat.stx_mask |= STATX_SIZE;
  90. }
  91. stat.stx_mode = 0;
  92. if mask & STATX_MODE != 0 {
  93. stat.stx_mode |= (idata.mode & !S_IFMT) as u16;
  94. stat.stx_mask |= STATX_MODE;
  95. }
  96. if mask & STATX_TYPE != 0 {
  97. stat.stx_mode |= (idata.mode & S_IFMT) as u16;
  98. if s_isblk(idata.mode) || s_ischr(idata.mode) {
  99. stat.stx_rdev_major = (devid? >> 8) & 0xff;
  100. stat.stx_rdev_minor = devid? & 0xff;
  101. }
  102. stat.stx_mask |= STATX_TYPE;
  103. }
  104. if mask & STATX_INO != 0 {
  105. stat.stx_ino = idata.ino as _;
  106. stat.stx_mask |= STATX_INO;
  107. }
  108. if mask & STATX_BLOCKS != 0 {
  109. stat.stx_blocks = (idata.size + 512 - 1) / 512;
  110. stat.stx_blksize = io_blksize as _;
  111. stat.stx_mask |= STATX_BLOCKS;
  112. }
  113. if mask & STATX_UID != 0 {
  114. stat.stx_uid = idata.uid as _;
  115. stat.stx_mask |= STATX_UID;
  116. }
  117. if mask & STATX_GID != 0 {
  118. stat.stx_gid = idata.gid as _;
  119. stat.stx_mask |= STATX_GID;
  120. }
  121. stat.stx_dev_major = (fsdev >> 8) & 0xff;
  122. stat.stx_dev_minor = fsdev & 0xff;
  123. // TODO: support more attributes
  124. stat.stx_attributes_mask = 0;
  125. Ok(())
  126. }
  127. fn creat(&self, at: &mut Dentry, mode: Mode) -> KResult<()> {
  128. Err(EINVAL)
  129. }
  130. fn mkdir(&self, at: &mut Dentry, mode: Mode) -> KResult<()> {
  131. Err(EINVAL)
  132. }
  133. fn mknod(&self, at: &mut Dentry, mode: Mode, dev: DevId) -> KResult<()> {
  134. Err(EINVAL)
  135. }
  136. fn unlink(&self, at: &mut Dentry) -> KResult<()> {
  137. Err(EINVAL)
  138. }
  139. fn symlink(&self, at: &mut Dentry, target: &str) -> KResult<()> {
  140. Err(EINVAL)
  141. }
  142. fn read(
  143. &self,
  144. buffer: &mut [u8],
  145. count: usize,
  146. offset: usize,
  147. ) -> KResult<usize> {
  148. Err(EINVAL)
  149. }
  150. fn write(&self, buffer: &[u8], offset: usize) -> KResult<usize> {
  151. Err(EINVAL)
  152. }
  153. fn devid(&self) -> KResult<DevId> {
  154. Err(EINVAL)
  155. }
  156. fn readlink(&self, buffer: &mut [u8]) -> KResult<usize> {
  157. Err(EINVAL)
  158. }
  159. fn truncate(&self, length: usize) -> KResult<()> {
  160. Err(EINVAL)
  161. }
  162. }
  163. pub struct InodeCache<Fs: Vfs> {
  164. cache: BTreeMap<Ino, Arc<dyn Inode>>,
  165. vfs: Weak<Mutex<Fs>>,
  166. }
  167. impl<Fs: Vfs> InodeCache<Fs> {
  168. pub fn new() -> Self {
  169. Self {
  170. cache: BTreeMap::new(),
  171. vfs: Weak::new(),
  172. }
  173. }
  174. pub fn get_vfs(&self) -> Weak<Mutex<Fs>> {
  175. self.vfs.clone()
  176. }
  177. pub fn set_vfs(&mut self, vfs: Weak<Mutex<Fs>>) {
  178. assert_eq!(self.vfs.upgrade().is_some(), false);
  179. self.vfs = vfs;
  180. }
  181. pub fn submit(
  182. &mut self,
  183. ino: Ino,
  184. inode: Arc<impl Inode + 'static>,
  185. ) -> KResult<Arc<dyn Inode>> {
  186. match self.cache.entry(ino) {
  187. Entry::Occupied(_) => Err(EEXIST), // TODO: log error to console
  188. Entry::Vacant(entry) => Ok(entry.insert(inode).clone()),
  189. }
  190. }
  191. pub fn get(&self, ino: Ino) -> Option<Arc<dyn Inode>> {
  192. self.cache.get(&ino).cloned()
  193. }
  194. pub fn free(&mut self, ino: Ino) {
  195. self.cache.remove(&ino);
  196. }
  197. }