diff --git a/headers/private/kernel/vfs.h b/headers/private/kernel/vfs.h index f754c75973..b79731ef09 100644 --- a/headers/private/kernel/vfs.h +++ b/headers/private/kernel/vfs.h @@ -112,6 +112,7 @@ status_t vfs_synchronous_io(io_request* request, void* cookie); status_t vfs_get_vnode_cache(struct vnode *vnode, struct VMCache **_cache, bool allocate); +status_t vfs_set_vnode_cache(struct vnode *vnode, struct VMCache *_cache); status_t vfs_get_file_map(struct vnode *vnode, off_t offset, size_t size, struct file_io_vec *vecs, size_t *_count); status_t vfs_get_fs_node_from_path(fs_volume *volume, const char *path, diff --git a/src/system/kernel/cache/file_cache.cpp b/src/system/kernel/cache/file_cache.cpp index 5f1f459617..00957cc8fd 100644 --- a/src/system/kernel/cache/file_cache.cpp +++ b/src/system/kernel/cache/file_cache.cpp @@ -932,6 +932,8 @@ cache_prefetch_vnode(struct vnode* vnode, off_t offset, size_t size) VMCache* cache; if (vfs_get_vnode_cache(vnode, &cache, false) != B_OK) return; + if (cache->type != CACHE_TYPE_VNODE) + return; file_cache_ref* ref = ((VMVnodeCache*)cache)->FileCacheRef(); off_t fileSize = cache->virtual_end; @@ -1029,7 +1031,7 @@ cache_node_opened(struct vnode* vnode, int32 fdType, VMCache* cache, return; off_t size = -1; - if (cache != NULL) { + if (cache != NULL && cache->type == CACHE_TYPE_VNODE) { file_cache_ref* ref = ((VMVnodeCache*)cache)->FileCacheRef(); if (ref != NULL) size = cache->virtual_end; @@ -1048,7 +1050,7 @@ cache_node_closed(struct vnode* vnode, int32 fdType, VMCache* cache, return; int32 accessType = 0; - if (cache != NULL) { + if (cache != NULL && cache->type == CACHE_TYPE_VNODE) { // ToDo: set accessType } diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index d731c88f9e..c75b643446 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -1035,7 +1035,7 @@ free_vnode(struct vnode* vnode, bool reenter) // long as the vnode is busy and in the hash, that won't happen, but as // soon as we've removed it from the hash, it could reload the vnode -- with // a new cache attached! - if (vnode->cache != NULL) + if (vnode->cache != NULL && vnode->cache->type == CACHE_TYPE_VNODE) ((VMVnodeCache*)vnode->cache)->VnodeDeleted(); // The file system has removed the resources of the vnode now, so we can @@ -4021,7 +4021,7 @@ change_vnode_id(fs_volume* volume, ino_t vnodeID, ino_t newID) vnode->id = newID; sVnodeTable->Insert(vnode); - if (vnode->cache != NULL) + if (vnode->cache != NULL && vnode->cache->type == CACHE_TYPE_VNODE) ((VMVnodeCache*)vnode->cache)->SetVnodeID(newID); return B_OK; @@ -4828,6 +4828,31 @@ vfs_get_vnode_cache(struct vnode* vnode, VMCache** _cache, bool allocate) } +/*! Sets the vnode's VMCache object, for subsystems that want to manage + their own. + In case it's successful, it will also grab a reference to the cache + it returns. +*/ +extern "C" status_t +vfs_set_vnode_cache(struct vnode* vnode, VMCache* _cache) +{ + rw_lock_read_lock(&sVnodeLock); + vnode->Lock(); + + status_t status = B_OK; + if (vnode->cache != NULL) { + status = B_NOT_ALLOWED; + } else { + vnode->cache = _cache; + _cache->AcquireRef(); + } + + vnode->Unlock(); + rw_lock_read_unlock(&sVnodeLock); + return status; +} + + status_t vfs_get_file_map(struct vnode* vnode, off_t offset, size_t size, file_io_vec* vecs, size_t* _count)