keos_project5/page_cache/
overlaying.rs1use super::PageCache;
4use alloc::{string::String, vec::Vec};
5use keos::{
6 fs::{FileBlockNumber, InodeNumber, traits::FileSystem},
7 mm::Page,
8 sync::atomic::AtomicUsize,
9};
10
11pub struct Directory<FS: FileSystem + 'static>(keos::fs::Directory, PageCache<FS>);
13
14impl<FS: FileSystem> keos::fs::traits::Directory for Directory<FS> {
15 fn ino(&self) -> InodeNumber {
16 self.0.ino()
17 }
18
19 fn size(&self) -> usize {
20 self.0.size()
21 }
22
23 fn link_count(&self) -> usize {
24 self.0.link_count()
25 }
26
27 fn open_entry(&self, entry: &str) -> Result<keos::fs::File, keos::KernelError> {
28 self.0.open(entry).map(|en| match en {
29 keos::fs::File::RegularFile(r) => {
30 keos::fs::File::RegularFile(keos::fs::RegularFile::new(RegularFile {
31 size: AtomicUsize::new(r.size()),
32 file: r,
33 cache: self.1.clone(),
34 }))
35 }
36 keos::fs::File::Directory(d) => {
37 keos::fs::File::Directory(keos::fs::Directory::new(Directory(d, self.1.clone())))
38 }
39 })
40 }
41
42 fn create_entry(&self, entry: &str, is_dir: bool) -> Result<keos::fs::File, keos::KernelError> {
43 self.0.create(entry, is_dir).map(|en| match en {
44 keos::fs::File::RegularFile(r) => {
45 keos::fs::File::RegularFile(keos::fs::RegularFile::new(RegularFile {
46 size: AtomicUsize::new(r.size()),
47 file: r,
48 cache: self.1.clone(),
49 }))
50 }
51 keos::fs::File::Directory(d) => {
52 keos::fs::File::Directory(keos::fs::Directory::new(Directory(d, self.1.clone())))
53 }
54 })
55 }
56
57 fn unlink_entry(&self, entry: &str) -> Result<(), keos::KernelError> {
58 self.0.open(entry).map(|en| {
59 if let keos::fs::File::RegularFile(r) = en {
60 let mut guard = self.1.0.inner.lock();
62 guard.do_unlink(r);
63 guard.unlock();
64 }
65 })?;
66
67 self.0.unlink(entry)
68 }
69
70 fn read_dir(&self) -> Result<Vec<(InodeNumber, String)>, keos::KernelError> {
71 self.0.read_dir()
72 }
73
74 fn removed(&self) -> Result<&keos::sync::atomic::AtomicBool, keos::KernelError> {
75 self.0.removed()
76 }
77}
78
79pub struct RegularFile<FS: FileSystem> {
81 file: keos::fs::RegularFile,
82 size: AtomicUsize,
83 cache: PageCache<FS>,
84}
85
86impl<FS: FileSystem> keos::fs::traits::RegularFile for RegularFile<FS> {
87 fn ino(&self) -> InodeNumber {
88 self.file.0.ino()
89 }
90
91 fn size(&self) -> usize {
92 self.size.load()
93 }
94
95 fn read(&self, fba: FileBlockNumber, buf: &mut [u8; 4096]) -> Result<bool, keos::KernelError> {
96 self.cache.read(&self.file, fba, buf)
97 }
98
99 fn write(
100 &self,
101 fba: FileBlockNumber,
102 buf: &[u8; 4096],
103 min_size: usize,
104 ) -> Result<(), keos::KernelError> {
105 if self.size() < min_size {
106 self.size.store(min_size);
107 let mut guard = self.cache.0.inner.lock();
108 let result = guard.do_write(self.file.clone(), fba, buf, min_size);
109 guard.unlock();
110 result
111 } else {
112 let mut guard = self.cache.0.inner.lock();
113 let result = guard.do_write(self.file.clone(), fba, buf, self.size.load());
114 guard.unlock();
115 result
116 }
117 }
118
119 fn writeback(&self) -> Result<(), keos::KernelError> {
120 let mut guard = self.cache.0.inner.lock();
121 let result = guard.do_writeback(self.file.clone());
122 guard.unlock();
123 result
124 }
125
126 fn mmap(&self, fba: FileBlockNumber) -> Result<Page, keos::KernelError> {
127 let mut guard = self.cache.0.inner.lock();
128 let result = guard.do_mmap(self.file.clone(), fba);
129 guard.unlock();
130 result
131 }
132}
133
134impl<FS: FileSystem + 'static> FileSystem for PageCache<FS> {
135 fn root(&self) -> Option<keos::fs::Directory> {
136 self.0
137 .fs
138 .root()
139 .map(|n| keos::fs::Directory::new(Directory(n, Self(self.0.clone()))))
140 }
141}