diff options
author | Andreas Kling <kling@serenityos.org> | 2022-08-23 18:51:18 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-08-24 14:57:51 +0200 |
commit | 30861daa93c06280cff4e355b31d11ecbf8079ec (patch) | |
tree | fdb41ebda018893cf9498a11126194cf71e9395a /Kernel/Syscalls/mmap.cpp | |
parent | cf16b2c8e64709d570c5f54a981017d217e95ed0 (diff) | |
download | serenity-30861daa93c06280cff4e355b31d11ecbf8079ec.zip |
Kernel: Simplify the File memory-mapping API
Before this change, we had File::mmap() which did all the work of
setting up a VMObject, and then creating a Region in the current
process's address space.
This patch simplifies the interface by removing the region part.
Files now only have to return a suitable VMObject from
vmobject_for_mmap(), and then sys$mmap() itself will take care of
actually mapping it into the address space.
This fixes an issue where we'd try to block on I/O (for inode metadata
lookup) while holding the address space spinlock. It also reduces time
spent holding the address space lock.
Diffstat (limited to 'Kernel/Syscalls/mmap.cpp')
-rw-r--r-- | Kernel/Syscalls/mmap.cpp | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/Kernel/Syscalls/mmap.cpp b/Kernel/Syscalls/mmap.cpp index 0d5ebba9bd..1e5be912ab 100644 --- a/Kernel/Syscalls/mmap.cpp +++ b/Kernel/Syscalls/mmap.cpp @@ -190,10 +190,17 @@ ErrorOr<FlatPtr> Process::sys$mmap(Userspace<Syscall::SC_mmap_params const*> use if (map_stack && (!map_private || !map_anonymous)) return EINVAL; + Memory::VirtualRange requested_range { VirtualAddress { addr }, rounded_size }; + if (addr && !(map_fixed || map_fixed_noreplace)) { + // If there's an address but MAP_FIXED wasn't specified, the address is just a hint. + requested_range = { {}, rounded_size }; + } + Memory::Region* region = nullptr; LockRefPtr<OpenFileDescription> description; - LockRefPtr<Memory::AnonymousVMObject> vmobject; + LockRefPtr<Memory::VMObject> vmobject; + u64 used_offset = 0; if (map_anonymous) { auto strategy = map_noreserve ? AllocationStrategy::None : AllocationStrategy::Reserve; @@ -206,6 +213,7 @@ ErrorOr<FlatPtr> Process::sys$mmap(Userspace<Syscall::SC_mmap_params const*> use } else { if (offset < 0) return EINVAL; + used_offset = static_cast<u64>(offset); if (static_cast<size_t>(offset) & ~PAGE_MASK) return EINVAL; description = TRY(open_file_description(fd)); @@ -220,6 +228,8 @@ ErrorOr<FlatPtr> Process::sys$mmap(Userspace<Syscall::SC_mmap_params const*> use } if (description->inode()) TRY(validate_inode_mmap_prot(prot, *description->inode(), map_shared)); + + vmobject = TRY(description->vmobject_for_mmap(*this, requested_range, used_offset, map_shared)); } return address_space().with([&](auto& space) -> ErrorOr<FlatPtr> { @@ -227,17 +237,16 @@ ErrorOr<FlatPtr> Process::sys$mmap(Userspace<Syscall::SC_mmap_params const*> use if (map_fixed) TRY(space->unmap_mmap_range(VirtualAddress(addr), size)); - Memory::VirtualRange requested_range { VirtualAddress { addr }, rounded_size }; - if (addr && !(map_fixed || map_fixed_noreplace)) { - // If there's an address but MAP_FIXED wasn't specified, the address is just a hint. - requested_range = { {}, rounded_size }; - } - - if (map_anonymous) { - region = TRY(space->allocate_region_with_vmobject(map_randomized ? Memory::RandomizeVirtualAddress::Yes : Memory::RandomizeVirtualAddress::No, requested_range.base(), requested_range.size(), alignment, vmobject.release_nonnull(), 0, {}, prot, map_shared)); - } else { - region = TRY(description->mmap(*this, *space, requested_range, static_cast<u64>(offset), prot, map_shared)); - } + region = TRY(space->allocate_region_with_vmobject( + map_randomized ? Memory::RandomizeVirtualAddress::Yes : Memory::RandomizeVirtualAddress::No, + requested_range.base(), + requested_range.size(), + alignment, + vmobject.release_nonnull(), + used_offset, + {}, + prot, + map_shared)); if (!region) return ENOMEM; |