From d2d6afc4dec0d182f5c4f64becc673bb1ebfd6b7 Mon Sep 17 00:00:00 2001 From: Harry Cheng Date: Wed, 31 Jul 2019 16:44:38 +0800 Subject: [PATCH] mmap write back --- crate/memory/src/memory_set/handler/file.rs | 22 ++++++++++++++++++--- crate/memory/src/memory_set/handler/mod.rs | 5 +++-- kernel/src/process/structs.rs | 13 ++++++++++-- kernel/src/syscall/mem.rs | 19 ++++++++++++++++++ kernel/src/syscall/mod.rs | 1 + 5 files changed, 53 insertions(+), 7 deletions(-) diff --git a/crate/memory/src/memory_set/handler/file.rs b/crate/memory/src/memory_set/handler/file.rs index cfd505e..eaf19fe 100644 --- a/crate/memory/src/memory_set/handler/file.rs +++ b/crate/memory/src/memory_set/handler/file.rs @@ -8,13 +8,16 @@ pub struct File { pub file_start: usize, pub file_end: usize, pub allocator: T, + pub write_back: bool, } -pub trait Read: Clone + Send + Sync + 'static { +pub trait MappedFile: Clone + Send + Sync + 'static { fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize; + fn write_at(&self, offset: usize, buf: &[u8]) -> usize; + fn sync_all(&self); } -impl MemoryHandler for File { +impl MemoryHandler for File { fn box_clone(&self) -> Box { Box::new(self.clone()) } @@ -33,6 +36,9 @@ impl MemoryHandler for File { // PageTable::unmap requires page to be present entry.set_present(true); + if self.write_back && entry.dirty() { + self.write_data(pt, addr); + } pt.unmap(addr); } @@ -73,7 +79,7 @@ impl MemoryHandler for File { } } -impl File { +impl File { fn fill_data(&self, pt: &mut dyn PageTable, addr: VirtAddr) { let data = pt.get_page_slice_mut(addr); let file_offset = addr + self.file_start - self.mem_start; @@ -85,6 +91,16 @@ impl File { data[read_size..].iter_mut().for_each(|x| *x = 0); } } + + fn write_data(&self, pt: &mut dyn PageTable, addr: VirtAddr) { + let data = pt.get_page_slice_mut(addr); + let file_offset = addr + self.file_start - self.mem_start; + let write_size = (self.file_end as isize - file_offset as isize) + .min(PAGE_SIZE as isize) + .max(0) as usize; + let written_size = self.file.write_at(file_offset, &mut data[..write_size]); + assert!(write_size == written_size); + } } impl Debug for File { diff --git a/crate/memory/src/memory_set/handler/mod.rs b/crate/memory/src/memory_set/handler/mod.rs index e2bd3a2..d7be117 100644 --- a/crate/memory/src/memory_set/handler/mod.rs +++ b/crate/memory/src/memory_set/handler/mod.rs @@ -1,7 +1,8 @@ use super::*; +use core::any::Any; // here may be a interesting part for lab -pub trait MemoryHandler: Debug + Send + Sync + 'static { +pub trait MemoryHandler: Any + Debug + Send + Sync + 'static { fn box_clone(&self) -> Box; /// Map `addr` in the page table @@ -44,5 +45,5 @@ mod linear; pub use self::byframe::ByFrame; pub use self::delay::Delay; -pub use self::file::{File, Read}; +pub use self::file::{File, MappedFile}; pub use self::linear::Linear; diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 28827de..c9c55a4 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -15,7 +15,7 @@ use xmas_elf::{ use crate::arch::interrupt::{Context, TrapFrame}; use crate::fs::{FileHandle, FileLike, OpenOptions, FOLLOW_MAX_DEPTH}; use crate::memory::{ - ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, Read, + ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, MappedFile, }; use crate::sync::{Condvar, SpinNoIrqLock as Mutex}; @@ -471,6 +471,7 @@ impl ElfExt for ElfFile<'_> { file_start: ph.offset() as usize, file_end: ph.offset() as usize + ph.file_size() as usize, allocator: GlobalFrameAlloc, + write_back: false, }, "elf", ); @@ -519,8 +520,16 @@ impl ElfExt for ElfFile<'_> { #[derive(Clone)] pub struct INodeForMap(pub Arc); -impl Read for INodeForMap { +impl MappedFile for INodeForMap { fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize { self.0.read_at(offset, buf).unwrap() } + + fn write_at(&self, offset: usize, buf: &[u8]) -> usize { + self.0.write_at(offset, buf).unwrap() + } + + fn sync_all(&self) { + self.0.sync_all().unwrap(); + } } diff --git a/kernel/src/syscall/mem.rs b/kernel/src/syscall/mem.rs index 16e2d6f..e9621c1 100644 --- a/kernel/src/syscall/mem.rs +++ b/kernel/src/syscall/mem.rs @@ -82,6 +82,7 @@ impl Syscall<'_> { file_start: offset, file_end: offset + len, allocator: GlobalFrameAlloc, + write_back: flags.contains(MmapFlags::SHARED), }, "mmap_file", ); @@ -116,7 +117,25 @@ impl Syscall<'_> { self.vm().pop_with_split(addr, addr + len); Ok(0) } + + pub fn sys_msync(&mut self, addr: usize, len: usize, flags: usize) -> SysResult { + let flags = MsyncFlags::from_bits_truncate(flags); + + if flags.contains(MsyncFlags::SYNC | MsyncFlags::ASYNC) { + return Err(SysError::EINVAL); + } + Ok(0) + } } + +bitflags! { + pub struct MsyncFlags: usize { + const ASYNC = 1; + const INVALIDATE = 2; + const SYNC = 4; + } +} + bitflags! { pub struct MmapProt: usize { /// Data cannot be accessed diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 1ac2258..cd711f6 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -170,6 +170,7 @@ impl Syscall<'_> { SYS_MPROTECT => self.sys_mprotect(args[0], args[1], args[2]), SYS_MUNMAP => self.sys_munmap(args[0], args[1]), SYS_MADVISE => self.unimplemented("madvise", Ok(0)), + SYS_MSYNC => self.sys_msync(args[0], args[1], args[2]), // signal SYS_RT_SIGACTION => self.unimplemented("sigaction", Ok(0)),