diff --git a/Kernel/Memory/AddressSpace.cpp b/Kernel/Memory/AddressSpace.cpp index 57f0cea656..1467f5922e 100644 --- a/Kernel/Memory/AddressSpace.cpp +++ b/Kernel/Memory/AddressSpace.cpp @@ -149,11 +149,11 @@ Optional AddressSpace::allocate_range(VirtualAddress vaddr, size_t KResultOr AddressSpace::try_allocate_split_region(Region const& source_region, VirtualRange const& range, size_t offset_in_vmobject) { - auto new_region = Region::try_create_user_accessible( + auto maybe_new_region = Region::try_create_user_accessible( range, source_region.vmobject(), offset_in_vmobject, KString::try_create(source_region.name()), source_region.access(), source_region.is_cacheable() ? Region::Cacheable::Yes : Region::Cacheable::No, source_region.is_shared()); - if (!new_region) - return ENOMEM; - auto* region = add_region(new_region.release_nonnull()); + if (maybe_new_region.is_error()) + return maybe_new_region.error(); + auto* region = add_region(maybe_new_region.release_value()); if (!region) return ENOMEM; region->set_syscall_region(source_region.is_syscall_region()); @@ -173,12 +173,14 @@ KResultOr AddressSpace::allocate_region(VirtualRange const& range, Stri auto maybe_vmobject = AnonymousVMObject::try_create_with_size(range.size(), strategy); if (maybe_vmobject.is_error()) return maybe_vmobject.error(); - auto region = Region::try_create_user_accessible(range, maybe_vmobject.release_value(), 0, KString::try_create(name), prot_to_region_access_flags(prot), Region::Cacheable::Yes, false); - if (!region) - return ENOMEM; + auto maybe_region = Region::try_create_user_accessible(range, maybe_vmobject.release_value(), 0, KString::try_create(name), prot_to_region_access_flags(prot), Region::Cacheable::Yes, false); + if (maybe_region.is_error()) + return maybe_region.error(); + + auto region = maybe_region.release_value(); if (!region->map(page_directory())) return ENOMEM; - auto* added_region = add_region(region.release_nonnull()); + auto* added_region = add_region(move(region)); if (!added_region) return ENOMEM; return added_region; @@ -201,12 +203,12 @@ KResultOr AddressSpace::allocate_region_with_vmobject(VirtualRange cons return EINVAL; } offset_in_vmobject &= PAGE_MASK; - auto region = Region::try_create_user_accessible(range, move(vmobject), offset_in_vmobject, KString::try_create(name), prot_to_region_access_flags(prot), Region::Cacheable::Yes, shared); - if (!region) { + auto maybe_region = Region::try_create_user_accessible(range, move(vmobject), offset_in_vmobject, KString::try_create(name), prot_to_region_access_flags(prot), Region::Cacheable::Yes, shared); + if (maybe_region.is_error()) { dbgln("allocate_region_with_vmobject: Unable to allocate Region"); - return ENOMEM; + return maybe_region.error(); } - auto* added_region = add_region(region.release_nonnull()); + auto* added_region = add_region(maybe_region.release_value()); if (!added_region) return ENOMEM; if (!added_region->map(page_directory())) diff --git a/Kernel/Memory/MemoryManager.cpp b/Kernel/Memory/MemoryManager.cpp index 62f4907a9c..d8e98388f0 100644 --- a/Kernel/Memory/MemoryManager.cpp +++ b/Kernel/Memory/MemoryManager.cpp @@ -743,9 +743,12 @@ OwnPtr MemoryManager::allocate_kernel_region(PhysicalAddress paddr, size OwnPtr MemoryManager::allocate_kernel_region_with_vmobject(VirtualRange const& range, VMObject& vmobject, StringView name, Region::Access access, Region::Cacheable cacheable) { - auto region = Region::try_create_kernel_only(range, vmobject, 0, KString::try_create(name), access, cacheable); - if (region) - region->map(kernel_page_directory()); + auto maybe_region = Region::try_create_kernel_only(range, vmobject, 0, KString::try_create(name), access, cacheable); + if (maybe_region.is_error()) + return {}; + + auto region = maybe_region.release_value(); + region->map(kernel_page_directory()); return region; } diff --git a/Kernel/Memory/Region.cpp b/Kernel/Memory/Region.cpp index 5865316b2d..7ddb9f5d2e 100644 --- a/Kernel/Memory/Region.cpp +++ b/Kernel/Memory/Region.cpp @@ -50,7 +50,7 @@ Region::~Region() } } -OwnPtr Region::clone() +KResultOr> Region::try_clone() { VERIFY(Process::current()); @@ -60,12 +60,14 @@ OwnPtr Region::clone() VERIFY(vmobject().is_shared_inode()); // Create a new region backed by the same VMObject. - auto region = Region::try_create_user_accessible( + auto maybe_region = Region::try_create_user_accessible( m_range, m_vmobject, m_offset_in_vmobject, m_name ? m_name->try_clone() : OwnPtr {}, access(), m_cacheable ? Cacheable::Yes : Cacheable::No, m_shared); - if (!region) { + if (maybe_region.is_error()) { dbgln("Region::clone: Unable to allocate new Region"); - return nullptr; + return maybe_region.error(); } + + auto region = maybe_region.release_value(); region->set_mmap(m_mmap); region->set_shared(m_shared); region->set_syscall_region(is_syscall_region()); @@ -77,16 +79,19 @@ OwnPtr Region::clone() auto maybe_vmobject_clone = vmobject().try_clone(); if (maybe_vmobject_clone.is_error()) - return {}; + return maybe_vmobject_clone.error(); + auto vmobject_clone = maybe_vmobject_clone.release_value(); // Set up a COW region. The parent (this) region becomes COW as well! remap(); - auto clone_region = Region::try_create_user_accessible( - m_range, maybe_vmobject_clone.release_value(), m_offset_in_vmobject, m_name ? m_name->try_clone() : OwnPtr {}, access(), m_cacheable ? Cacheable::Yes : Cacheable::No, m_shared); - if (!clone_region) { + auto maybe_clone_region = Region::try_create_user_accessible( + m_range, vmobject_clone, m_offset_in_vmobject, m_name ? m_name->try_clone() : OwnPtr {}, access(), m_cacheable ? Cacheable::Yes : Cacheable::No, m_shared); + if (maybe_clone_region.is_error()) { dbgln("Region::clone: Unable to allocate new Region for COW"); - return nullptr; + return maybe_clone_region.error(); } + auto clone_region = maybe_clone_region.release_value(); + if (m_stack) { VERIFY(is_readable()); VERIFY(is_writable()); @@ -143,17 +148,14 @@ size_t Region::amount_shared() const return bytes; } -OwnPtr Region::try_create_user_accessible(VirtualRange const& range, NonnullRefPtr vmobject, size_t offset_in_vmobject, OwnPtr name, Region::Access access, Cacheable cacheable, bool shared) +KResultOr> Region::try_create_user_accessible(VirtualRange const& range, NonnullRefPtr vmobject, size_t offset_in_vmobject, OwnPtr name, Region::Access access, Cacheable cacheable, bool shared) { - auto region = adopt_own_if_nonnull(new (nothrow) Region(range, move(vmobject), offset_in_vmobject, move(name), access, cacheable, shared)); - if (!region) - return nullptr; - return region; + return adopt_nonnull_own_or_enomem(new (nothrow) Region(range, move(vmobject), offset_in_vmobject, move(name), access, cacheable, shared)); } -OwnPtr Region::try_create_kernel_only(VirtualRange const& range, NonnullRefPtr vmobject, size_t offset_in_vmobject, OwnPtr name, Region::Access access, Cacheable cacheable) +KResultOr> Region::try_create_kernel_only(VirtualRange const& range, NonnullRefPtr vmobject, size_t offset_in_vmobject, OwnPtr name, Region::Access access, Cacheable cacheable) { - return adopt_own_if_nonnull(new (nothrow) Region(range, move(vmobject), offset_in_vmobject, move(name), access, cacheable, false)); + return adopt_nonnull_own_or_enomem(new (nothrow) Region(range, move(vmobject), offset_in_vmobject, move(name), access, cacheable, false)); } bool Region::should_cow(size_t page_index) const diff --git a/Kernel/Memory/Region.h b/Kernel/Memory/Region.h index 94d777ff2e..5f3c760234 100644 --- a/Kernel/Memory/Region.h +++ b/Kernel/Memory/Region.h @@ -49,8 +49,8 @@ public: Yes, }; - static OwnPtr try_create_user_accessible(VirtualRange const&, NonnullRefPtr, size_t offset_in_vmobject, OwnPtr name, Region::Access access, Cacheable, bool shared); - static OwnPtr try_create_kernel_only(VirtualRange const&, NonnullRefPtr, size_t offset_in_vmobject, OwnPtr name, Region::Access access, Cacheable = Cacheable::Yes); + static KResultOr> try_create_user_accessible(VirtualRange const&, NonnullRefPtr, size_t offset_in_vmobject, OwnPtr name, Region::Access access, Cacheable, bool shared); + static KResultOr> try_create_kernel_only(VirtualRange const&, NonnullRefPtr, size_t offset_in_vmobject, OwnPtr name, Region::Access access, Cacheable = Cacheable::Yes); ~Region(); @@ -90,7 +90,7 @@ public: PageFaultResponse handle_fault(PageFault const&); - OwnPtr clone(); + KResultOr> try_clone(); bool contains(VirtualAddress vaddr) const { diff --git a/Kernel/Syscalls/fork.cpp b/Kernel/Syscalls/fork.cpp index 6f166e15aa..a0ff8cd74a 100644 --- a/Kernel/Syscalls/fork.cpp +++ b/Kernel/Syscalls/fork.cpp @@ -96,14 +96,14 @@ KResultOr Process::sys$fork(RegisterState& regs) ScopedSpinLock lock(address_space().get_lock()); for (auto& region : address_space().regions()) { dbgln_if(FORK_DEBUG, "fork: cloning Region({}) '{}' @ {}", region, region->name(), region->vaddr()); - auto region_clone = region->clone(); - if (!region_clone) { + auto maybe_region_clone = region->try_clone(); + if (maybe_region_clone.is_error()) { dbgln("fork: Cannot clone region, insufficient memory"); // TODO: tear down new process? - return ENOMEM; + return maybe_region_clone.error(); } - auto* child_region = child->address_space().add_region(region_clone.release_nonnull()); + auto* child_region = child->address_space().add_region(maybe_region_clone.release_value()); if (!child_region) { dbgln("fork: Cannot add region, insufficient memory"); // TODO: tear down new process?