Kernel IOBuffer: Fixed potential memory leak.

* IOBuffer::FreeVirtualVecCookie() did not put the last physical page
  back. This was only an issue in case GetNextVirtualVec() wasn't
  iterated through the end, for example in case of an error.
* Fixed the condition when to put back a physical page; the current
  solution will also work with the generic page mapper implementation.
* This fixes the low hanging fruits of Ingo's comment in #5777.
This commit is contained in:
Axel Dörfler
2017-04-06 23:31:48 +02:00
parent f17488662a
commit 99ccb18d97
+31 -22
View File
@@ -1,6 +1,6 @@
/*
* Copyright 2008-2011, Ingo Weinhold, [email protected].
* Copyright 2008, Axel Dörfler, [email protected].
* Copyright 2008-2017, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
@@ -38,6 +38,33 @@ enum {
};
struct virtual_vec_cookie {
uint32 vec_index;
generic_size_t vec_offset;
area_id mapped_area;
void* physical_page_handle;
addr_t virtual_address;
virtual_vec_cookie()
:
vec_index(0),
vec_offset(0),
mapped_area(-1),
physical_page_handle(NULL),
virtual_address((addr_t)-1)
{
}
void PutPhysicalPageIfNeeded()
{
if (virtual_address != (addr_t)-1) {
vm_put_physical_page(virtual_address, physical_page_handle);
virtual_address = (addr_t)-1;
}
}
};
// #pragma mark -
@@ -57,15 +84,6 @@ IORequestChunk::~IORequestChunk()
// #pragma mark -
struct virtual_vec_cookie {
uint32 vec_index;
generic_size_t vec_offset;
area_id mapped_area;
void* physical_page_handle;
addr_t virtual_address;
};
IOBuffer*
IOBuffer::Create(uint32 count, bool vip)
{
@@ -124,21 +142,11 @@ IOBuffer::GetNextVirtualVec(void*& _cookie, iovec& vector)
if (cookie == NULL)
return B_NO_MEMORY;
cookie->vec_index = 0;
cookie->vec_offset = 0;
cookie->mapped_area = -1;
cookie->physical_page_handle = NULL;
cookie->virtual_address = 0;
_cookie = cookie;
}
// recycle a potential previously mapped page
if (cookie->physical_page_handle != NULL) {
// TODO: This check is invalid! The physical page mapper is not required to
// return a non-NULL handle (the generic implementation does not)!
vm_put_physical_page(cookie->virtual_address,
cookie->physical_page_handle);
}
cookie->PutPhysicalPageIfNeeded();
if (cookie->vec_index >= fVecCount)
return B_BAD_INDEX;
@@ -203,7 +211,8 @@ IOBuffer::FreeVirtualVecCookie(void* _cookie)
virtual_vec_cookie* cookie = (virtual_vec_cookie*)_cookie;
if (cookie->mapped_area >= 0)
delete_area(cookie->mapped_area);
// TODO: A vm_get_physical_page() may still be unmatched!
cookie->PutPhysicalPageIfNeeded();
free_etc(cookie, fVIP ? HEAP_PRIORITY_VIP : 0);
}