Kernel: Handle AnonymousVMObject allocation failure when forking

Thanks to all the RAII, AnonymousVMObject::try_clone() can now
gracefully handle allocation failure.
This commit is contained in:
Andreas Kling 2021-08-04 22:58:58 +02:00
parent 0672163840
commit 89a9ae7d0c
2 changed files with 13 additions and 9 deletions

View file

@ -46,19 +46,21 @@ RefPtr<VMObject> 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<SharedCommittedCowPages>(committed_pages.release_value());
auto new_shared_committed_cow_pages = try_create<SharedCommittedCowPages>(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<NonnullRefPtr<PhysicalPage>> physical_
}
}
AnonymousVMObject::AnonymousVMObject(AnonymousVMObject const& other)
AnonymousVMObject::AnonymousVMObject(AnonymousVMObject const& other, NonnullRefPtr<SharedCommittedCowPages> 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();

View file

@ -39,10 +39,12 @@ public:
size_t purge();
private:
class SharedCommittedCowPages;
explicit AnonymousVMObject(size_t, AllocationStrategy, Optional<CommittedPhysicalPageSet>);
explicit AnonymousVMObject(PhysicalAddress, size_t);
explicit AnonymousVMObject(Span<NonnullRefPtr<PhysicalPage>>);
explicit AnonymousVMObject(AnonymousVMObject const&);
explicit AnonymousVMObject(AnonymousVMObject const&, NonnullRefPtr<SharedCommittedCowPages>);
virtual StringView class_name() const override { return "AnonymousVMObject"sv; }