Преглед на файлове

缺页中断使用的锁修改为irq_save; 添加脏页回写机制

MemoryShore преди 8 месеца
родител
ревизия
2f6b28dbcb

+ 1 - 1
kernel/Cargo.toml

@@ -88,4 +88,4 @@ debug = true   # Controls whether the compiler passes `-g`
 
 # The release profile, used for `cargo build --release`
 [profile.release]
-debug = true
+debug = false

+ 2 - 2
kernel/src/arch/x86_64/mm/fault.rs

@@ -28,7 +28,7 @@ pub type PageMapper =
 
 impl X86_64MMArch {
     pub fn vma_access_error(vma: Arc<LockedVMA>, error_code: X86PfErrorCode) -> bool {
-        let vm_flags = *vma.lock().vm_flags();
+        let vm_flags = *vma.lock_irqsave().vm_flags();
         let foreign = false;
         if error_code.contains(X86PfErrorCode::X86_PF_PK) {
             return true;
@@ -236,7 +236,7 @@ impl X86_64MMArch {
                     address.data(),
                 )
             });
-            let guard = vma.lock();
+            let guard = vma.lock_irqsave();
             let region = *guard.region();
             let vm_flags = *guard.vm_flags();
             drop(guard);

+ 1 - 1
kernel/src/arch/x86_64/mm/pkru.rs

@@ -16,7 +16,7 @@ const PKEY_MASK: usize = 1 << 32 | 1 << 33 | 1 << 34 | 1 << 35;
 /// ## 返回值
 /// - `u16`: vma的protection_key
 pub fn vma_pkey(vma: Arc<LockedVMA>) -> u16 {
-    let guard = vma.lock();
+    let guard = vma.lock_irqsave();
     ((guard.vm_flags().bits() & PKEY_MASK) >> VM_PKEY_SHIFT) as u16
 }
 

+ 3 - 3
kernel/src/ipc/shm.rs

@@ -166,7 +166,7 @@ impl ShmManager {
         let mut cur_phys = PhysPageFrame::new(phys_page.0);
         for _ in 0..page_count.data() {
             let page = Arc::new(Page::new(true, cur_phys.phys_address()));
-            page.write().set_shm_id(shm_id);
+            page.write_irqsave().set_shm_id(shm_id);
             let paddr = cur_phys.phys_address();
             page_manager_guard.insert(paddr, &page);
             cur_phys = cur_phys.next();
@@ -325,7 +325,7 @@ impl ShmManager {
             // 设置共享内存物理页当映射计数等于0时可被回收
             for _ in 0..count.data() {
                 let page = page_manager_guard.get_unwrap(&cur_phys.phys_address());
-                page.write().set_dealloc_when_zero(true);
+                page.write_irqsave().set_dealloc_when_zero(true);
 
                 cur_phys = cur_phys.next();
             }
@@ -444,7 +444,7 @@ impl KernelShm {
         for _ in 0..page_count.data() {
             let page = page_manager_guard.get(&cur_phys.phys_address()).unwrap();
             id_set.extend(
-                page.read()
+                page.read_irqsave()
                     .anon_vma()
                     .iter()
                     .map(|vma| vma.id())

+ 5 - 5
kernel/src/ipc/syscall.rs

@@ -351,7 +351,7 @@ impl Syscall {
                     .mappings
                     .contains(vaddr)
                     .ok_or(SystemError::EINVAL)?;
-                if vma.lock().region().start() != vaddr {
+                if vma.lock_irqsave().region().start() != vaddr {
                     return Err(SystemError::EINVAL);
                 }
 
@@ -387,7 +387,7 @@ impl Syscall {
                     // 将vma加入到对应Page的anon_vma
                     page_manager_guard
                         .get_unwrap(&phys.phys_address())
-                        .write()
+                        .write_irqsave()
                         .insert_vma(vma.clone());
 
                     phys = phys.next();
@@ -395,7 +395,7 @@ impl Syscall {
                 }
 
                 // 更新vma的映射状态
-                vma.lock().set_mapped(true);
+                vma.lock_irqsave().set_mapped(true);
 
                 vaddr.data()
             }
@@ -428,7 +428,7 @@ impl Syscall {
             .ok_or(SystemError::EINVAL)?;
 
         // 判断vaddr是否为起始地址
-        if vma.lock().region().start() != vaddr {
+        if vma.lock_irqsave().region().start() != vaddr {
             return Err(SystemError::EINVAL);
         }
 
@@ -443,7 +443,7 @@ impl Syscall {
         // 如果物理页的shm_id为None,代表不是共享页
         let mut page_manager_guard = page_manager_lock_irqsave();
         let page = page_manager_guard.get(&paddr).ok_or(SystemError::EINVAL)?;
-        let shm_id = page.read().shm_id().ok_or(SystemError::EINVAL)?;
+        let shm_id = page.read_irqsave().shm_id().ok_or(SystemError::EINVAL)?;
         drop(page_manager_guard);
 
         // 获取对应共享页管理信息

+ 1 - 1
kernel/src/mm/allocator/page_frame.rs

@@ -371,7 +371,7 @@ pub unsafe fn deallocate_page_frames(
 
         if let Some(page) = page {
             // 如果page是共享页,将其共享页信息从SHM_MANAGER中删去
-            let page_guard = page.read();
+            let page_guard = page.read_irqsave();
             if page_guard.shared() {
                 shm_manager_lock().free_id(&page_guard.shm_id().unwrap());
             }

+ 103 - 47
kernel/src/mm/fault.rs

@@ -61,7 +61,7 @@ pub struct PageFaultMessage {
 
 impl PageFaultMessage {
     pub fn new(vma: Arc<LockedVMA>, address: VirtAddr, flags: FaultFlags) -> Self {
-        let guard = vma.lock();
+        let guard = vma.lock_irqsave();
         let file_pgoff = guard.file_page_offset().map(|file_page_offset| {
             ((address - guard.region().start()) >> MMArch::PAGE_SHIFT) + file_page_offset
         });
@@ -142,7 +142,7 @@ impl PageFaultHandler {
             return VmFaultReason::VM_FAULT_SIGSEGV;
         }
 
-        let guard = vma.lock();
+        let guard = vma.lock_irqsave();
         let vm_flags = *guard.vm_flags();
         drop(guard);
         if unlikely(vm_flags.contains(VmFlags::VM_HUGETLB)) {
@@ -173,7 +173,7 @@ impl PageFaultHandler {
                 .allocate_table(address, 2)
                 .expect("failed to allocate PUD table");
         }
-        let page_flags = vma.lock().flags();
+        let page_flags = vma.lock_irqsave().flags();
 
         for level in 2..=3 {
             let level = MMArch::PAGE_LEVELS - level;
@@ -207,13 +207,17 @@ impl PageFaultHandler {
         let flags = pfm.flags;
         let vma = pfm.vma.clone();
         let mut ret = VmFaultReason::VM_FAULT_COMPLETED;
+
+        // pte存在
         if let Some(mut entry) = mapper.get_entry(address, 0) {
             if !entry.present() {
                 ret = Self::do_swap_page(pfm.clone(), mapper);
             }
+
             if entry.protnone() && vma.is_accessible() {
                 ret = Self::do_numa_page(pfm.clone(), mapper);
             }
+
             if flags.intersects(FaultFlags::FAULT_FLAG_WRITE | FaultFlags::FAULT_FLAG_UNSHARE) {
                 if !entry.write() {
                     ret = Self::do_wp_page(pfm.clone(), mapper);
@@ -227,7 +231,7 @@ impl PageFaultHandler {
             ret = Self::do_fault(pfm, mapper);
         }
 
-        vma.lock().set_mapped(true);
+        vma.lock_irqsave().set_mapped(true);
 
         return ret;
     }
@@ -246,7 +250,7 @@ impl PageFaultHandler {
     ) -> VmFaultReason {
         let address = pfm.address_aligned_down();
         let vma = pfm.vma.clone();
-        let guard = vma.lock();
+        let guard = vma.lock_irqsave();
         if let Some(flush) = mapper.map(address, guard.flags()) {
             flush.flush();
             crate::debug::klog::mm::mm_debug_log(
@@ -260,7 +264,7 @@ impl PageFaultHandler {
             let paddr = mapper.translate(address).unwrap().0;
             let mut page_manager_guard = page_manager_lock_irqsave();
             let page = page_manager_guard.get_unwrap(&paddr);
-            page.write().insert_vma(vma.clone());
+            page.write_irqsave().insert_vma(vma.clone());
             VmFaultReason::VM_FAULT_COMPLETED
         } else {
             VmFaultReason::VM_FAULT_OOM
@@ -288,7 +292,12 @@ impl PageFaultHandler {
 
         if !pfm.flags().contains(FaultFlags::FAULT_FLAG_WRITE) {
             return Self::do_read_fault(pfm, mapper);
-        } else if !pfm.vma().lock().vm_flags().contains(VmFlags::VM_SHARED) {
+        } else if !pfm
+            .vma()
+            .lock_irqsave()
+            .vm_flags()
+            .contains(VmFlags::VM_SHARED)
+        {
             return Self::do_cow_fault(pfm, mapper);
         } else {
             return Self::do_shared_fault(pfm, mapper);
@@ -316,7 +325,7 @@ impl PageFaultHandler {
         //     crate::process::ProcessManager::current_pid().data()
         // );
         // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_cow_fault
-        let file = pfm.vma().lock().vm_file().unwrap();
+        let file = pfm.vma().lock_irqsave().vm_file().unwrap();
 
         let mut ret = Self::filemap_fault(pfm, mapper);
 
@@ -338,7 +347,7 @@ impl PageFaultHandler {
         pfm: &mut PageFaultMessage,
         mapper: &mut PageMapper,
     ) -> VmFaultReason {
-        let fs = pfm.vma().lock().vm_file().unwrap().inode().fs();
+        let fs = pfm.vma().lock_irqsave().vm_file().unwrap().inode().fs();
 
         let mut ret = Self::do_fault_around(pfm, mapper);
         if !ret.is_empty() {
@@ -434,38 +443,75 @@ impl PageFaultHandler {
         let vma = pfm.vma.clone();
         let old_paddr = mapper.translate(address).unwrap().0;
         let mut page_manager = page_manager_lock_irqsave();
-        let map_count = page_manager.get_unwrap(&old_paddr).read().map_count();
+        let old_page = page_manager.get_unwrap(&old_paddr);
+        let map_count = old_page.read_irqsave().map_count();
         drop(page_manager);
 
         let mut entry = mapper.get_entry(address, 0).unwrap();
-        let new_flags = entry.flags().set_write(true);
+        let new_flags = entry.flags().set_write(true).set_dirty(true);
 
-        if map_count == 1 {
+        if vma.lock().vm_flags().contains(VmFlags::VM_SHARED) {
+            // 共享映射,直接修改页表项保护位,标记为脏页
             let table = mapper.get_table(address, 0).unwrap();
             let i = table.index_of(address).unwrap();
             entry.set_flags(new_flags);
             table.set_entry(i, entry);
-            VmFaultReason::VM_FAULT_COMPLETED
-        } else if let Some(flush) = mapper.map(address, new_flags) {
-            let mut page_manager_guard = page_manager_lock_irqsave();
-            let old_page = page_manager_guard.get_unwrap(&old_paddr);
-            old_page.write().remove_vma(&vma);
-            // drop(page_manager_guard);
 
-            flush.flush();
-            let paddr = mapper.translate(address).unwrap().0;
-            // let mut page_manager_guard = page_manager_lock_irqsave();
-            let page = page_manager_guard.get_unwrap(&paddr);
-            page.write().insert_vma(vma.clone());
-
-            (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping(
-                MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8,
-                MMArch::PAGE_SIZE,
-            );
+            old_page.write_irqsave().add_flags(PageFlags::PG_DIRTY);
 
             VmFaultReason::VM_FAULT_COMPLETED
+        } else if vma.is_anonymous() {
+            // 私有匿名映射,根据引用计数判断是否拷贝页面
+            if map_count == 1 {
+                let table = mapper.get_table(address, 0).unwrap();
+                let i = table.index_of(address).unwrap();
+                entry.set_flags(new_flags);
+                table.set_entry(i, entry);
+                VmFaultReason::VM_FAULT_COMPLETED
+            } else if let Some(flush) = mapper.map(address, new_flags) {
+                let mut page_manager_guard = page_manager_lock_irqsave();
+                let old_page = page_manager_guard.get_unwrap(&old_paddr);
+                old_page.write_irqsave().remove_vma(&vma);
+                // drop(page_manager_guard);
+
+                flush.flush();
+                let paddr = mapper.translate(address).unwrap().0;
+                // let mut page_manager_guard = page_manager_lock_irqsave();
+                let page = page_manager_guard.get_unwrap(&paddr);
+                page.write_irqsave().insert_vma(vma.clone());
+
+                (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping(
+                    MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8,
+                    MMArch::PAGE_SIZE,
+                );
+
+                VmFaultReason::VM_FAULT_COMPLETED
+            } else {
+                VmFaultReason::VM_FAULT_OOM
+            }
         } else {
-            VmFaultReason::VM_FAULT_OOM
+            // 私有文件映射,必须拷贝页面
+            if let Some(flush) = mapper.map(address, new_flags) {
+                let mut page_manager_guard = page_manager_lock_irqsave();
+                let old_page = page_manager_guard.get_unwrap(&old_paddr);
+                old_page.write_irqsave().remove_vma(&vma);
+                // drop(page_manager_guard);
+
+                flush.flush();
+                let paddr = mapper.translate(address).unwrap().0;
+                // let mut page_manager_guard = page_manager_lock_irqsave();
+                let page = page_manager_guard.get_unwrap(&paddr);
+                page.write_irqsave().insert_vma(vma.clone());
+
+                (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping(
+                    MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8,
+                    MMArch::PAGE_SIZE,
+                );
+
+                VmFaultReason::VM_FAULT_COMPLETED
+            } else {
+                VmFaultReason::VM_FAULT_OOM
+            }
         }
     }
 
@@ -487,7 +533,7 @@ impl PageFaultHandler {
                 .expect("failed to allocate pte table");
         }
         let vma = pfm.vma();
-        let vma_guard = vma.lock();
+        let vma_guard = vma.lock_irqsave();
         let vma_region = *vma_guard.region();
         drop(vma_guard);
 
@@ -530,7 +576,7 @@ impl PageFaultHandler {
             return VmFaultReason::VM_FAULT_OOM;
         }
 
-        let fs = pfm.vma().lock().vm_file().unwrap().inode().fs();
+        let fs = pfm.vma().lock_irqsave().vm_file().unwrap().inode().fs();
         // from_pte - pte_pgoff得出预读起始pte相对缺失页的偏移,加上pfm.file_pgoff(缺失页在文件中的偏移)得出起始页在文件中的偏移,结束pte同理
         fs.map_pages(
             pfm,
@@ -557,7 +603,7 @@ impl PageFaultHandler {
         end_pgoff: usize,
     ) -> VmFaultReason {
         let vma = pfm.vma();
-        let vma_guard = vma.lock();
+        let vma_guard = vma.lock_irqsave();
         let file = vma_guard.vm_file().expect("no vm_file in vma");
         let page_cache = file.inode().page_cache().unwrap();
 
@@ -571,7 +617,7 @@ impl PageFaultHandler {
 
         for pgoff in start_pgoff..=end_pgoff {
             if let Some(page) = page_cache.get_page(pgoff) {
-                let page_guard = page.read();
+                let page_guard = page.read_irqsave();
                 if page_guard.flags().contains(PageFlags::PG_UPTODATE) {
                     let phys = page_guard.phys_address();
 
@@ -600,7 +646,7 @@ impl PageFaultHandler {
         mapper: &mut PageMapper,
     ) -> VmFaultReason {
         let vma = pfm.vma();
-        let vma_guard = vma.lock();
+        let vma_guard = vma.lock_irqsave();
         let file = vma_guard.vm_file().expect("no vm_file in vma");
         let page_cache = file.inode().page_cache().unwrap();
         let file_pgoff = pfm.file_pgoff.expect("no file_pgoff");
@@ -629,15 +675,15 @@ impl PageFaultHandler {
             (MMArch::phys_2_virt(new_cache_page).unwrap().data() as *mut u8)
                 .copy_from_nonoverlapping(buf.as_mut_ptr(), MMArch::PAGE_SIZE);
 
-            let page = Arc::new(Page::new(false, new_cache_page));
+            let page = Arc::new(Page::new(true, new_cache_page));
             pfm.page = Some(page.clone());
 
-            page.write().add_flags(PageFlags::PG_LRU);
+            page.write_irqsave().add_flags(PageFlags::PG_LRU);
             page_manager_lock_irqsave().insert(new_cache_page, &page);
             page_reclaimer_lock_irqsave().insert_page(new_cache_page, &page);
             page_cache.add_page(file_pgoff, &page);
 
-            page.write()
+            page.write_irqsave()
                 .set_page_cache_index(Some(page_cache), Some(file_pgoff));
 
             //     // 分配空白页并映射到缺页地址
@@ -653,12 +699,16 @@ impl PageFaultHandler {
         mapper: &mut PageMapper,
     ) -> VmFaultReason {
         let vma = pfm.vma();
-        let vma_guard = vma.lock();
+        let vma_guard = vma.lock_irqsave();
         let cache_page = pfm.page.clone().expect("no page in pfm");
-        let page_phys = cache_page.read().phys_address();
+        let page_phys = cache_page.read_irqsave().phys_address();
 
         if pfm.flags().contains(FaultFlags::FAULT_FLAG_WRITE)
-            && !pfm.vma().lock().vm_flags().contains(VmFlags::VM_SHARED)
+            && !pfm
+                .vma()
+                .lock_irqsave()
+                .vm_flags()
+                .contains(VmFlags::VM_SHARED)
         {
             // 私有文件映射的写时复制场景
             // 分配空白页并映射到缺页地址
@@ -679,26 +729,32 @@ impl PageFaultHandler {
             );
 
             let mut page_manager_guard = page_manager_lock_irqsave();
-            let page_guard = cache_page.read();
+            let page_guard = cache_page.read_irqsave();
             let new_page = Arc::new(Page::new(page_guard.shared(), new_phys));
 
             // 新页加入页管理器中
             page_manager_guard.insert(new_phys, &new_page);
-            new_page
-                .write()
-                .set_page_cache_index(cache_page.read().page_cache(), cache_page.read().index());
+            new_page.write_irqsave().set_page_cache_index(
+                cache_page.read_irqsave().page_cache(),
+                cache_page.read_irqsave().index(),
+            );
 
             // 将vma插入页的vma链表中
-            new_page.write().insert_vma(pfm.vma());
+            new_page.write_irqsave().insert_vma(pfm.vma());
         } else {
             // 直接映射到PageCache
             mapper.map_phys(*pfm.address(), page_phys, vma_guard.flags());
+            cache_page.write_irqsave().insert_vma(pfm.vma());
 
             if pfm.flags().contains(FaultFlags::FAULT_FLAG_WRITE)
-                && pfm.vma().lock().vm_flags().contains(VmFlags::VM_SHARED)
+                && pfm
+                    .vma()
+                    .lock_irqsave()
+                    .vm_flags()
+                    .contains(VmFlags::VM_SHARED)
             {
                 // 如果是共享写映射,将pagecache页设为脏页,以便回收时能够回写
-                cache_page.write().add_flags(PageFlags::PG_DIRTY)
+                cache_page.write_irqsave().add_flags(PageFlags::PG_DIRTY)
             }
         }
         VmFaultReason::VM_FAULT_COMPLETED

+ 1 - 1
kernel/src/mm/madvise.rs

@@ -12,7 +12,7 @@ impl LockedVMA {
         _flusher: impl Flusher<MMArch>,
     ) -> Result<(), SystemError> {
         //TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/madvise.c?fi=madvise#do_madvise
-        let mut vma = self.lock();
+        let mut vma = self.lock_irqsave();
         let mut new_flags = *vma.vm_flags();
         match behavior {
             MadvFlags::MADV_REMOVE => {

+ 86 - 51
kernel/src/mm/page.rs

@@ -21,7 +21,7 @@ use crate::{
     init::initcall::INITCALL_MM,
     ipc::shm::ShmId,
     libs::{
-        rwlock::RwLock,
+        rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
         spinlock::{SpinLock, SpinLockGuard},
     },
     process::{ProcessControlBlock, ProcessManager},
@@ -143,6 +143,8 @@ fn page_reclaim_thread() -> i32 {
             let page_to_free = 4096;
             page_reclaimer_lock_irqsave().shrink_list(PageFrameCount::new(page_to_free));
         } else {
+            //TODO 暂时让页面回收线程负责脏页回写任务,后续需要分离
+            page_reclaimer_lock_irqsave().flush_dirty_pages();
             // 休眠5秒
             // log::info!("sleep");
             let _ = usleep(PosixTimeSpec::new(5, 0));
@@ -176,53 +178,91 @@ impl PageReclaimer {
     pub fn shrink_list(&mut self, count: PageFrameCount) {
         for _ in 0..count.data() {
             let (paddr, page) = self.lru.pop_lru().expect("pagecache is empty");
-            let page_cache = page.read().page_cache().unwrap();
-            for vma in page.read().anon_vma() {
-                let address_space = vma.lock().address_space().unwrap();
+            let page_cache = page.read_irqsave().page_cache().unwrap();
+            for vma in page.read_irqsave().anon_vma() {
+                let address_space = vma.lock_irqsave().address_space().unwrap();
                 let address_space = address_space.upgrade().unwrap();
                 let mut guard = address_space.write();
                 let mapper = &mut guard.user_mapper.utable;
-                let virt = vma.lock().page_address(&page).unwrap();
+                let virt = vma.lock_irqsave().page_address(&page).unwrap();
                 unsafe {
                     mapper.unmap(virt, false).unwrap().flush();
                 }
             }
-            page_cache.remove_page(page.read().index().unwrap());
+            page_cache.remove_page(page.read_irqsave().index().unwrap());
             page_manager_lock_irqsave().remove_page(&paddr);
-            if page.read().flags.contains(PageFlags::PG_DIRTY) {
-                //TODO 回写页面
-                let inode = page
-                    .read()
-                    .page_cache
-                    .clone()
-                    .unwrap()
-                    .inode
-                    .clone()
-                    .unwrap()
-                    .upgrade()
-                    .unwrap();
-                inode
-                    .write_at(
-                        page.read().index().unwrap(),
-                        MMArch::PAGE_SIZE,
-                        unsafe {
-                            core::slice::from_raw_parts(
-                                MMArch::phys_2_virt(page.read().phys_addr).unwrap().data()
-                                    as *mut u8,
-                                MMArch::PAGE_SIZE,
-                            )
-                        },
-                        SpinLock::new(FilePrivateData::Unused).lock(),
-                    )
-                    .unwrap();
+            if page.read_irqsave().flags.contains(PageFlags::PG_DIRTY) {
+                Self::page_writeback(&page, true);
             }
         }
     }
 
     pub fn wakeup_claim_thread() {
-        log::info!("wakeup_claim_thread");
+        // log::info!("wakeup_claim_thread");
         let _ = ProcessManager::wakeup(unsafe { PAGE_RECLAIMER_THREAD.as_ref().unwrap() });
     }
+
+    pub fn page_writeback(page: &Arc<Page>, unmap: bool) {
+        if !unmap {
+            page.write_irqsave().remove_flags(PageFlags::PG_DIRTY);
+        }
+
+        for vma in page.read_irqsave().anon_vma() {
+            let address_space = vma.lock_irqsave().address_space().unwrap();
+            let address_space = address_space.upgrade().unwrap();
+            let mut guard = address_space.write();
+            let mapper = &mut guard.user_mapper.utable;
+            let virt = vma.lock_irqsave().page_address(page).unwrap();
+            if unmap {
+                unsafe {
+                    mapper.unmap(virt, false).unwrap().flush();
+                }
+            } else {
+                unsafe {
+                    // 保护位设为只读
+                    mapper.remap(
+                        virt,
+                        mapper.get_entry(virt, 0).unwrap().flags().set_write(false),
+                    )
+                };
+            }
+        }
+        let inode = page
+            .read_irqsave()
+            .page_cache
+            .clone()
+            .unwrap()
+            .inode
+            .clone()
+            .unwrap()
+            .upgrade()
+            .unwrap();
+        inode
+            .write_at(
+                page.read_irqsave().index().unwrap(),
+                MMArch::PAGE_SIZE,
+                unsafe {
+                    core::slice::from_raw_parts(
+                        MMArch::phys_2_virt(page.read_irqsave().phys_addr)
+                            .unwrap()
+                            .data() as *mut u8,
+                        MMArch::PAGE_SIZE,
+                    )
+                },
+                SpinLock::new(FilePrivateData::Unused).lock(),
+            )
+            .unwrap();
+    }
+
+    pub fn flush_dirty_pages(&self) {
+        // log::info!("flush_dirty_pages");
+        let iter = self.lru.iter();
+        for (_, page) in iter {
+            if page.read_irqsave().flags().contains(PageFlags::PG_DIRTY) {
+                Self::page_writeback(page, false);
+            }
+        }
+    }
 }
 
 bitflags! {
@@ -251,20 +291,6 @@ pub struct Page {
     inner: RwLock<InnerPage>,
 }
 
-impl core::ops::Deref for Page {
-    type Target = RwLock<InnerPage>;
-
-    fn deref(&self) -> &Self::Target {
-        &self.inner
-    }
-}
-
-impl core::ops::DerefMut for Page {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.inner
-    }
-}
-
 impl Page {
     pub fn new(shared: bool, phys_addr: PhysAddr) -> Self {
         let inner = InnerPage::new(shared, phys_addr);
@@ -272,6 +298,14 @@ impl Page {
             inner: RwLock::new(inner),
         }
     }
+
+    pub fn read_irqsave(&self) -> RwLockReadGuard<InnerPage> {
+        self.inner.read_irqsave()
+    }
+
+    pub fn write_irqsave(&self) -> RwLockWriteGuard<InnerPage> {
+        self.inner.write_irqsave()
+    }
 }
 
 #[derive(Debug)]
@@ -582,11 +616,12 @@ impl<Arch: MemoryManagementArch> PageTable<Arch> {
                             let mut page_manager_guard = page_manager_lock_irqsave();
                             let old_phys = entry.address().unwrap();
                             let old_page = page_manager_guard.get_unwrap(&old_phys);
-                            let new_page = Arc::new(Page::new(old_page.read().shared(), phys));
-                            if let Some(ref page_cache) = old_page.read().page_cache() {
-                                new_page.write().set_page_cache_index(
+                            let new_page =
+                                Arc::new(Page::new(old_page.read_irqsave().shared(), phys));
+                            if let Some(ref page_cache) = old_page.read_irqsave().page_cache() {
+                                new_page.write_irqsave().set_page_cache_index(
                                     Some(page_cache.clone()),
-                                    old_page.read().index(),
+                                    old_page.read_irqsave().index(),
                                 );
                             }
 

+ 2 - 2
kernel/src/mm/syscall.rs

@@ -416,7 +416,7 @@ impl Syscall {
             return Err(SystemError::EINVAL);
         }
         let vma = vma.unwrap();
-        let vm_flags = *vma.lock().vm_flags();
+        let vm_flags = *vma.lock_irqsave().vm_flags();
 
         // 暂时不支持巨页映射
         if vm_flags.contains(VmFlags::VM_HUGETLB) {
@@ -590,7 +590,7 @@ impl Syscall {
                 .mappings
                 .find_nearest(VirtAddr::new(start))
             {
-                let guard = vma.lock();
+                let guard = vma.lock_irqsave();
                 let vm_start = guard.region().start().data();
                 let vm_end = guard.region().end().data();
                 if start < vm_start {

+ 48 - 35
kernel/src/mm/ucontext.rs

@@ -179,19 +179,19 @@ impl InnerAddressSpace {
         for vma in self.mappings.vmas.iter() {
             // TODO: 增加对VMA是否为文件映射的判断,如果是的话,就跳过
 
-            let vma_guard: SpinLockGuard<'_, VMA> = vma.lock();
+            let vma_guard: SpinLockGuard<'_, VMA> = vma.lock_irqsave();
 
             // 仅拷贝VMA信息并添加反向映射,因为UserMapper克隆时已经分配了新的物理页
             let new_vma = LockedVMA::new(vma_guard.clone_info_only());
             new_guard.mappings.vmas.insert(new_vma.clone());
             // debug!("new vma: {:x?}", new_vma);
-            let new_vma_guard = new_vma.lock();
+            let new_vma_guard = new_vma.lock_irqsave();
             let new_mapper = &new_guard.user_mapper.utable;
             let mut page_manager_guard = page_manager_lock_irqsave();
             for page in new_vma_guard.pages().map(|p| p.virt_address()) {
                 if let Some((paddr, _)) = new_mapper.translate(page) {
                     let page = page_manager_guard.get_unwrap(&paddr);
-                    page.write().insert_vma(new_vma.clone());
+                    page.write_irqsave().insert_vma(new_vma.clone());
                 }
             }
 
@@ -598,9 +598,9 @@ impl InnerAddressSpace {
         let regions: Vec<Arc<LockedVMA>> = self.mappings.conflicts(to_unmap).collect::<Vec<_>>();
 
         for r in regions {
-            let r = r.lock().region;
+            let r = r.lock_irqsave().region;
             let r = self.mappings.remove_vma(&r).unwrap();
-            let intersection = r.lock().region().intersect(&to_unmap).unwrap();
+            let intersection = r.lock_irqsave().region().intersect(&to_unmap).unwrap();
             let split_result = r.extract(intersection, &self.user_mapper.utable).unwrap();
 
             // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑
@@ -652,10 +652,10 @@ impl InnerAddressSpace {
 
         for r in regions {
             // debug!("mprotect: r: {:?}", r);
-            let r = *r.lock().region();
+            let r = *r.lock_irqsave().region();
             let r = self.mappings.remove_vma(&r).unwrap();
 
-            let intersection = r.lock().region().intersect(&region).unwrap();
+            let intersection = r.lock_irqsave().region().intersect(&region).unwrap();
             let split_result = r
                 .extract(intersection, mapper)
                 .expect("Failed to extract VMA");
@@ -667,7 +667,7 @@ impl InnerAddressSpace {
                 self.mappings.insert_vma(after);
             }
 
-            let mut r_guard = r.lock();
+            let mut r_guard = r.lock_irqsave();
             // 如果VMA的保护标志不允许指定的修改,则返回错误
             if !r_guard.can_have_flags(prot_flags) {
                 drop(r_guard);
@@ -710,10 +710,10 @@ impl InnerAddressSpace {
         let regions = self.mappings.conflicts(region).collect::<Vec<_>>();
 
         for r in regions {
-            let r = *r.lock().region();
+            let r = *r.lock_irqsave().region();
             let r = self.mappings.remove_vma(&r).unwrap();
 
-            let intersection = r.lock().region().intersect(&region).unwrap();
+            let intersection = r.lock_irqsave().region().intersect(&region).unwrap();
             let split_result = r
                 .extract(intersection, mapper)
                 .expect("Failed to extract VMA");
@@ -886,7 +886,7 @@ impl UserMappings {
     #[allow(dead_code)]
     pub fn contains(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> {
         for v in self.vmas.iter() {
-            let guard = v.lock();
+            let guard = v.lock_irqsave();
             if guard.region.contains(vaddr) {
                 return Some(v.clone());
             }
@@ -906,13 +906,13 @@ impl UserMappings {
     pub fn find_nearest(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> {
         let mut nearest: Option<Arc<LockedVMA>> = None;
         for v in self.vmas.iter() {
-            let guard = v.lock();
+            let guard = v.lock_irqsave();
             if guard.region.contains(vaddr) {
                 return Some(v.clone());
             }
             if guard.region.start >= vaddr
                 && if let Some(ref nearest) = nearest {
-                    guard.region.start < nearest.lock().region.start
+                    guard.region.start < nearest.lock_irqsave().region.start
                 } else {
                     true
                 }
@@ -928,7 +928,7 @@ impl UserMappings {
         let r = self
             .vmas
             .iter()
-            .filter(move |v| v.lock().region.intersect(&request).is_some())
+            .filter(move |v| v.lock_irqsave().region.intersect(&request).is_some())
             .cloned();
         return r;
     }
@@ -1050,7 +1050,7 @@ impl UserMappings {
 
     /// 在当前进程的映射关系中,插入一个新的VMA。
     pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
-        let region = vma.lock().region;
+        let region = vma.lock_irqsave().region;
         // 要求插入的地址范围必须是空闲的,也就是说,当前进程的地址空间中,不能有任何与之重叠的VMA。
         assert!(self.conflicts(region).next().is_none());
         self.reserve_hole(&region);
@@ -1070,7 +1070,7 @@ impl UserMappings {
         // 请注意,由于这里会对每个VMA加锁,因此性能很低
         let vma: Arc<LockedVMA> = self
             .vmas
-            .drain_filter(|vma| vma.lock().region == *region)
+            .drain_filter(|vma| vma.lock_irqsave().region == *region)
             .next()?;
         self.unreserve_hole(region);
 
@@ -1120,7 +1120,7 @@ impl LockedVMA {
             id: LOCKEDVMA_ID_ALLOCATOR.alloc().unwrap(),
             vma: SpinLock::new(vma),
         });
-        r.vma.lock().self_ref = Arc::downgrade(&r);
+        r.vma.lock_irqsave().self_ref = Arc::downgrade(&r);
         return r;
     }
 
@@ -1132,6 +1132,10 @@ impl LockedVMA {
         return self.vma.lock();
     }
 
+    pub fn lock_irqsave(&self) -> SpinLockGuard<VMA> {
+        return self.vma.lock_irqsave();
+    }
+
     /// 调整当前VMA的页面的标志位
     ///
     /// TODO:增加调整虚拟页映射的物理地址的功能
@@ -1146,7 +1150,7 @@ impl LockedVMA {
         mapper: &mut PageMapper,
         mut flusher: impl Flusher<MMArch>,
     ) -> Result<(), SystemError> {
-        let mut guard = self.lock();
+        let mut guard = self.lock_irqsave();
         for page in guard.region.pages() {
             // 暂时要求所有的页帧都已经映射到页表
             // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了
@@ -1164,7 +1168,7 @@ impl LockedVMA {
     pub fn unmap(&self, mapper: &mut PageMapper, mut flusher: impl Flusher<MMArch>) {
         // todo: 如果当前vma与文件相关,完善文件相关的逻辑
 
-        let mut guard = self.lock();
+        let mut guard = self.lock_irqsave();
 
         // 获取物理页的anon_vma的守卫
         let mut page_manager_guard: SpinLockGuard<'_, crate::mm::page::PageManager> =
@@ -1178,10 +1182,10 @@ impl LockedVMA {
 
             // 从anon_vma中删除当前VMA
             let page = page_manager_guard.get_unwrap(&paddr);
-            page.write().remove_vma(self);
+            page.write_irqsave().remove_vma(self);
 
             // 如果物理页的anon_vma链表长度为0并且不是共享页,则释放物理页.
-            if page.read().can_deallocate() {
+            if page.read_irqsave().can_deallocate() {
                 unsafe {
                     drop(page);
                     deallocate_page_frames(
@@ -1195,10 +1199,19 @@ impl LockedVMA {
             flusher.consume(flush);
         }
         guard.mapped = false;
+
+        // 当vma对应共享文件的写映射时,唤醒脏页回写线程
+        if guard.vm_file().is_some()
+            && guard
+                .vm_flags()
+                .contains(VmFlags::VM_SHARED | VmFlags::VM_WRITE)
+        {
+            crate::mm::page::PageReclaimer::wakeup_claim_thread();
+        }
     }
 
     pub fn mapped(&self) -> bool {
-        return self.vma.lock().mapped;
+        return self.vma.lock_irqsave().mapped;
     }
 
     /// 将当前VMA进行切分,切分成3个VMA,分别是:
@@ -1210,7 +1223,7 @@ impl LockedVMA {
         assert!(region.start().check_aligned(MMArch::PAGE_SIZE));
         assert!(region.end().check_aligned(MMArch::PAGE_SIZE));
 
-        let mut guard = self.lock();
+        let mut guard = self.lock_irqsave();
         {
             // 如果传入的region不在当前VMA的范围内,则直接返回None
             if unlikely(region.start() < guard.region.start() || region.end() > guard.region.end())
@@ -1253,27 +1266,27 @@ impl LockedVMA {
         // 重新设置before、after这两个VMA里面的物理页的anon_vma
         let mut page_manager_guard = page_manager_lock_irqsave();
         if let Some(before) = before.clone() {
-            let virt_iter = before.lock().region.iter_pages();
+            let virt_iter = before.lock_irqsave().region.iter_pages();
             for frame in virt_iter {
                 if let Some((paddr, _)) = utable.translate(frame.virt_address()) {
                     let page = page_manager_guard.get_unwrap(&paddr);
-                    let mut page_guard = page.write();
+                    let mut page_guard = page.write_irqsave();
                     page_guard.insert_vma(before.clone());
                     page_guard.remove_vma(self);
-                    before.lock().mapped = true;
+                    before.lock_irqsave().mapped = true;
                 }
             }
         }
 
         if let Some(after) = after.clone() {
-            let virt_iter = after.lock().region.iter_pages();
+            let virt_iter = after.lock_irqsave().region.iter_pages();
             for frame in virt_iter {
                 if let Some((paddr, _)) = utable.translate(frame.virt_address()) {
                     let page = page_manager_guard.get_unwrap(&paddr);
-                    let mut page_guard = page.write();
+                    let mut page_guard = page.write_irqsave();
                     page_guard.insert_vma(after.clone());
                     page_guard.remove_vma(self);
-                    after.lock().mapped = true;
+                    after.lock_irqsave().mapped = true;
                 }
             }
         }
@@ -1289,7 +1302,7 @@ impl LockedVMA {
 
     /// 判断VMA是否为外部(非当前进程空间)的VMA
     pub fn is_foreign(&self) -> bool {
-        let guard = self.lock();
+        let guard = self.lock_irqsave();
         if let Some(space) = guard.user_address_space.clone() {
             if let Some(space) = space.upgrade() {
                 return AddressSpace::is_current(&space);
@@ -1303,14 +1316,14 @@ impl LockedVMA {
 
     /// 判断VMA是否可访问
     pub fn is_accessible(&self) -> bool {
-        let guard = self.lock();
+        let guard = self.lock_irqsave();
         let vm_access_flags: VmFlags = VmFlags::VM_READ | VmFlags::VM_WRITE | VmFlags::VM_EXEC;
         guard.vm_flags().intersects(vm_access_flags)
     }
 
     /// 判断VMA是否为匿名映射
     pub fn is_anonymous(&self) -> bool {
-        let guard = self.lock();
+        let guard = self.lock_irqsave();
         guard.vm_file.is_none()
     }
 
@@ -1582,7 +1595,7 @@ impl VMA {
         for _ in 0..count.data() {
             let paddr = cur_phy.phys_address();
             let page = page_manager_guard.get_unwrap(&paddr);
-            page.write().insert_vma(r.clone());
+            page.write_irqsave().insert_vma(r.clone());
             cur_phy = cur_phy.next();
         }
 
@@ -1655,14 +1668,14 @@ impl VMA {
 
             // 将VMA加入到anon_vma
             let page = page_manager_guard.get_unwrap(&paddr);
-            page.write().insert_vma(r.clone());
+            page.write_irqsave().insert_vma(r.clone());
         }
         // debug!("VMA::zeroed: done");
         return Ok(r);
     }
 
     pub fn page_address(&self, page: &Arc<Page>) -> Result<VirtAddr, SystemError> {
-        let page_guard = page.read();
+        let page_guard = page.read_irqsave();
         let index = page_guard.index().unwrap();
         if index >= self.file_pgoff.unwrap() {
             let address =