-
Notifications
You must be signed in to change notification settings - Fork 36
文件页缓存 #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
文件页缓存 #53
Changes from 18 commits
b3682c9
e072ce5
c978b61
32cf91a
6fffc95
08ec69b
864dc97
36bd34f
a971d0b
b490c98
06b58d6
86f78d1
263e3af
b4a2264
a087ccc
4fad43b
77e4d9f
b8b8944
a4eef02
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,189 @@ | ||
use core::{any::Any, ffi::c_int}; | ||
use core::{ | ||
any::Any, | ||
ffi::c_int, | ||
sync::atomic::{AtomicUsize, Ordering}, | ||
}; | ||
|
||
use alloc::{string::String, sync::Arc}; | ||
use alloc::{ | ||
string::String, | ||
sync::{Arc, Weak}, | ||
}; | ||
use axerrno::{LinuxError, LinuxResult}; | ||
use axfs::fops::DirEntry; | ||
use axio::PollState; | ||
use axio::SeekFrom; | ||
use axsync::{Mutex, MutexGuard}; | ||
use linux_raw_sys::general::S_IFDIR; | ||
|
||
use super::{FileLike, Kstat, get_file_like}; | ||
use super::{ | ||
FileLike, Kstat, get_file_like, | ||
page_cache::{PageCache, page_cache_manager}, | ||
}; | ||
|
||
/// File wrapper for `axfs::fops::File`. | ||
pub struct File { | ||
inner: Mutex<axfs::fops::File>, | ||
inner: Option<Arc<Mutex<axfs::fops::File>>>, | ||
path: String, | ||
is_direct: bool, | ||
cache: Weak<PageCache>, | ||
offset: AtomicUsize, | ||
size: AtomicUsize, | ||
|
||
} | ||
|
||
impl File { | ||
pub fn new(inner: axfs::fops::File, path: String) -> Self { | ||
pub fn new( | ||
inner: Option<Arc<Mutex<axfs::fops::File>>>, | ||
path: String, | ||
is_direct: bool, | ||
cache: Weak<PageCache>, | ||
) -> Self { | ||
debug!("Starry-api open file {}", path); | ||
|
||
let size = { | ||
if is_direct { | ||
let inner = inner.clone().unwrap(); | ||
|
||
let inner = inner.lock(); | ||
let metadata = inner.get_attr().unwrap(); | ||
metadata.size() as usize | ||
} else { | ||
let cache = cache.upgrade().unwrap(); | ||
cache.get_file_size() | ||
} | ||
}; | ||
Self { | ||
inner: Mutex::new(inner), | ||
inner, | ||
path, | ||
is_direct, | ||
cache, | ||
offset: AtomicUsize::new(0), | ||
size: AtomicUsize::new(size), | ||
} | ||
} | ||
|
||
pub fn get_cache(&self) -> Arc<PageCache> { | ||
|
||
self.cache.upgrade().unwrap() | ||
} | ||
|
||
pub fn get_size(&self) -> usize { | ||
|
||
self.size.load(Ordering::SeqCst) | ||
} | ||
|
||
/// Get the path of the file. | ||
pub fn path(&self) -> &str { | ||
&self.path | ||
} | ||
|
||
/// Get the inner node of the file. | ||
pub fn inner(&self) -> MutexGuard<axfs::fops::File> { | ||
self.inner.lock() | ||
fn inner(&self) -> MutexGuard<axfs::fops::File> { | ||
self.inner.as_ref().unwrap().lock() | ||
} | ||
|
||
pub fn seek(&self, pos: SeekFrom) -> LinuxResult<isize> { | ||
if self.is_direct { | ||
match self.inner().seek(pos) { | ||
Ok(pos) => return Ok(pos as isize), | ||
Err(e) => { | ||
error!("Seek failed: {}", e); | ||
return Err(LinuxError::EINVAL); | ||
} | ||
} | ||
} | ||
let size = self.size.load(Ordering::SeqCst) as u64; | ||
|
||
let offset = self.offset.load(Ordering::SeqCst) as u64; | ||
|
||
let new_offset = match pos { | ||
SeekFrom::Start(pos) => Some(pos), | ||
SeekFrom::Current(off) => offset.checked_add_signed(off), | ||
SeekFrom::End(off) => size.checked_add_signed(off), | ||
} | ||
.unwrap(); | ||
self.offset.store(new_offset as usize, Ordering::SeqCst); | ||
Ok(new_offset as isize) | ||
} | ||
|
||
pub fn fsync(&self) -> LinuxResult<usize> { | ||
if self.is_direct { | ||
return Ok(0); | ||
} | ||
let cache = self.get_cache(); | ||
Ok(cache.sync()?) | ||
} | ||
|
||
pub fn read_at(&self, buf: &mut [u8], offset: usize) -> LinuxResult<usize> { | ||
if self.is_direct { | ||
return Ok(self.inner().read_at(offset as u64, buf)?); | ||
} | ||
|
||
let cache = self.get_cache(); | ||
Ok(cache.read_at(offset, buf)) | ||
} | ||
|
||
pub fn write_at(&self, buf: &[u8], offset: usize) -> LinuxResult<usize> { | ||
if self.is_direct { | ||
return Ok(self.inner().write_at(offset as u64, buf)?); | ||
} | ||
|
||
let cache = self.get_cache(); | ||
Ok(cache.write_at(offset, buf)) | ||
} | ||
|
||
pub fn truncate(&self, offset: usize) -> LinuxResult<usize> { | ||
if self.is_direct { | ||
self.inner().truncate(offset as u64)?; | ||
return Ok(offset); | ||
} | ||
let cache = self.get_cache(); | ||
Ok(cache.truncate(offset) as usize) | ||
} | ||
} | ||
|
||
impl Drop for File { | ||
fn drop(&mut self) { | ||
debug!("Starry-api drop file {}", self.path); | ||
if !self.is_direct { | ||
let cache_manager = page_cache_manager(); | ||
cache_manager.close_page_cache(&self.path); | ||
} | ||
} | ||
} | ||
|
||
impl FileLike for File { | ||
fn read(&self, buf: &mut [u8]) -> LinuxResult<usize> { | ||
Ok(self.inner().read(buf)?) | ||
if self.is_direct { | ||
return Ok(self.inner().read(buf)?); | ||
} | ||
|
||
let cache = self.get_cache(); | ||
let offset = self.offset.load(Ordering::SeqCst); | ||
let len = cache.write_at(offset, buf); | ||
|
||
self.offset.fetch_add(len, Ordering::SeqCst); | ||
Ok(len) | ||
} | ||
|
||
fn write(&self, buf: &[u8]) -> LinuxResult<usize> { | ||
Ok(self.inner().write(buf)?) | ||
if self.is_direct { | ||
return Ok(self.inner().write(buf)?); | ||
} | ||
|
||
let cache = self.get_cache(); | ||
let offset = self.offset.load(Ordering::SeqCst); | ||
let len = cache.write_at(offset, buf); | ||
self.offset.fetch_add(len, Ordering::SeqCst); | ||
self.size.fetch_max(offset + len, Ordering::SeqCst); | ||
Ok(len) | ||
} | ||
|
||
fn stat(&self) -> LinuxResult<Kstat> { | ||
if !self.is_direct { | ||
let cache = self.get_cache(); | ||
return cache.stat(); | ||
} | ||
|
||
let metadata = self.inner().get_attr()?; | ||
let ty = metadata.file_type() as u8; | ||
let perm = metadata.perm().bits() as u32; | ||
|
||
let size = self.size.load(Ordering::SeqCst); | ||
Ok(Kstat { | ||
mode: ((ty as u32) << 12) | perm, | ||
size: metadata.size(), | ||
size: size as u64, | ||
blocks: metadata.blocks(), | ||
blksize: 512, | ||
..Default::default() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merge it with
axio::PollState