From f7bc46254aa2748476e47be073c22d9e39c4cf86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 28 Sep 2004 16:30:25 +0000 Subject: [PATCH] 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 --- src/kernel/core/cache/file_cache.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/kernel/core/cache/file_cache.cpp b/src/kernel/core/cache/file_cache.cpp index 2c1c0e8a0f..4bb4e1656b 100644 --- a/src/kernel/core/cache/file_cache.cpp +++ b/src/kernel/core/cache/file_cache.cpp @@ -94,8 +94,10 @@ readwrite_pages(file_cache_ref *ref, off_t offset, const iovec *vecs, size_t cou return status; // 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; + } 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_t bytesLeft = size; + size_t bytesLeft = size, lastLeft = size; + off_t lastOffset = offset; for (; bytesLeft > 0; offset += B_PAGE_SIZE) { // 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 if (bufferBase != buffer) { size_t requestSize = buffer - (addr_t)bufferBase; - if ((doWrite && write_to_cache(ref, offset + pageOffset, requestSize, bufferBase, requestSize) != B_OK) - || (!doWrite && read_from_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, lastOffset + pageOffset, requestSize, bufferBase, requestSize) != B_OK)) { vm_put_physical_page(virtualAddress); 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! return B_OK; } + + // prepare a potential gap request + lastOffset = offset + B_PAGE_SIZE; + lastLeft = 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; } - // fill the last remainding bytes of the request - if (doWrite) - return write_to_cache(ref, offset, bytesLeft, bufferBase, bytesLeft); + // fill the last remainding bytes of the request (either write or read) + + 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); }