diff --git a/Kernel/VM/AnonymousVMObject.cpp b/Kernel/VM/AnonymousVMObject.cpp index 7ea5c8c33f..ad9ab7e92c 100644 --- a/Kernel/VM/AnonymousVMObject.cpp +++ b/Kernel/VM/AnonymousVMObject.cpp @@ -46,19 +46,21 @@ RefPtr AnonymousVMObject::try_clone() // one would keep the one it still has. This ensures that the original // one and this one, as well as the clone have sufficient resources // to cow all pages as needed - m_shared_committed_cow_pages = try_create(committed_pages.release_value()); + auto new_shared_committed_cow_pages = try_create(committed_pages.release_value()); - if (!m_shared_committed_cow_pages) + if (!new_shared_committed_cow_pages) return {}; + auto clone = adopt_ref_if_nonnull(new (nothrow) AnonymousVMObject(*this, *new_shared_committed_cow_pages)); + if (!clone) + return {}; + + m_shared_committed_cow_pages = move(new_shared_committed_cow_pages); + // Both original and clone become COW. So create a COW map for ourselves // or reset all pages to be copied again if we were previously cloned ensure_or_reset_cow_map(); - // FIXME: If this allocation fails, we need to rollback all changes. - auto clone = adopt_ref_if_nonnull(new (nothrow) AnonymousVMObject(*this)); - VERIFY(clone); - if (m_unused_committed_pages.has_value() && !m_unused_committed_pages->is_empty()) { // The parent vmobject didn't use up all committed pages. When // cloning (fork) we will overcommit. For this purpose we drop all @@ -153,9 +155,9 @@ AnonymousVMObject::AnonymousVMObject(Span> physical_ } } -AnonymousVMObject::AnonymousVMObject(AnonymousVMObject const& other) +AnonymousVMObject::AnonymousVMObject(AnonymousVMObject const& other, NonnullRefPtr shared_committed_cow_pages) : VMObject(other) - , m_shared_committed_cow_pages(other.m_shared_committed_cow_pages) + , m_shared_committed_cow_pages(move(shared_committed_cow_pages)) , m_purgeable(other.m_purgeable) { ensure_cow_map(); diff --git a/Kernel/VM/AnonymousVMObject.h b/Kernel/VM/AnonymousVMObject.h index b37247dbf8..88a523605d 100644 --- a/Kernel/VM/AnonymousVMObject.h +++ b/Kernel/VM/AnonymousVMObject.h @@ -39,10 +39,12 @@ public: size_t purge(); private: + class SharedCommittedCowPages; + explicit AnonymousVMObject(size_t, AllocationStrategy, Optional); explicit AnonymousVMObject(PhysicalAddress, size_t); explicit AnonymousVMObject(Span>); - explicit AnonymousVMObject(AnonymousVMObject const&); + explicit AnonymousVMObject(AnonymousVMObject const&, NonnullRefPtr); virtual StringView class_name() const override { return "AnonymousVMObject"sv; }