DMAResource::TranslateNext(): Fixed several bugs that could cause too
many bytes to be read/written, which, among other things, could trigger an assert in the IORequest code: * In case of a partial (i.e. non-block-aligned) begin, transferLeft was not adjusted correctly. * The main loop was lacking a transferLeft check. * Main loop: When finally using a bounce buffer, the unrestricted vec length was used as base length for the bounce buffer. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27042 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -483,13 +483,21 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation)
|
|||||||
|
|
||||||
dmaLength += length;
|
dmaLength += length;
|
||||||
|
|
||||||
vecOffset += length - partialBegin;
|
size_t transferred = length - partialBegin;
|
||||||
|
vecOffset += transferred;
|
||||||
offset -= partialBegin;
|
offset -= partialBegin;
|
||||||
|
|
||||||
|
if (transferLeft > transferred)
|
||||||
|
transferLeft -= transferred;
|
||||||
|
else
|
||||||
|
transferLeft = 0;
|
||||||
|
|
||||||
TRACE(" partial begin, using bounce buffer: offset: %lld, length: "
|
TRACE(" partial begin, using bounce buffer: offset: %lld, length: "
|
||||||
"%lu\n", offset, length);
|
"%lu\n", offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32 i = vecIndex; i < vecIndex + segmentCount;) {
|
for (uint32 i = vecIndex;
|
||||||
|
i < vecIndex + segmentCount && transferLeft > 0;) {
|
||||||
if (dmaBuffer->VecCount() >= fRestrictions.max_segment_count)
|
if (dmaBuffer->VecCount() >= fRestrictions.max_segment_count)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -501,9 +509,10 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
addr_t base = (addr_t)vec.iov_base + vecOffset;
|
addr_t base = (addr_t)vec.iov_base + vecOffset;
|
||||||
size_t length = vec.iov_len - vecOffset;
|
size_t maxLength = vec.iov_len - vecOffset;
|
||||||
if (length > transferLeft)
|
if (maxLength > transferLeft)
|
||||||
length = transferLeft;
|
maxLength = transferLeft;
|
||||||
|
size_t length = maxLength;
|
||||||
|
|
||||||
// Cut the vec according to transfer size, segment size, and boundary.
|
// Cut the vec according to transfer size, segment size, and boundary.
|
||||||
|
|
||||||
@@ -540,7 +549,7 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation)
|
|||||||
|
|
||||||
// If length is 0, use bounce buffer for complete vec.
|
// If length is 0, use bounce buffer for complete vec.
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
length = vec.iov_len - vecOffset;
|
length = maxLength;
|
||||||
useBounceBufferSize = length;
|
useBounceBufferSize = length;
|
||||||
TRACE(" vec %lu: 0 length, using bounce buffer: %lu\n", i,
|
TRACE(" vec %lu: 0 length, using bounce buffer: %lu\n", i,
|
||||||
useBounceBufferSize);
|
useBounceBufferSize);
|
||||||
@@ -567,7 +576,7 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation)
|
|||||||
|
|
||||||
dmaLength += length;
|
dmaLength += length;
|
||||||
vecOffset += length;
|
vecOffset += length;
|
||||||
transferLeft -= length;
|
transferLeft -= min_c(length, transferLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're writing partially, we always need to have a block sized bounce
|
// If we're writing partially, we always need to have a block sized bounce
|
||||||
|
|||||||
Reference in New Issue
Block a user