diff --git a/src/system/kernel/cache/file_cache.cpp b/src/system/kernel/cache/file_cache.cpp index 4ae4979c3a..2999c7895f 100644 --- a/src/system/kernel/cache/file_cache.cpp +++ b/src/system/kernel/cache/file_cache.cpp @@ -767,13 +767,15 @@ do_cache_io(void* _cacheRef, void* cookie, off_t offset, addr_t buffer, file_cache_ref* ref = (file_cache_ref*)_cacheRef; VMCache* cache = ref->cache; - bool useBuffer = buffer != 0; + + const bool useBuffer = buffer != 0; + const off_t startOffset = offset; + const size_t size = *_size; TRACE(("cache_io(ref = %p, offset = %lld, buffer = %p, size = %lu, %s)\n", - ref, offset, (void*)buffer, *_size, doWrite ? "write" : "read")); + ref, offset, (void*)buffer, size, doWrite ? "write" : "read")); int32 pageOffset = offset & (B_PAGE_SIZE - 1); - size_t size = *_size; offset -= pageOffset; // "offset" and "lastOffset" are always aligned to B_PAGE_SIZE, @@ -791,15 +793,6 @@ do_cache_io(void* _cacheRef, void* cookie, off_t offset, addr_t buffer, AutoLocker locker(cache); - // Now that we have the lock, make sure the situation didn't change. - if ((pageOffset + offset) >= cache->virtual_end) { - locker.Unlock(); - *_size = 0; - return B_OK; - } - if ((off_t)(pageOffset + offset + size) > cache->virtual_end) - size = cache->virtual_end - (pageOffset + offset); - size_t bytesLeft = size, lastLeft = size; int32 lastPageOffset = pageOffset; addr_t lastBuffer = buffer; @@ -915,6 +908,15 @@ do_cache_io(void* _cacheRef, void* cookie, off_t offset, addr_t buffer, lastPageOffset = 0; } + if ((lastOffset + (off_t)lastLeft) > cache->virtual_end) { + // Someone else must've shrunk the cache. + if (lastOffset > startOffset) + *_size = lastOffset - startOffset; + else + *_size = 0; + return B_OK; + } + if (bytesLeft <= bytesInPage) break; @@ -1310,7 +1312,7 @@ file_cache_disable(void* _cacheRef) AutoLocker _(ref->cache); - // If already disabled, there's nothing to do for us. + // If already disabled, there's nothing for us to do. if (ref->disabled_count > 0) { ref->disabled_count++; return B_OK;