ea2cd27e57
vm_cache_ref starts with a reference count of 1. When acquiring a vm_cache, you no longer need to worry if that should go through the vm_store, or not; as it now always does. * map_backing_store() no longer needs to play with the vm_cache_ref references. * that simplified some code. * vfs_get_vnode_cache() now grabs a reference to the cache, if successful. * better balanced vnode ownership on vnode_store creation (vnode_store released the vnode before if its creation failed). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15641 a95241bf-73f2-0310-859d-f6bbb57e9c96
128 lines
2.7 KiB
C++
128 lines
2.7 KiB
C++
/*
|
|
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
|
|
#include "vnode_store.h"
|
|
|
|
#include <file_cache.h>
|
|
#include <vfs.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
static void
|
|
store_destroy(struct vm_store *store)
|
|
{
|
|
free(store);
|
|
}
|
|
|
|
|
|
static status_t
|
|
store_commit(struct vm_store *_store, off_t size)
|
|
{
|
|
vnode_store *store = (vnode_store *)_store;
|
|
|
|
store->vm.committed_size = size;
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
static bool
|
|
store_has_page(struct vm_store *_store, off_t offset)
|
|
{
|
|
// We always pretend to have the page - even if it's beyond the size of
|
|
// the file. The read function will only cut down the size of the read,
|
|
// it won't fail because of that.
|
|
return true;
|
|
}
|
|
|
|
|
|
static status_t
|
|
store_read(struct vm_store *_store, off_t offset, const iovec *vecs, size_t count, size_t *_numBytes)
|
|
{
|
|
vnode_store *store = (vnode_store *)_store;
|
|
size_t bytesUntouched = *_numBytes;
|
|
|
|
status_t status = vfs_read_pages(store->vnode, NULL, offset, vecs, count, _numBytes);
|
|
|
|
bytesUntouched -= *_numBytes;
|
|
|
|
// if the request could be filled completely, or an error occured, we're done here
|
|
if (status < B_OK || bytesUntouched == 0)
|
|
return status;
|
|
|
|
// Clear out any leftovers that were not touched by the above read - we're
|
|
// doing this here so that not every file system/device has to implement
|
|
// this
|
|
for (int32 i = count; i-- > 0 && bytesUntouched != 0;) {
|
|
size_t length = min_c(bytesUntouched, vecs[i].iov_len);
|
|
|
|
// ToDo: will have to map the pages in later (when we switch to physical pages)
|
|
memset((void *)((addr_t)vecs[i].iov_base + vecs[i].iov_len - length), 0, length);
|
|
bytesUntouched -= length;
|
|
}
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
static status_t
|
|
store_write(struct vm_store *_store, off_t offset, const iovec *vecs, size_t count, size_t *_numBytes)
|
|
{
|
|
vnode_store *store = (vnode_store *)_store;
|
|
return vfs_write_pages(store->vnode, NULL, offset, vecs, count, _numBytes);
|
|
}
|
|
|
|
|
|
static void
|
|
store_acquire_ref(struct vm_store *_store)
|
|
{
|
|
vnode_store *store = (vnode_store *)_store;
|
|
vfs_acquire_vnode(store->vnode);
|
|
}
|
|
|
|
|
|
static void
|
|
store_release_ref(struct vm_store *_store)
|
|
{
|
|
vnode_store *store = (vnode_store *)_store;
|
|
vfs_put_vnode(store->vnode);
|
|
}
|
|
|
|
|
|
static vm_store_ops sStoreOps = {
|
|
&store_destroy,
|
|
&store_commit,
|
|
&store_has_page,
|
|
&store_read,
|
|
&store_write,
|
|
NULL, /* fault */
|
|
&store_acquire_ref,
|
|
&store_release_ref
|
|
};
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
extern "C" vm_store *
|
|
vm_create_vnode_store(void *vnode)
|
|
{
|
|
vnode_store *store = (vnode_store *)malloc(sizeof(struct vnode_store));
|
|
if (store == NULL)
|
|
return NULL;
|
|
|
|
store->vm.ops = &sStoreOps;
|
|
store->vm.cache = NULL;
|
|
store->vm.committed_size = 0;
|
|
|
|
store->vnode = vnode;
|
|
store->file_cache_ref = NULL;
|
|
|
|
return &store->vm;
|
|
}
|
|
|