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