diff options
author | Hendiadyoin1 <leon.a@serenityos.org> | 2022-06-18 18:38:31 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-07-15 12:42:43 +0200 |
commit | 10d9bb93be15560f5a30e253028518109ca0c7c1 (patch) | |
tree | ce833ef8cb9d1f7e8d1b9580ca598cceef081901 | |
parent | d783389877435ef937b4306ac689470a5ca576bb (diff) | |
download | serenity-10d9bb93be15560f5a30e253028518109ca0c7c1.zip |
Kernel: Handle multiple regions in sys$msync
-rw-r--r-- | Kernel/Syscalls/mmap.cpp | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/Kernel/Syscalls/mmap.cpp b/Kernel/Syscalls/mmap.cpp index 998f4b1de5..8359709bc9 100644 --- a/Kernel/Syscalls/mmap.cpp +++ b/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; } |