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