Bläddra i källkod

Kernel: Handle multiple regions in sys$msync

Hendiadyoin1 3 år sedan
förälder
incheckning
10d9bb93be
1 ändrade filer med 26 tillägg och 12 borttagningar
  1. 26 12
      Kernel/Syscalls/mmap.cpp

+ 26 - 12
Kernel/Syscalls/mmap.cpp

@@ -571,23 +571,37 @@ ErrorOr<FlatPtr> Process::sys$msync(Userspace<void*> address, size_t size, int f
     // Note: This is not specified
     auto rounded_size = TRY(Memory::page_round_up(size));
 
-    // FIXME: We probably want to sync all mappings in the address+size range.
-    auto* region = address_space().find_region_containing(Memory::VirtualRange { address.vaddr(), rounded_size });
+    auto regions = TRY(address_space().find_regions_intersecting(Memory::VirtualRange { address.vaddr(), rounded_size }));
     // All regions from address upto address+size shall be mapped
-    if (!region)
+    if (regions.is_empty())
         return ENOMEM;
 
-    auto& vmobject = region->vmobject();
-    if (!vmobject.is_shared_inode())
-        return 0;
+    size_t total_intersection_size = 0;
+    Memory::VirtualRange range_to_sync { address.vaddr(), rounded_size };
+    for (auto const* region : regions) {
+        // Region was not mapped
+        if (!region->is_mmap())
+            return ENOMEM;
+        total_intersection_size += region->range().intersect(range_to_sync).size();
+    }
+    // Part of the indicated range was not mapped
+    if (total_intersection_size != size)
+        return ENOMEM;
+
+    for (auto* region : regions) {
+        auto& vmobject = region->vmobject();
+        if (!vmobject.is_shared_inode())
+            continue;
 
-    off_t offset = region->offset_in_vmobject() + address.ptr() - region->range().base().get();
+        off_t offset = region->offset_in_vmobject() + address.ptr() - region->range().base().get();
 
-    auto& inode_vmobject = static_cast<Memory::SharedInodeVMObject&>(vmobject);
-    // FIXME: Handle MS_ASYNC
-    TRY(inode_vmobject.sync(offset / PAGE_SIZE, size / PAGE_SIZE));
-    // FIXME: Handle MS_INVALIDATE
-    // FIXME: If msync() causes any write to a file, the file's st_ctime and st_mtime fields shall be marked for update.
+        auto& inode_vmobject = static_cast<Memory::SharedInodeVMObject&>(vmobject);
+        // FIXME: If multiple regions belong to the same vmobject we might want to coalesce these writes
+        // FIXME: Handle MS_ASYNC
+        TRY(inode_vmobject.sync(offset / PAGE_SIZE, rounded_size / PAGE_SIZE));
+        // FIXME: Handle MS_INVALIDATE
+        // FIXME: If msync() causes any write to a file, the file's st_ctime and st_mtime fields shall be marked for update.
+    }
     return 0;
 }