mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-11 02:13:56 +09:00
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.
This commit is contained in:
parent
d45db06826
commit
a324d4d6a3
Notes:
sideshowbarker
2024-07-18 18:07:21 +09:00
Author: https://github.com/bgianfo
Commit: a324d4d6a3
Pull-request: https://github.com/SerenityOS/serenity/pull/7103
Reviewed-by: https://github.com/awesomekling
6 changed files with 20 additions and 13 deletions
|
@ -230,6 +230,8 @@ KResultOr<size_t> SB16::write(FileDescription&, u64, const UserOrKernelBuffer& d
|
|||
if (!page)
|
||||
return ENOMEM;
|
||||
auto vmobject = AnonymousVMObject::create_with_physical_page(*page);
|
||||
if (!vmobject)
|
||||
return ENOMEM;
|
||||
m_dma_region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_SIZE, "SB16 DMA buffer", Region::Access::Write);
|
||||
if (!m_dma_region)
|
||||
return ENOMEM;
|
||||
|
|
|
@ -433,7 +433,9 @@ Optional<AsyncDeviceRequest::RequestResult> AHCIPort::prepare_and_set_scatter_li
|
|||
allocated_dma_regions.append(m_dma_buffers.at(index));
|
||||
}
|
||||
|
||||
m_current_scatter_list = ScatterGatherList::create(request, allocated_dma_regions, m_connected_device->block_size());
|
||||
m_current_scatter_list = ScatterGatherList::create(request, move(allocated_dma_regions), m_connected_device->block_size());
|
||||
if (!m_current_scatter_list)
|
||||
return AsyncDeviceRequest::Failure;
|
||||
if (request.request_type() == AsyncBlockDeviceRequest::Write) {
|
||||
if (!request.read_from_buffer(request.buffer(), m_current_scatter_list->dma_region().as_ptr(), m_connected_device->block_size() * request.block_count())) {
|
||||
return AsyncDeviceRequest::MemoryFault;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue