Make reading the write_overlay more efficient. Instead of always reading the
original file and then overwriting it with what we have in memory, just linearly fill the buffer, closing gaps between our buffers with original file content as needed. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30927 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -451,54 +451,71 @@ status_t
|
|||||||
OverlayInode::Read(void *_cookie, off_t position, void *buffer, size_t *length,
|
OverlayInode::Read(void *_cookie, off_t position, void *buffer, size_t *length,
|
||||||
bool readPages)
|
bool readPages)
|
||||||
{
|
{
|
||||||
if (position >= fStat.st_size) {
|
uint8 *pointer = (uint8 *)buffer;
|
||||||
*length = 0;
|
write_buffer *element = fWriteBuffers;
|
||||||
return B_OK;
|
size_t bytesLeft = MIN(fStat.st_size - position, *length);
|
||||||
}
|
*length = bytesLeft;
|
||||||
|
|
||||||
if (position < fOriginalNodeLength) {
|
|
||||||
void *superCookie = NULL;
|
void *superCookie = NULL;
|
||||||
if (_cookie != NULL)
|
if (!fIsVirtual && _cookie != NULL)
|
||||||
superCookie = ((open_cookie *)_cookie)->super_cookie;
|
superCookie = ((open_cookie *)_cookie)->super_cookie;
|
||||||
|
|
||||||
size_t readLength = MIN(fOriginalNodeLength - position, *length);
|
while (bytesLeft > 0) {
|
||||||
status_t result = B_ERROR;
|
size_t gapSize = bytesLeft;
|
||||||
|
if (element != NULL) {
|
||||||
|
gapSize = MIN(bytesLeft, element->position > position ?
|
||||||
|
element->position - position : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gapSize > 0 && !fIsVirtual && position < fOriginalNodeLength) {
|
||||||
|
// there's a part missing between the read position and our
|
||||||
|
// next position, fill the gap with original file content
|
||||||
|
size_t readLength = MIN(fOriginalNodeLength - position, gapSize);
|
||||||
|
status_t result = B_ERROR;
|
||||||
if (readPages) {
|
if (readPages) {
|
||||||
iovec vector;
|
iovec vector;
|
||||||
vector.iov_base = buffer;
|
vector.iov_base = pointer;
|
||||||
vector.iov_len = readLength;
|
vector.iov_len = readLength;
|
||||||
|
|
||||||
result = fSuperVnode.ops->read_pages(SuperVolume(),
|
result = fSuperVnode.ops->read_pages(SuperVolume(),
|
||||||
&fSuperVnode, superCookie, position, &vector, 1, &readLength);
|
&fSuperVnode, superCookie, position, &vector, 1,
|
||||||
|
&readLength);
|
||||||
} else {
|
} else {
|
||||||
result = fSuperVnode.ops->read(SuperVolume(), &fSuperVnode,
|
result = fSuperVnode.ops->read(SuperVolume(), &fSuperVnode,
|
||||||
superCookie, position, buffer, &readLength);
|
superCookie, position, pointer, &readLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if (readLength < *length)
|
pointer += readLength;
|
||||||
memset((uint8 *)buffer + readLength, 0, *length - readLength);
|
position += readLength;
|
||||||
} else
|
bytesLeft -= readLength;
|
||||||
memset(buffer, 0, *length);
|
gapSize -= readLength;
|
||||||
|
}
|
||||||
|
|
||||||
// overlay the read with whatever chunks we have written
|
if (gapSize > 0) {
|
||||||
write_buffer *element = fWriteBuffers;
|
// there's a gap before our next position which we cannot
|
||||||
*length = MIN(fStat.st_size - position, *length);
|
// fill with original file content, zero it out
|
||||||
off_t end = position + *length;
|
memset(pointer, 0, gapSize);
|
||||||
while (element) {
|
bytesLeft -= gapSize;
|
||||||
if (element->position > end)
|
position += gapSize;
|
||||||
|
pointer += gapSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we've reached the end
|
||||||
|
if (bytesLeft == 0 || element == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
off_t elementEnd = element->position + element->length;
|
off_t elementEnd = element->position + element->length;
|
||||||
if (elementEnd > position) {
|
if (elementEnd > position) {
|
||||||
off_t copyPosition = MAX(position, element->position);
|
size_t copyLength = MIN(elementEnd - position, bytesLeft);
|
||||||
size_t copyLength = MIN(elementEnd - position, *length);
|
memcpy(pointer, element->buffer + (position - element->position),
|
||||||
memcpy((uint8 *)buffer + (copyPosition - position),
|
|
||||||
element->buffer + (copyPosition - element->position),
|
|
||||||
copyLength);
|
copyLength);
|
||||||
|
|
||||||
|
bytesLeft -= copyLength;
|
||||||
|
position += copyLength;
|
||||||
|
pointer += copyLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
element = element->next;
|
element = element->next;
|
||||||
|
|||||||
Reference in New Issue
Block a user