xref: /haiku/src/system/kernel/cache/vnode_store.cpp (revision b06a48ab8f30b45916a9c157b992827779182163)
1 /*
2  * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include "vnode_store.h"
8 
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include <file_cache.h>
13 #include <vfs.h>
14 
15 
16 status_t
17 VMVnodeCache::Init(struct vnode *vnode)
18 {
19 	status_t error = VMCache::Init(CACHE_TYPE_VNODE);
20 	if (error != B_OK)
21 		return error;
22 
23 	fVnode = vnode;
24 	fFileCacheRef = NULL;
25 
26 	vfs_vnode_to_node_ref(fVnode, &fDevice, &fInode);
27 
28 	return B_OK;
29 }
30 
31 
32 bool
33 VMVnodeCache::HasPage(off_t offset)
34 {
35 	// We always pretend to have the page - even if it's beyond the size of
36 	// the file. The read function will only cut down the size of the read,
37 	// it won't fail because of that.
38 	return true;
39 }
40 
41 
42 status_t
43 VMVnodeCache::Read(off_t offset, const iovec *vecs, size_t count,
44 	size_t *_numBytes)
45 {
46 	size_t bytesUntouched = *_numBytes;
47 
48 	status_t status = vfs_read_pages(fVnode, NULL, offset, vecs, count,
49 		0, _numBytes);
50 
51 	bytesUntouched -= *_numBytes;
52 
53 	// If the request could be filled completely, or an error occured,
54 	// we're done here
55 	if (status < B_OK || bytesUntouched == 0)
56 		return status;
57 
58 	// Clear out any leftovers that were not touched by the above read - we're
59 	// doing this here so that not every file system/device has to implement
60 	// this
61 	for (int32 i = count; i-- > 0 && bytesUntouched != 0;) {
62 		size_t length = min_c(bytesUntouched, vecs[i].iov_len);
63 
64 		// ToDo: will have to map the pages in later (when we switch to physical pages)
65 		memset((void *)((addr_t)vecs[i].iov_base + vecs[i].iov_len - length),
66 			0, length);
67 		bytesUntouched -= length;
68 	}
69 
70 	return B_OK;
71 }
72 
73 
74 status_t
75 VMVnodeCache::Write(off_t offset, const iovec *vecs, size_t count,
76 	size_t *_numBytes)
77 {
78 	return vfs_write_pages(fVnode, NULL, offset, vecs, count, 0, _numBytes);
79 }
80 
81 
82 status_t
83 VMVnodeCache::Fault(struct vm_address_space *aspace, off_t offset)
84 {
85 	return B_BAD_HANDLER;
86 }
87 
88 
89 status_t
90 VMVnodeCache::AcquireUnreferencedStoreRef()
91 {
92 	struct vnode *vnode;
93 	status_t status = vfs_get_vnode(fDevice, fInode, false, &vnode);
94 
95 	// If successful, update the store's vnode pointer, so that release_ref()
96 	// won't use a stale pointer.
97 	if (status == B_OK)
98 		fVnode = vnode;
99 
100 	return status;
101 }
102 
103 
104 void
105 VMVnodeCache::AcquireStoreRef()
106 {
107 	vfs_acquire_vnode(fVnode);
108 }
109 
110 
111 void
112 VMVnodeCache::ReleaseStoreRef()
113 {
114 	vfs_put_vnode(fVnode);
115 }
116 
117