Skip to content

Commit a4eef02

Browse files
committed
refactor starry fs
1 parent b8b8944 commit a4eef02

File tree

5 files changed

+199
-129
lines changed

5 files changed

+199
-129
lines changed

api/src/file/fs.rs

Lines changed: 173 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ use alloc::{
1010
};
1111
use axerrno::{LinuxError, LinuxResult};
1212
use axfs::fops::DirEntry;
13-
use axio::PollState;
14-
use axio::SeekFrom;
13+
use axio::{PollState, SeekFrom};
1514
use axsync::{Mutex, MutexGuard};
1615
use linux_raw_sys::general::S_IFDIR;
1716

@@ -20,174 +19,240 @@ use super::{
2019
page_cache::{PageCache, page_cache_manager},
2120
};
2221

23-
/// File wrapper for `axfs::fops::File`.
24-
pub struct File {
25-
inner: Option<Arc<Mutex<axfs::fops::File>>>,
26-
path: String,
27-
is_direct: bool,
28-
cache: Weak<PageCache>,
29-
offset: AtomicUsize,
30-
size: AtomicUsize,
22+
/// File wrapper for `axfs::fops::File` with two variants.
23+
pub enum File {
24+
Direct {
25+
path: String,
26+
inner: Arc<Mutex<axfs::fops::File>>,
27+
},
28+
Cached {
29+
path: String,
30+
size: AtomicUsize,
31+
offset: AtomicUsize,
32+
cache: Weak<PageCache>,
33+
},
3134
}
3235

3336
impl File {
34-
pub fn new(
35-
inner: Option<Arc<Mutex<axfs::fops::File>>>,
36-
path: String,
37-
is_direct: bool,
38-
cache: Weak<PageCache>,
39-
) -> Self {
40-
debug!("Starry-api open file {}", path);
37+
pub fn new_file_direct(path: String, inner: Arc<Mutex<axfs::fops::File>>) -> Self {
4138
let size = {
42-
if is_direct {
43-
let inner = inner.clone().unwrap();
44-
let inner = inner.lock();
45-
let metadata = inner.get_attr().unwrap();
46-
metadata.size() as usize
47-
} else {
48-
let cache = cache.upgrade().unwrap();
49-
cache.get_file_size()
50-
}
39+
let inner = inner.clone();
40+
let inner = inner.lock();
41+
let metadata = inner.get_attr().unwrap();
42+
metadata.size() as usize
5143
};
52-
Self {
44+
File::Direct {
45+
path,
5346
inner,
47+
}
48+
}
49+
50+
pub fn new_file_cached(path: String, cache: Weak<PageCache>) -> Self {
51+
let size = {
52+
let cache = cache.upgrade().unwrap();
53+
cache.file_size()
54+
};
55+
File::Cached {
5456
path,
55-
is_direct,
56-
cache,
57-
offset: AtomicUsize::new(0),
5857
size: AtomicUsize::new(size),
58+
offset: AtomicUsize::new(0),
59+
cache,
5960
}
6061
}
6162

62-
pub fn get_cache(&self) -> Arc<PageCache> {
63-
self.cache.upgrade().unwrap()
63+
pub fn size(&self) -> usize {
64+
match self {
65+
File::Direct { inner, .. } => {
66+
let inner = inner.lock();
67+
inner.get_attr().unwrap().size() as usize
68+
},
69+
File::Cached { size, .. } => {
70+
size.load(Ordering::Relaxed)
71+
}
72+
}
6473
}
6574

66-
pub fn get_size(&self) -> usize {
67-
self.size.load(Ordering::SeqCst)
75+
pub fn offset(&self) -> usize {
76+
match self {
77+
File::Direct { .. } => {
78+
panic!("Please use seek for File::Direc");
79+
},
80+
File::Cached { offset, .. } => {
81+
offset.load(Ordering::Relaxed)
82+
}
83+
}
6884
}
6985

7086
/// Get the path of the file.
71-
pub fn path(&self) -> &str {
72-
&self.path
87+
pub fn path(&self) -> &String {
88+
match self {
89+
File::Direct { path, .. } | File::Cached { path, .. } => path,
90+
}
7391
}
7492

75-
/// Get the inner node of the file.
93+
/// Get the cache of the file. Only available in File::Cached.
94+
pub fn cache(&self) -> Arc<PageCache> {
95+
match self {
96+
File::Direct { .. } => {
97+
panic!("File::Direct doesn't have cache.");
98+
}
99+
File::Cached { cache, .. } => cache.upgrade().unwrap(),
100+
}
101+
}
102+
103+
/// Get the inner node of the file. Only available in File::Direct.
76104
fn inner(&self) -> MutexGuard<axfs::fops::File> {
77-
self.inner.as_ref().unwrap().lock()
105+
match self {
106+
File::Direct { inner, .. } => inner.lock(),
107+
File::Cached { .. } => {
108+
panic!("File::Cached doesn't have inner.");
109+
}
110+
}
78111
}
79112

80113
pub fn seek(&self, pos: SeekFrom) -> LinuxResult<isize> {
81-
if self.is_direct {
82-
match self.inner().seek(pos) {
83-
Ok(pos) => return Ok(pos as isize),
84-
Err(e) => {
85-
error!("Seek failed: {}", e);
86-
return Err(LinuxError::EINVAL);
114+
match self {
115+
File::Direct { .. } => {
116+
let mut inner = self.inner();
117+
match inner.seek(pos) {
118+
Ok(pos) => Ok(pos as isize),
119+
Err(e) => {
120+
error!("Seek failed: {}", e);
121+
Err(LinuxError::EINVAL)
122+
}
87123
}
88124
}
125+
File::Cached { offset, .. } => {
126+
let size = self.size() as u64;
127+
let offset_val = offset.load(Ordering::Relaxed) as u64;
128+
let new_offset = match pos {
129+
SeekFrom::Start(pos) => Some(pos),
130+
SeekFrom::Current(off) => offset_val.checked_add_signed(off),
131+
SeekFrom::End(off) => size.checked_add_signed(off),
132+
}
133+
.unwrap_or(0);
134+
offset.store(new_offset as usize, Ordering::SeqCst);
135+
Ok(new_offset as isize)
136+
}
89137
}
90-
let size = self.size.load(Ordering::SeqCst) as u64;
91-
let offset = self.offset.load(Ordering::SeqCst) as u64;
92-
let new_offset = match pos {
93-
SeekFrom::Start(pos) => Some(pos),
94-
SeekFrom::Current(off) => offset.checked_add_signed(off),
95-
SeekFrom::End(off) => size.checked_add_signed(off),
96-
}
97-
.unwrap();
98-
self.offset.store(new_offset as usize, Ordering::SeqCst);
99-
Ok(new_offset as isize)
100138
}
101139

102140
pub fn fsync(&self) -> LinuxResult<usize> {
103-
if self.is_direct {
104-
return Ok(0);
141+
match self {
142+
File::Direct { .. } => Ok(0),
143+
File::Cached { .. } => {
144+
let cache = self.cache();
145+
Ok(cache.sync()?)
146+
}
105147
}
106-
let cache = self.get_cache();
107-
Ok(cache.sync()?)
108148
}
109149

110150
pub fn read_at(&self, buf: &mut [u8], offset: usize) -> LinuxResult<usize> {
111-
if self.is_direct {
112-
return Ok(self.inner().read_at(offset as u64, buf)?);
151+
match self {
152+
File::Direct { .. } => {
153+
let inner = self.inner();
154+
Ok(inner.read_at(offset as u64, buf)?)
155+
}
156+
File::Cached { .. } => {
157+
let cache = self.cache();
158+
Ok(cache.read_at(offset, buf))
159+
}
113160
}
114-
115-
let cache = self.get_cache();
116-
Ok(cache.read_at(offset, buf))
117161
}
118162

119163
pub fn write_at(&self, buf: &[u8], offset: usize) -> LinuxResult<usize> {
120-
if self.is_direct {
121-
return Ok(self.inner().write_at(offset as u64, buf)?);
164+
match self {
165+
File::Direct { .. } => {
166+
let inner = self.inner();
167+
Ok(inner.write_at(offset as u64, buf)?)
168+
}
169+
File::Cached { .. } => {
170+
let cache = self.cache();
171+
Ok(cache.write_at(offset, buf))
172+
}
122173
}
123-
124-
let cache = self.get_cache();
125-
Ok(cache.write_at(offset, buf))
126174
}
127175

128176
pub fn truncate(&self, offset: usize) -> LinuxResult<usize> {
129-
if self.is_direct {
130-
self.inner().truncate(offset as u64)?;
131-
return Ok(offset);
177+
match self {
178+
File::Direct { .. } => {
179+
let inner = self.inner();
180+
inner.truncate(offset as u64)?;
181+
Ok(offset)
182+
}
183+
File::Cached { .. } => {
184+
let cache = self.cache();
185+
Ok(cache.truncate(offset) as usize)
186+
}
132187
}
133-
let cache = self.get_cache();
134-
Ok(cache.truncate(offset) as usize)
135188
}
136189
}
137190

138191
impl Drop for File {
139192
fn drop(&mut self) {
140-
debug!("Starry-api drop file {}", self.path);
141-
if !self.is_direct {
193+
debug!("Starry-api drop file {}", self.path());
194+
if let File::Cached { .. } = self {
142195
let cache_manager = page_cache_manager();
143-
cache_manager.close_page_cache(&self.path);
196+
cache_manager.close_page_cache(self.path());
144197
}
145198
}
146199
}
147200

148201
impl FileLike for File {
149202
fn read(&self, buf: &mut [u8]) -> LinuxResult<usize> {
150-
if self.is_direct {
151-
return Ok(self.inner().read(buf)?);
203+
match self {
204+
File::Direct { .. } => {
205+
let mut inner = self.inner();
206+
Ok(inner.read(buf)?)
207+
}
208+
File::Cached { offset, .. } => {
209+
let cache = self.cache();
210+
let offset_val = offset.load(Ordering::SeqCst);
211+
let len = cache.read_at(offset_val, buf);
212+
offset.fetch_add(len, Ordering::SeqCst);
213+
Ok(len)
214+
}
152215
}
153-
154-
let cache = self.get_cache();
155-
let offset = self.offset.load(Ordering::SeqCst);
156-
let len = cache.write_at(offset, buf);
157-
self.offset.fetch_add(len, Ordering::SeqCst);
158-
Ok(len)
159216
}
160217

161218
fn write(&self, buf: &[u8]) -> LinuxResult<usize> {
162-
if self.is_direct {
163-
return Ok(self.inner().write(buf)?);
219+
match self {
220+
File::Direct { .. } => {
221+
let mut inner = self.inner();
222+
Ok(inner.write(buf)?)
223+
}
224+
File::Cached { offset, size, .. } => {
225+
let cache = self.cache();
226+
let offset_val = offset.load(Ordering::SeqCst);
227+
let len = cache.write_at(offset_val, buf);
228+
offset.fetch_add(len, Ordering::SeqCst);
229+
size.fetch_max(offset_val + len, Ordering::SeqCst);
230+
Ok(len)
231+
}
164232
}
165-
166-
let cache = self.get_cache();
167-
let offset = self.offset.load(Ordering::SeqCst);
168-
let len = cache.write_at(offset, buf);
169-
self.offset.fetch_add(len, Ordering::SeqCst);
170-
self.size.fetch_max(offset + len, Ordering::SeqCst);
171-
Ok(len)
172233
}
173234

174235
fn stat(&self) -> LinuxResult<Kstat> {
175-
if !self.is_direct {
176-
let cache = self.get_cache();
177-
return cache.stat();
236+
match self {
237+
File::Direct { .. } => {
238+
let inner = self.inner();
239+
let metadata = inner.get_attr()?;
240+
let ty = metadata.file_type() as u8;
241+
let perm = metadata.perm().bits() as u32;
242+
let size = self.size();
243+
Ok(Kstat {
244+
mode: ((ty as u32) << 12) | perm,
245+
size: size as u64,
246+
blocks: metadata.blocks(),
247+
blksize: 512,
248+
..Default::default()
249+
})
250+
}
251+
File::Cached { .. } => {
252+
let cache = self.cache();
253+
cache.stat()
254+
}
178255
}
179-
180-
let metadata = self.inner().get_attr()?;
181-
let ty = metadata.file_type() as u8;
182-
let perm = metadata.perm().bits() as u32;
183-
let size = self.size.load(Ordering::SeqCst);
184-
Ok(Kstat {
185-
mode: ((ty as u32) << 12) | perm,
186-
size: size as u64,
187-
blocks: metadata.blocks(),
188-
blksize: 512,
189-
..Default::default()
190-
})
191256
}
192257

193258
fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {

api/src/file/page_cache.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ impl Page {
191191
}
192192

193193
/// 查询本页面的实际起始物理地址
194-
fn get_phys_addr(&self) -> PhysAddr {
194+
fn phys_addr(&self) -> PhysAddr {
195195
let vaddr = self.inner.start_vaddr();
196196
assert!(
197197
// 保证该页在线性映射区
@@ -307,7 +307,7 @@ impl Page {
307307
"unmap virt page {} ({}, {:#x})",
308308
self.page_id, pid, aligned_virt_page
309309
);
310-
310+
311311
let mut aspace = curr.task_ext().process_data().aspace.lock();
312312
aspace.force_unmap_page(aligned_virt_page);
313313
flush_tlb(Some(aligned_virt_page));
@@ -624,7 +624,7 @@ impl PageCache {
624624
}
625625

626626
/// 获取文件大小
627-
pub fn get_file_size(&self) -> usize {
627+
pub fn file_size(&self) -> usize {
628628
self.size.load(Ordering::SeqCst)
629629
}
630630

@@ -868,7 +868,7 @@ impl PageCacheManager {
868868
// 主要用于 mmap 相关函数,需要根据 fd 找到对应的 page cache
869869
pub fn fd_cache(&self, fd: i32) -> Arc<PageCache> {
870870
let file = File::from_fd(fd).unwrap();
871-
file.get_cache()
871+
file.cache()
872872
}
873873
}
874874

0 commit comments

Comments
 (0)