mirror of
https://review.haiku-os.org/haiku
synced 2024-11-23 15:28:58 +01:00
kernel/fs: Fix handling of partial requests in do_synchronous_iterative_vnode_io.
If get_vecs returns 0 and no vecs, then we need to quit iterating. Otherwise we'll just loop forever and leak memory. Also add an assert in IOBuffer::GetNextVirtualVec that would have caught this problem, and the memory leak it results in.
This commit is contained in:
parent
e829154ffe
commit
5c56d775a9
@ -165,9 +165,10 @@ IOBuffer::GetNextVirtualVec(void*& _cookie, iovec& vector)
|
||||
}
|
||||
|
||||
if (cookie->vec_index == 0
|
||||
&& (fVecCount > 1 || fVecs[0].length > B_PAGE_SIZE)) {
|
||||
&& (fVecCount > 1 || fVecs[0].length > B_PAGE_SIZE)) {
|
||||
void* mappedAddress;
|
||||
addr_t mappedSize;
|
||||
ASSERT(cookie->mapped_area == -1);
|
||||
|
||||
// TODO: This is a potential violation of the VIP requirement, since
|
||||
// vm_map_physical_memory_vecs() allocates memory without special flags!
|
||||
@ -216,9 +217,9 @@ void
|
||||
IOBuffer::FreeVirtualVecCookie(void* _cookie)
|
||||
{
|
||||
virtual_vec_cookie* cookie = (virtual_vec_cookie*)_cookie;
|
||||
|
||||
if (cookie->mapped_area >= 0)
|
||||
delete_area(cookie->mapped_area);
|
||||
|
||||
cookie->PutPhysicalPageIfNeeded();
|
||||
|
||||
free_etc(cookie, fVIP ? HEAP_PRIORITY_VIP : 0);
|
||||
|
@ -292,8 +292,9 @@ do_synchronous_iterative_vnode_io(struct vnode* vnode, void* openCookie,
|
||||
generic_size_t length = request->Length();
|
||||
|
||||
status_t error = B_OK;
|
||||
bool partial = false;
|
||||
|
||||
for (; error == B_OK && length > 0
|
||||
for (; error == B_OK && length > 0 && !partial
|
||||
&& buffer->GetNextVirtualVec(virtualVecCookie, vector) == B_OK;) {
|
||||
uint8* vecBase = (uint8*)vector.iov_base;
|
||||
generic_size_t vecLength = min_c(vector.iov_len, length);
|
||||
@ -309,8 +310,12 @@ do_synchronous_iterative_vnode_io(struct vnode* vnode, void* openCookie,
|
||||
fileVecs[0].length = vecLength;
|
||||
fileVecCount = 1;
|
||||
}
|
||||
if (error != B_OK || fileVecCount == 0)
|
||||
if (error != B_OK)
|
||||
break;
|
||||
if (fileVecCount == 0) {
|
||||
partial = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < fileVecCount; i++) {
|
||||
const file_io_vec& fileVec = fileVecs[i];
|
||||
@ -325,15 +330,17 @@ do_synchronous_iterative_vnode_io(struct vnode* vnode, void* openCookie,
|
||||
vecBase += transferred;
|
||||
vecLength -= transferred;
|
||||
|
||||
if (transferred != toTransfer)
|
||||
if (transferred != toTransfer) {
|
||||
partial = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer->FreeVirtualVecCookie(virtualVecCookie);
|
||||
|
||||
bool partial = length > 0;
|
||||
partial = (partial || length > 0);
|
||||
size_t bytesTransferred = request->Length() - length;
|
||||
request->SetTransferredBytes(partial, bytesTransferred);
|
||||
if (finished != NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user