xref: /haiku/src/system/kernel/cache/vnode_store.cpp (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
1 /*
2  * Copyright 2004, 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, size_t *_numBytes)
45 {
46 	vnode_store *store = (vnode_store *)_store;
47 	size_t bytesUntouched = *_numBytes;
48 
49 	status_t status = vfs_read_pages(store->vnode, NULL, offset, vecs, count, _numBytes);
50 
51 	bytesUntouched -= *_numBytes;
52 
53 	// if the request could be filled completely, or an error occured, we're done here
54 	if (status < B_OK || bytesUntouched == 0)
55 		return status;
56 
57 	// Clear out any leftovers that were not touched by the above read - we're
58 	// doing this here so that not every file system/device has to implement
59 	// this
60 	for (int32 i = count; i-- > 0 && bytesUntouched != 0;) {
61 		size_t length = min_c(bytesUntouched, vecs[i].iov_len);
62 
63 		// ToDo: will have to map the pages in later (when we switch to physical pages)
64 		memset((void *)((addr_t)vecs[i].iov_base + vecs[i].iov_len - length), 0, length);
65 		bytesUntouched -= length;
66 	}
67 
68 	return B_OK;
69 }
70 
71 
72 static status_t
73 store_write(struct vm_store *_store, off_t offset, const iovec *vecs, size_t count, size_t *_numBytes)
74 {
75 	vnode_store *store = (vnode_store *)_store;
76 	return vfs_write_pages(store->vnode, NULL, offset, vecs, count, _numBytes);
77 }
78 
79 
80 static void
81 store_acquire_ref(struct vm_store *_store)
82 {
83 	vnode_store *store = (vnode_store *)_store;
84 	vfs_acquire_vnode(store->vnode);
85 }
86 
87 
88 static void
89 store_release_ref(struct vm_store *_store)
90 {
91 	vnode_store *store = (vnode_store *)_store;
92 	vfs_put_vnode(store->vnode);
93 }
94 
95 
96 static vm_store_ops sStoreOps = {
97 	&store_destroy,
98 	&store_commit,
99 	&store_has_page,
100 	&store_read,
101 	&store_write,
102 	NULL,	/* fault */
103 	&store_acquire_ref,
104 	&store_release_ref
105 };
106 
107 
108 //	#pragma mark -
109 
110 
111 extern "C" vm_store *
112 vm_create_vnode_store(void *vnode)
113 {
114 	vnode_store *store = (vnode_store *)malloc(sizeof(struct vnode_store));
115 	if (store == NULL) {
116 		vfs_put_vnode(vnode);
117 		return NULL;
118 	}
119 
120 	store->vm.ops = &sStoreOps;
121 	store->vm.cache = NULL;
122 	store->vm.committed_size = 0;
123 
124 	store->vnode = vnode;
125 	store->file_cache_ref = NULL;
126 
127 	return &store->vm;
128 }
129 
130