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 (!fIsVirtual && _cookie != NULL)
|
||||||
if (_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) {
|
||||||
if (readPages) {
|
gapSize = MIN(bytesLeft, element->position > position ?
|
||||||
iovec vector;
|
element->position - position : 0);
|
||||||
vector.iov_base = buffer;
|
|
||||||
vector.iov_len = readLength;
|
|
||||||
|
|
||||||
result = fSuperVnode.ops->read_pages(SuperVolume(),
|
|
||||||
&fSuperVnode, superCookie, position, &vector, 1, &readLength);
|
|
||||||
} else {
|
|
||||||
result = fSuperVnode.ops->read(SuperVolume(), &fSuperVnode,
|
|
||||||
superCookie, position, buffer, &readLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != B_OK)
|
if (gapSize > 0 && !fIsVirtual && position < fOriginalNodeLength) {
|
||||||
return result;
|
// 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) {
|
||||||
|
iovec vector;
|
||||||
|
vector.iov_base = pointer;
|
||||||
|
vector.iov_len = readLength;
|
||||||
|
|
||||||
if (readLength < *length)
|
result = fSuperVnode.ops->read_pages(SuperVolume(),
|
||||||
memset((uint8 *)buffer + readLength, 0, *length - readLength);
|
&fSuperVnode, superCookie, position, &vector, 1,
|
||||||
} else
|
&readLength);
|
||||||
memset(buffer, 0, *length);
|
} else {
|
||||||
|
result = fSuperVnode.ops->read(SuperVolume(), &fSuperVnode,
|
||||||
|
superCookie, position, pointer, &readLength);
|
||||||
|
}
|
||||||
|
|
||||||
// overlay the read with whatever chunks we have written
|
if (result != B_OK)
|
||||||
write_buffer *element = fWriteBuffers;
|
return result;
|
||||||
*length = MIN(fStat.st_size - position, *length);
|
|
||||||
off_t end = position + *length;
|
pointer += readLength;
|
||||||
while (element) {
|
position += readLength;
|
||||||
if (element->position > end)
|
bytesLeft -= readLength;
|
||||||
|
gapSize -= readLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gapSize > 0) {
|
||||||
|
// there's a gap before our next position which we cannot
|
||||||
|
// fill with original file content, zero it out
|
||||||
|
memset(pointer, 0, gapSize);
|
||||||
|
bytesLeft -= gapSize;
|
||||||
|
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