Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit beb3cc5

Browse filesBrowse files
feat(vm): handle shared files properly
Signed-off-by: Anhad Singh <andypythonappdeveloper@gmail.com>
1 parent 9095737 commit beb3cc5
Copy full SHA for beb3cc5

File tree

Expand file treeCollapse file tree

9 files changed

+387
-66
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+387
-66
lines changed

‎src/aero_kernel/src/fs/block/mod.rs

Copy file name to clipboardExpand all lines: src/aero_kernel/src/fs/block/mod.rs
+71-22Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,32 +32,46 @@ use crate::fs::{FileSystem, Result};
3232

3333
use crate::fs::ext2::Ext2;
3434
use crate::mem::paging::*;
35+
use crate::mem::AddressSpace;
3536
use crate::utils::sync::Mutex;
3637

3738
use super::cache::{Cache, CacheArc, CacheItem, Cacheable};
3839
use super::devfs::{alloc_device_marker, Device};
3940
use super::inode::INodeInterface;
4041

41-
type PageCacheKey = (usize, usize); // (block device pointer, offset)
42-
type PageCacheItem = CacheArc<CacheItem<PageCacheKey, CachedPage>>;
42+
type PageCacheKey = (usize, usize); // (owner ptr, index)
43+
pub type PageCacheItem = CacheArc<CacheItem<PageCacheKey, CachedPage>>;
4344

44-
struct CachedPage {
45-
device: Weak<dyn CachedAccess>,
45+
struct DirtyMapping {
46+
addr_space: AddressSpace,
47+
addr: VirtAddr,
48+
}
49+
50+
pub struct CachedPage {
51+
owner: Weak<dyn CachedAccess>,
4652
offset: usize,
4753
page: PhysFrame,
4854
dirty: AtomicBool,
55+
dirty_mappings: Mutex<Vec<DirtyMapping>>,
4956
}
5057

5158
impl CachedPage {
52-
fn new(device: Weak<dyn CachedAccess>, offset: usize) -> Self {
53-
Self {
54-
device,
59+
fn new(owner: Weak<dyn CachedAccess>, offset: usize) -> Self {
60+
let k = Self {
61+
owner,
5562
offset,
5663
page: FRAME_ALLOCATOR
5764
.allocate_frame()
5865
.expect("page_cache: out of memory"),
5966
dirty: AtomicBool::new(false),
60-
}
67+
dirty_mappings: Mutex::new(Vec::new()),
68+
};
69+
// TODO: temporary hack. i mean this is fine but is there a cleaner way to do this. this is
70+
// required since when the VM for the process umaps a page that contains a cached page, it
71+
// will unmap this page which will decrease the refcnt to 0 and deallocate it.
72+
get_vm_frames().unwrap()[k.page.start_address().as_u64() as usize / 4096usize]
73+
.inc_ref_count();
74+
k
6175
}
6276

6377
fn data_mut(&self) -> &mut [MaybeUninit<u8>] {
@@ -72,10 +86,14 @@ impl CachedPage {
7286
unsafe { core::slice::from_raw_parts_mut(data_ptr, Size4KiB::SIZE as usize) }
7387
}
7488

75-
fn data_addr(&self) -> PhysAddr {
89+
pub fn data_addr(&self) -> PhysAddr {
7690
self.page.start_address()
7791
}
7892

93+
pub fn page(&self) -> PhysFrame {
94+
self.page
95+
}
96+
7997
fn make_key(device: &Weak<dyn CachedAccess>, offset: usize) -> PageCacheKey {
8098
(device.as_ptr().addr(), offset)
8199
}
@@ -85,26 +103,35 @@ impl CachedPage {
85103
self.dirty.load(Ordering::SeqCst)
86104
}
87105

88-
fn mark_dirty(&self) {
106+
pub fn mark_dirty(&self) {
107+
log::error!("marking dirty --------------------------------------");
89108
self.dirty.store(true, Ordering::SeqCst);
90109
}
91110

92111
fn device(&self) -> Arc<dyn CachedAccess> {
93-
self.device.upgrade().unwrap()
112+
self.owner.upgrade().unwrap()
94113
}
95114

96115
fn sync(&self) {
97116
if !self.is_dirty() {
98117
return;
99118
}
100119

101-
// Commit the changes made to the cache to the disk.
102-
let disk = self.device();
103-
120+
// Commit the changes made to the cache to the owner.
121+
let owner = self.device();
104122
let offset_bytes = self.offset * Size4KiB::SIZE as usize;
105-
let sector = offset_bytes / disk.block_size();
123+
owner.write_direct(offset_bytes, self.page);
124+
125+
for mut mapping in self.dirty_mappings.lock_irq().drain(..) {
126+
let mut offset_table = mapping.addr_space.offset_page_table();
127+
offset_table
128+
.unmap(Page::<Size4KiB>::containing_address(mapping.addr))
129+
.unwrap()
130+
.1
131+
.flush();
132+
}
106133

107-
disk.write_dma(sector, self.data_addr(), Size4KiB::SIZE as usize);
134+
self.dirty.store(false, Ordering::SeqCst);
108135
}
109136
}
110137

@@ -116,12 +143,12 @@ impl Drop for CachedPage {
116143

117144
impl Cacheable<PageCacheKey> for CachedPage {
118145
fn cache_key(&self) -> PageCacheKey {
119-
Self::make_key(&self.device, self.offset)
146+
Self::make_key(&self.owner, self.offset)
120147
}
121148
}
122149

123150
lazy_static::lazy_static! {
124-
static ref PAGE_CACHE: Arc<Cache<PageCacheKey, CachedPage>> = Cache::new();
151+
pub(in crate::fs) static ref PAGE_CACHE: Arc<Cache<PageCacheKey, CachedPage>> = Cache::new();
125152
}
126153

127154
impl Cache<PageCacheKey, CachedPage> {
@@ -145,16 +172,16 @@ impl Cache<PageCacheKey, CachedPage> {
145172
let device = device.upgrade().expect("page_cache: device dropped");
146173

147174
let aligned_offset = align_down(offset as u64, Size4KiB::SIZE) as usize;
148-
let sector = aligned_offset / device.block_size();
149-
150175
device
151-
.read_dma(sector, page.data_addr(), Size4KiB::SIZE as usize)
176+
.read_direct(aligned_offset, page.page())
152177
.expect("page_cache: failed to read block");
153178

154179
PAGE_CACHE.make_item_cached(page)
155180
}
156181
}
157182

183+
// TODO: cache hit miss stats
184+
158185
pub struct DirtyRef<T: Sized> {
159186
cache: PageCacheItem,
160187
ptr: *mut T,
@@ -202,9 +229,12 @@ pub trait BlockDeviceInterface: Send + Sync {
202229
fn write_block(&self, sector: usize, buf: &[u8]) -> Option<usize>;
203230
}
204231

205-
pub trait CachedAccess: BlockDeviceInterface {
232+
pub trait CachedAccess: Send + Sync {
206233
fn sref(&self) -> Weak<dyn CachedAccess>;
207234

235+
fn read_direct(&self, offset: usize, dest: PhysFrame) -> Option<usize>;
236+
fn write_direct(&self, offset: usize, src: PhysFrame) -> Option<usize>;
237+
208238
fn read(&self, mut offset: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
209239
let mut loc = 0;
210240

@@ -236,6 +266,9 @@ pub trait CachedAccess: BlockDeviceInterface {
236266
let mut loc = 0;
237267

238268
while loc < buffer.len() {
269+
// TODO: If it is not found in the page cache, then, when the write perfectly falls on
270+
// page size boundaries, the page is not even read from disk, but allocated and
271+
// immediately marked dirty.
239272
let page = PAGE_CACHE.get_page(&self.sref(), offset);
240273

241274
let page_offset = offset % Size4KiB::SIZE as usize;
@@ -318,6 +351,22 @@ impl CachedAccess for BlockDevice {
318351
fn sref(&self) -> Weak<dyn CachedAccess> {
319352
self.sref.clone()
320353
}
354+
355+
fn read_direct(&self, offset: usize, dest: PhysFrame) -> Option<usize> {
356+
self.dev.read_dma(
357+
offset / self.dev.block_size(),
358+
dest.start_address(),
359+
Size4KiB::SIZE as _,
360+
)
361+
}
362+
363+
fn write_direct(&self, offset: usize, src: PhysFrame) -> Option<usize> {
364+
self.dev.write_dma(
365+
offset / self.dev.block_size(),
366+
src.start_address(),
367+
Size4KiB::SIZE as _,
368+
)
369+
}
321370
}
322371

323372
impl INodeInterface for BlockDevice {}

‎src/aero_kernel/src/fs/devfs.rs

Copy file name to clipboardExpand all lines: src/aero_kernel/src/fs/devfs.rs
+25-1Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::mem::paging::*;
3131
use crate::rendy::RendyInfo;
3232

3333
use super::cache::{DirCacheItem, INodeCacheItem};
34-
use super::inode::{INodeInterface, PollFlags, PollTable};
34+
use super::inode::{INodeInterface, MMapPage, PollFlags, PollTable};
3535
use super::ramfs::RamFs;
3636
use super::{FileSystem, FileSystemError, Result, MOUNT_MANAGER};
3737

@@ -132,6 +132,10 @@ impl INodeInterface for DevINode {
132132
fn open(&self, handle: Arc<super::file_table::FileHandle>) -> Result<Option<DirCacheItem>> {
133133
self.0.inode().open(handle)
134134
}
135+
136+
fn mmap_v2(&self, offset: usize) -> Result<MMapPage> {
137+
self.0.inode().mmap_v2(offset)
138+
}
135139
}
136140

137141
/// Implementation of dev filesystem. (See the module-level documentation for more
@@ -357,6 +361,26 @@ impl INodeInterface for DevFb {
357361
.expect("/dev/fb: terminal not initialized")
358362
}
359363

364+
fn mmap_v2(&self, offset: usize) -> Result<MMapPage> {
365+
let rinfo = crate::rendy::get_rendy_info();
366+
367+
// Make sure we are in bounds.
368+
if offset > rinfo.byte_len || offset + Size4KiB::SIZE as usize > rinfo.byte_len {
369+
return Err(FileSystemError::NotSupported);
370+
}
371+
372+
let mut lock = crate::rendy::DEBUG_RENDY.get().unwrap().lock_irq();
373+
let fb = lock.get_framebuffer();
374+
375+
let fb_ptr = fb.as_ptr().cast::<u8>();
376+
let fb_ptr = unsafe { fb_ptr.add(offset) };
377+
let fb_phys_ptr = unsafe { fb_ptr.sub(crate::PHYSICAL_MEMORY_OFFSET.as_u64() as usize) };
378+
379+
Ok(MMapPage::Direct(PhysFrame::containing_address(unsafe {
380+
PhysAddr::new_unchecked(fb_phys_ptr as u64)
381+
})))
382+
}
383+
360384
fn ioctl(&self, command: usize, arg: usize) -> Result<usize> {
361385
match command {
362386
FBIOGET_VSCREENINFO => {

‎src/aero_kernel/src/fs/ext2/mod.rs

Copy file name to clipboardExpand all lines: src/aero_kernel/src/fs/ext2/mod.rs
+24-2Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ use crate::socket::SocketAddrRef;
3737

3838
use self::group_desc::GroupDescriptors;
3939

40-
use super::block::{self, BlockDevice, CachedAccess};
40+
use super::block::{self, BlockDevice, CachedAccess, PAGE_CACHE};
4141

4242
use super::cache::{DirCacheItem, INodeCacheItem};
4343
use super::path::PathBuf;
4444
use super::{cache, FileSystemError, Path};
4545

46-
use super::inode::{self, INodeInterface, Metadata, PollFlags, PollTable};
46+
use super::inode::{self, INodeInterface, MMapPage, Metadata, PollFlags, PollTable};
4747
use super::FileSystem;
4848

4949
pub struct INode {
@@ -358,6 +358,20 @@ impl INode {
358358
}
359359
}
360360

361+
impl CachedAccess for INode {
362+
fn sref(&self) -> Weak<dyn CachedAccess> {
363+
self.sref.clone()
364+
}
365+
366+
fn read_direct(&self, offset: usize, dest: PhysFrame) -> Option<usize> {
367+
INodeInterface::read_at(self, offset, dest.as_slice_mut()).ok()
368+
}
369+
370+
fn write_direct(&self, offset: usize, src: PhysFrame) -> Option<usize> {
371+
INodeInterface::write_at(self, offset, src.as_slice_mut()).ok()
372+
}
373+
}
374+
361375
impl INodeInterface for INode {
362376
fn weak_filesystem(&self) -> Option<Weak<dyn FileSystem>> {
363377
Some(self.fs.clone())
@@ -587,6 +601,14 @@ impl INodeInterface for INode {
587601
Ok(private_cp)
588602
}
589603

604+
// TODO: cleanup
605+
fn mmap_v2(&self, offset: usize) -> super::Result<MMapPage> {
606+
Ok(MMapPage::PageCache(PAGE_CACHE.get_page(
607+
&(self.sref.clone() as Weak<dyn CachedAccess>),
608+
offset,
609+
)))
610+
}
611+
590612
fn listen(&self, backlog: usize) -> Result<(), SyscallError> {
591613
if let Some(proxy) = self.proxy.as_ref() {
592614
return proxy.listen(backlog);

‎src/aero_kernel/src/fs/inode.rs

Copy file name to clipboardExpand all lines: src/aero_kernel/src/fs/inode.rs
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use crate::socket::{SocketAddr, SocketAddrRef};
3333
use crate::userland::scheduler;
3434
use crate::utils::sync::{BMutex, Mutex, WaitQueue};
3535

36+
use super::block::PageCacheItem;
3637
use super::cache::{Cacheable, CachedINode, DirCacheItem, INodeCacheItem};
3738
use super::devfs::DevINode;
3839
use super::file_table::FileHandle;
@@ -109,6 +110,11 @@ impl From<PollFlags> for PollEventFlags {
109110
}
110111
}
111112

113+
pub enum MMapPage {
114+
Direct(PhysFrame),
115+
PageCache(PageCacheItem),
116+
}
117+
112118
/// An inode describes a file. An inode structure holds metadata of the
113119
/// inode which includes its type, size, the number of links referring to it,
114120
/// and the list of blocks holding the file's content. For example device files,
@@ -234,6 +240,14 @@ pub trait INodeInterface: Send + Sync {
234240
Err(FileSystemError::NotSupported)
235241
}
236242

243+
fn mmap_v2(&self, _offset: usize) -> Result<MMapPage> {
244+
log::error!(
245+
"{} does not support mmap_v2!",
246+
core::any::type_name_of_val(self),
247+
);
248+
Err(FileSystemError::NotSupported)
249+
}
250+
237251
// Socket operations:
238252
fn bind(&self, _address: SocketAddrRef, _length: usize) -> Result<()> {
239253
Err(FileSystemError::NotSocket)

‎src/aero_kernel/src/fs/ramfs.rs

Copy file name to clipboardExpand all lines: src/aero_kernel/src/fs/ramfs.rs
+16-1Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use super::cache::{
3333
};
3434
use super::devfs::DevINode;
3535
use super::inode::{
36-
DirEntry, FileContents, FileType, INodeInterface, Metadata, PollFlags, PollTable,
36+
DirEntry, FileContents, FileType, INodeInterface, MMapPage, Metadata, PollFlags, PollTable,
3737
};
3838
use super::{FileSystem, FileSystemError, Result};
3939

@@ -384,6 +384,21 @@ impl INodeInterface for LockedRamINode {
384384
}
385385
}
386386

387+
fn mmap_v2(&self, offset: usize) -> Result<MMapPage> {
388+
let this = self.0.read();
389+
390+
match &this.contents {
391+
FileContents::Device(dev) => {
392+
let device = dev.clone();
393+
drop(this);
394+
395+
device.mmap_v2(offset)
396+
}
397+
398+
_ => todo!(),
399+
}
400+
}
401+
387402
fn lookup(&self, dir: DirCacheItem, name: &str) -> Result<DirCacheItem> {
388403
let this = self.0.read();
389404
let child = this

‎src/aero_kernel/src/mem/paging/addr.rs

Copy file name to clipboardExpand all lines: src/aero_kernel/src/mem/paging/addr.rs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use bit_field::BitField;
3535
/// [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) trait can be used for performing conversions
3636
/// between `u64` and `usize`.
3737
38-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
38+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
3939
#[repr(transparent)]
4040
pub struct VirtAddr(u64);
4141

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.