xref: /haiku/src/system/kernel/cache/vnode_store.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
1 /*
2  * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "vnode_store.h"
8 
9 #include <file_cache.h>
10 #include <vfs.h>
11 
12 #include <stdlib.h>
13 #include <string.h>
14 
15 
16 static void
17 store_destroy(struct vm_store *store)
18 {
19 	free(store);
20 }
21 
22 
23 static status_t
24 store_commit(struct vm_store *_store, off_t size)
25 {
26 	vnode_store *store = (vnode_store *)_store;
27 
28 	store->vm.committed_size = size;
29 	return B_OK;
30 }
31 
32 
33 static bool
34 store_has_page(struct vm_store *_store, off_t offset)
35 {
36 	// We always pretend to have the page - even if it's beyond the size of
37 	// the file. The read function will only cut down the size of the read,
38 	// it won't fail because of that.
39 	return true;
40 }
41 
42 
43 static status_t
44 store_read(struct vm_store *_store, off_t offset, const iovec *vecs, size_t count,
45 	size_t *_numBytes, bool fsReenter)
46 {
47 	vnode_store *store = (vnode_store *)_store;
48 	size_t bytesUntouched = *_numBytes;
49 
50 	status_t status = vfs_read_pages(store->vnode, NULL, offset, vecs, count,
51 		_numBytes, fsReenter);
52 
53 	bytesUntouched -= *_numBytes;
54 
55 	// if the request could be filled completely, or an error occured, we're done here
56 	if (status < B_OK || bytesUntouched == 0)
57 		return status;
58 
59 	// Clear out any leftovers that were not touched by the above read - we're
60 	// doing this here so that not every file system/device has to implement
61 	// this
62 	for (int32 i = count; i-- > 0 && bytesUntouched != 0;) {
63 		size_t length = min_c(bytesUntouched, vecs[i].iov_len);
64 
65 		// ToDo: will have to map the pages in later (when we switch to physical pages)
66 		memset((void *)((addr_t)vecs[i].iov_base + vecs[i].iov_len - length), 0, length);
67 		bytesUntouched -= length;
68 	}
69 
70 	return B_OK;
71 }
72 
73 
74 static status_t
75 store_write(struct vm_store *_store, off_t offset, const iovec *vecs, size_t count,
76 	size_t *_numBytes, bool fsReenter)
77 {
78 	vnode_store *store = (vnode_store *)_store;
79 	return vfs_write_pages(store->vnode, NULL, offset, vecs, count, _numBytes, fsReenter);
80 }
81 
82 
83 static void
84 store_acquire_ref(struct vm_store *_store)
85 {
86 	vnode_store *store = (vnode_store *)_store;
87 	vfs_acquire_vnode(store->vnode);
88 }
89 
90 
91 static void
92 store_release_ref(struct vm_store *_store)
93 {
94 	vnode_store *store = (vnode_store *)_store;
95 	vfs_put_vnode(store->vnode);
96 }
97 
98 
99 static vm_store_ops sStoreOps = {
100 	&store_destroy,
101 	&store_commit,
102 	&store_has_page,
103 	&store_read,
104 	&store_write,
105 	NULL,	/* fault */
106 	&store_acquire_ref,
107 	&store_release_ref
108 };
109 
110 
111 //	#pragma mark -
112 
113 
114 extern "C" vm_store *
115 vm_create_vnode_store(void *vnode)
116 {
117 	vnode_store *store = (vnode_store *)malloc(sizeof(struct vnode_store));
118 	if (store == NULL)
119 		return NULL;
120 
121 	store->vm.ops = &sStoreOps;
122 	store->vm.cache = NULL;
123 	store->vm.committed_size = 0;
124 
125 	store->vnode = vnode;
126 	store->file_cache_ref = NULL;
127 
128 	return &store->vm;
129 }
130 
131