From eab435cd59a30d144ecc077fbdbc1bb37b3eb5a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 5 Aug 2005 11:52:22 +0000 Subject: [PATCH] vfs_get_vnode_cache() now only allocates a new cache if requested: this prevents the system to allocate caches for files that don't use or have a file cache (ie. only those can be mmap()ed!). Therefore, cache_prefetch() no longer crashes when trying to prefetch files without a file cache. read_into_cache() no longer does anything if the requested size is 0. Fixed a bug in cache_prefetch_vnode(): if the cache couldn't be retrieved, it put the vnode, but didn't own it (the caller does). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13904 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/vfs.h | 2 +- src/system/kernel/cache/file_cache.cpp | 13 ++++++++----- src/system/kernel/fs/vfs.cpp | 11 ++++++++--- src/system/kernel/vm/vm.cpp | 2 +- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/headers/private/kernel/vfs.h b/headers/private/kernel/vfs.h index 63ec0bebe2..042e160df0 100644 --- a/headers/private/kernel/vfs.h +++ b/headers/private/kernel/vfs.h @@ -75,7 +75,7 @@ status_t vfs_get_cookie_from_fd(int fd, void **_cookie); bool vfs_can_page(void *vnode, void *cookie); status_t vfs_read_pages(void *vnode, void *cookie, off_t pos, const iovec *vecs, size_t count, size_t *_numBytes); status_t vfs_write_pages(void *vnode, void *cookie, off_t pos, const iovec *vecs, size_t count, size_t *_numBytes); -status_t vfs_get_vnode_cache(void *vnode, struct vm_cache_ref **_cache); +status_t vfs_get_vnode_cache(void *vnode, struct vm_cache_ref **_cache, bool allocate); status_t vfs_get_file_map( void *_vnode, off_t offset, size_t size, struct file_io_vec *vecs, size_t *_count); status_t vfs_get_fs_node_from_path(mount_id mountID, const char *path, bool kernel, void **_node); status_t vfs_stat_vnode(void *_vnode, struct stat *stat); diff --git a/src/system/kernel/cache/file_cache.cpp b/src/system/kernel/cache/file_cache.cpp index c50c65c19c..0dcd45d165 100644 --- a/src/system/kernel/cache/file_cache.cpp +++ b/src/system/kernel/cache/file_cache.cpp @@ -487,6 +487,10 @@ read_into_cache(file_cache_ref *ref, off_t offset, size_t size, addr_t buffer, s TRACE(("read_from_cache: ref = %p, offset = %Ld, size = %lu, buffer = %p, bufferSize = %lu\n", ref, offset, size, (void *)buffer, bufferSize)); + // do we have to read in anything at all? + if (size == 0) + return B_OK; + // make sure "offset" is page aligned - but also remember the page offset int32 pageOffset = offset & (B_PAGE_SIZE - 1); size = PAGE_ALIGN(size + pageOffset); @@ -497,7 +501,8 @@ read_into_cache(file_cache_ref *ref, off_t offset, size_t size, addr_t buffer, s if (chunkSize > (MAX_IO_VECS * B_PAGE_SIZE)) chunkSize = MAX_IO_VECS * B_PAGE_SIZE; - status_t status = read_chunk_into_cache(ref, offset, chunkSize, pageOffset, buffer, bufferSize); + status_t status = read_chunk_into_cache(ref, offset, chunkSize, pageOffset, + buffer, bufferSize); if (status != B_OK) return status; @@ -819,10 +824,8 @@ extern "C" void cache_prefetch_vnode(void *vnode, off_t offset, size_t size) { vm_cache_ref *cache; - if (vfs_get_vnode_cache(vnode, &cache) != B_OK) { - vfs_put_vnode(vnode); + if (vfs_get_vnode_cache(vnode, &cache, false) != B_OK) return; - } file_cache_ref *ref = (struct file_cache_ref *)((vnode_store *)cache->cache->store)->file_cache_ref; off_t fileSize = cache->cache->virtual_size; @@ -985,7 +988,7 @@ file_cache_create(mount_id mountID, vnode_id vnodeID, off_t size, int fd) if (vfs_lookup_vnode(mountID, vnodeID, &ref->vnode) != B_OK) goto err2; - if (vfs_get_vnode_cache(ref->vnode, &ref->cache) != B_OK) + if (vfs_get_vnode_cache(ref->vnode, &ref->cache, true) != B_OK) goto err3; ref->cache->cache->virtual_size = size; diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 7cdb829376..31f91d7a9e 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -2458,7 +2458,7 @@ vfs_write_pages(void *_vnode, void *cookie, off_t pos, const iovec *vecs, size_t extern "C" status_t -vfs_get_vnode_cache(void *_vnode, vm_cache_ref **_cache) +vfs_get_vnode_cache(void *_vnode, vm_cache_ref **_cache, bool allocate) { struct vnode *vnode = (struct vnode *)_vnode; @@ -2470,9 +2470,14 @@ vfs_get_vnode_cache(void *_vnode, vm_cache_ref **_cache) mutex_lock(&sVnodeMutex); status_t status = B_OK; + // The cache could have been created in the meantime - if (vnode->cache == NULL) - status = vm_create_vnode_cache(vnode, &vnode->cache); + if (vnode->cache == NULL) { + if (allocate) + status = vm_create_vnode_cache(vnode, &vnode->cache); + else + status = B_BAD_VALUE; + } if (status == B_OK) *_cache = vnode->cache; diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 91c93540e4..c6b8dfb5e3 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -1099,7 +1099,7 @@ _vm_map_file(aspace_id aid, const char *name, void **_address, uint32 addressSpe if (status < B_OK) goto err1; - status = vfs_get_vnode_cache(vnode, &cacheRef); + status = vfs_get_vnode_cache(vnode, &cacheRef, false); if (status < B_OK) goto err2;