readwrite() was broken when it had to load more than one missing page at once.

It now prints a warning if the device driver doesn't handle iovecs correctly.
Again, this could lead to very strange behaviour.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9092 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2004-09-28 16:30:25 +00:00
parent f7ed173238
commit f7bc46254a

View File

@ -94,8 +94,10 @@ readwrite_pages(file_cache_ref *ref, off_t offset, const iovec *vecs, size_t cou
return status; return status;
// ToDo: this is a work-around for buggy device drivers! // ToDo: this is a work-around for buggy device drivers!
if (size > fileVecs[0].length) if (size > fileVecs[0].length) {
dprintf("warning: device driver %p doesn't respect total length in read_pages() call!\n", ref->device);
size = fileVecs[0].length; size = fileVecs[0].length;
}
ASSERT(size <= fileVecs[0].length); ASSERT(size <= fileVecs[0].length);
@ -343,7 +345,8 @@ readwrite(void *_cacheRef, off_t offset, addr_t bufferBase, size_t *_size, bool
*_size = size; *_size = size;
} }
size_t bytesLeft = size; size_t bytesLeft = size, lastLeft = size;
off_t lastOffset = offset;
for (; bytesLeft > 0; offset += B_PAGE_SIZE) { for (; bytesLeft > 0; offset += B_PAGE_SIZE) {
// check if this page is already in memory // check if this page is already in memory
@ -364,8 +367,8 @@ readwrite(void *_cacheRef, off_t offset, addr_t bufferBase, size_t *_size, bool
// it is, so let's satisfy in the first part of the request // it is, so let's satisfy in the first part of the request
if (bufferBase != buffer) { if (bufferBase != buffer) {
size_t requestSize = buffer - (addr_t)bufferBase; size_t requestSize = buffer - (addr_t)bufferBase;
if ((doWrite && write_to_cache(ref, offset + pageOffset, requestSize, bufferBase, requestSize) != B_OK) if ((doWrite && write_to_cache(ref, lastOffset + pageOffset, requestSize, bufferBase, requestSize) != B_OK)
|| (!doWrite && read_from_cache(ref, offset + pageOffset, requestSize, bufferBase, requestSize) != B_OK)) { || (!doWrite && read_from_cache(ref, lastOffset + pageOffset, requestSize, bufferBase, requestSize) != B_OK)) {
vm_put_physical_page(virtualAddress); vm_put_physical_page(virtualAddress);
return B_IO_ERROR; return B_IO_ERROR;
} }
@ -386,6 +389,10 @@ readwrite(void *_cacheRef, off_t offset, addr_t bufferBase, size_t *_size, bool
// we've read the last page, so we're done! // we've read the last page, so we're done!
return B_OK; return B_OK;
} }
// prepare a potential gap request
lastOffset = offset + B_PAGE_SIZE;
lastLeft = bytesLeft - B_PAGE_SIZE;
} }
if (bytesLeft <= B_PAGE_SIZE) if (bytesLeft <= B_PAGE_SIZE)
@ -395,11 +402,14 @@ readwrite(void *_cacheRef, off_t offset, addr_t bufferBase, size_t *_size, bool
bytesLeft -= B_PAGE_SIZE; bytesLeft -= B_PAGE_SIZE;
} }
// fill the last remainding bytes of the request // fill the last remainding bytes of the request (either write or read)
if (doWrite)
return write_to_cache(ref, offset, bytesLeft, bufferBase, bytesLeft); lastOffset += pageOffset;
return read_from_cache(ref, offset, bytesLeft, bufferBase, bytesLeft); if (doWrite)
return write_to_cache(ref, lastOffset, lastLeft, bufferBase, lastLeft);
return read_from_cache(ref, lastOffset, lastLeft, bufferBase, lastLeft);
} }