summaryrefslogtreecommitdiff
path: root/Kernel/VM
diff options
context:
space:
mode:
authorBrian Gianforcaro <bgianf@serenityos.org>2021-05-14 05:06:29 -0700
committerAndreas Kling <kling@serenityos.org>2021-05-15 09:01:32 +0200
commita324d4d6a342ad6847697c32f127c31ea76f6e61 (patch)
tree8e5b1cbeeedf8b9b66e35f35cd248e61cbd9e5d3 /Kernel/VM
parentd45db06826461886b69a832ae34f933d3b613fc7 (diff)
downloadserenity-a324d4d6a342ad6847697c32f127c31ea76f6e61.zip
Kernel: Make AnonymousVMObject physical page APIs OOM safe
AnonymousVMObject::create_with_physical_page(s) can't be NonnullRefPtr as it allocates internally. Fixing the API then surfaced an issue in ScatterGatherList, where the code was attempting to create an AnonymousVMObject in the constructor which will not be observable during OOM. Fix all of these issues and start propagating errors at the callers of the AnonymousVMObject and ScatterGatherList APis.
Diffstat (limited to 'Kernel/VM')
-rw-r--r--Kernel/VM/AnonymousVMObject.cpp8
-rw-r--r--Kernel/VM/AnonymousVMObject.h4
-rw-r--r--Kernel/VM/ScatterGatherList.cpp11
-rw-r--r--Kernel/VM/ScatterGatherList.h4
4 files changed, 15 insertions, 12 deletions
diff --git a/Kernel/VM/AnonymousVMObject.cpp b/Kernel/VM/AnonymousVMObject.cpp
index 038bae41a5..912e4cb275 100644
--- a/Kernel/VM/AnonymousVMObject.cpp
+++ b/Kernel/VM/AnonymousVMObject.cpp
@@ -60,14 +60,14 @@ RefPtr<AnonymousVMObject> AnonymousVMObject::create_with_size(size_t size, Alloc
return adopt_ref_if_nonnull(new AnonymousVMObject(size, commit));
}
-NonnullRefPtr<AnonymousVMObject> AnonymousVMObject::create_with_physical_pages(NonnullRefPtrVector<PhysicalPage> physical_pages)
+RefPtr<AnonymousVMObject> AnonymousVMObject::create_with_physical_pages(NonnullRefPtrVector<PhysicalPage> physical_pages)
{
- return adopt_ref(*new AnonymousVMObject(physical_pages));
+ return adopt_ref_if_nonnull(new AnonymousVMObject(physical_pages));
}
-NonnullRefPtr<AnonymousVMObject> AnonymousVMObject::create_with_physical_page(PhysicalPage& page)
+RefPtr<AnonymousVMObject> AnonymousVMObject::create_with_physical_page(PhysicalPage& page)
{
- return adopt_ref(*new AnonymousVMObject(page));
+ return adopt_ref_if_nonnull(new AnonymousVMObject(page));
}
RefPtr<AnonymousVMObject> AnonymousVMObject::create_for_physical_range(PhysicalAddress paddr, size_t size)
diff --git a/Kernel/VM/AnonymousVMObject.h b/Kernel/VM/AnonymousVMObject.h
index a2c990fa59..bdca7c0336 100644
--- a/Kernel/VM/AnonymousVMObject.h
+++ b/Kernel/VM/AnonymousVMObject.h
@@ -22,8 +22,8 @@ public:
static RefPtr<AnonymousVMObject> create_with_size(size_t, AllocationStrategy);
static RefPtr<AnonymousVMObject> create_for_physical_range(PhysicalAddress paddr, size_t size);
- static NonnullRefPtr<AnonymousVMObject> create_with_physical_page(PhysicalPage& page);
- static NonnullRefPtr<AnonymousVMObject> create_with_physical_pages(NonnullRefPtrVector<PhysicalPage>);
+ static RefPtr<AnonymousVMObject> create_with_physical_page(PhysicalPage& page);
+ static RefPtr<AnonymousVMObject> create_with_physical_pages(NonnullRefPtrVector<PhysicalPage>);
virtual RefPtr<VMObject> clone() override;
RefPtr<PhysicalPage> allocate_committed_page(size_t);
diff --git a/Kernel/VM/ScatterGatherList.cpp b/Kernel/VM/ScatterGatherList.cpp
index 6ebbfece2d..a8452de263 100644
--- a/Kernel/VM/ScatterGatherList.cpp
+++ b/Kernel/VM/ScatterGatherList.cpp
@@ -8,13 +8,16 @@
namespace Kernel {
-NonnullRefPtr<ScatterGatherList> ScatterGatherList::create(AsyncBlockDeviceRequest& request, NonnullRefPtrVector<PhysicalPage> allocated_pages, size_t device_block_size)
+RefPtr<ScatterGatherList> ScatterGatherList::create(AsyncBlockDeviceRequest& request, NonnullRefPtrVector<PhysicalPage> allocated_pages, size_t device_block_size)
{
- return adopt_ref(*new ScatterGatherList(request, allocated_pages, device_block_size));
+ auto vm_object = AnonymousVMObject::create_with_physical_pages(allocated_pages);
+ if (!vm_object)
+ return {};
+ return adopt_ref_if_nonnull(new ScatterGatherList(vm_object.release_nonnull(), request, device_block_size));
}
-ScatterGatherList::ScatterGatherList(AsyncBlockDeviceRequest& request, NonnullRefPtrVector<PhysicalPage> allocated_pages, size_t device_block_size)
- : m_vm_object(AnonymousVMObject::create_with_physical_pages(allocated_pages))
+ScatterGatherList::ScatterGatherList(NonnullRefPtr<AnonymousVMObject> vm_object, AsyncBlockDeviceRequest& request, size_t device_block_size)
+ : m_vm_object(move(vm_object))
{
m_dma_region = MM.allocate_kernel_region_with_vmobject(m_vm_object, page_round_up((request.block_count() * device_block_size)), "AHCI Scattered DMA", Region::Access::Read | Region::Access::Write, Region::Cacheable::Yes);
}
diff --git a/Kernel/VM/ScatterGatherList.h b/Kernel/VM/ScatterGatherList.h
index 0d94cbcfa2..9998d677d4 100644
--- a/Kernel/VM/ScatterGatherList.h
+++ b/Kernel/VM/ScatterGatherList.h
@@ -18,13 +18,13 @@ namespace Kernel {
class ScatterGatherList : public RefCounted<ScatterGatherList> {
public:
- static NonnullRefPtr<ScatterGatherList> create(AsyncBlockDeviceRequest&, NonnullRefPtrVector<PhysicalPage> allocated_pages, size_t device_block_size);
+ static RefPtr<ScatterGatherList> create(AsyncBlockDeviceRequest&, NonnullRefPtrVector<PhysicalPage> allocated_pages, size_t device_block_size);
const VMObject& vmobject() const { return m_vm_object; }
VirtualAddress dma_region() const { return m_dma_region->vaddr(); }
size_t scatters_count() const { return m_vm_object->physical_pages().size(); }
private:
- ScatterGatherList(AsyncBlockDeviceRequest&, NonnullRefPtrVector<PhysicalPage> allocated_pages, size_t device_block_size);
+ ScatterGatherList(NonnullRefPtr<AnonymousVMObject>, AsyncBlockDeviceRequest&, size_t device_block_size);
NonnullRefPtr<AnonymousVMObject> m_vm_object;
OwnPtr<Region> m_dma_region;
};