1 /* 2 * General functionality supporting file paging. 3 * 4 * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include "file_pager.h" 23 #include "file_paging.h" 24 25 #include <systypes/fcntl.h> 26 27 28 29 FilePaging::FilePaging(Pages *pages) 30 : _pages(pages) 31 { 32 } 33 34 FilePaging::~FilePaging() 35 { 36 } 37 38 39 40 /* Return any registered page mapper for the given 'fileid' or NULL if no such 41 mapper is registered. */ 42 43 PageMapper *FilePaging::get(fileid_t fileid) 44 { 45 FileMapping::iterator entry = _mappers.find(fileid); 46 PageMapper *mapper; 47 48 if (entry == _mappers.end()) 49 mapper = NULL; 50 else 51 mapper = entry->second; 52 53 return mapper; 54 } 55 56 /* Remove a page mapper and its resources for the given 'fileid'. */ 57 58 void FilePaging::remove(fileid_t fileid, PageMapper *mapper) 59 { 60 _mappers.erase(fileid); 61 delete mapper->accessor(); 62 delete mapper; 63 } 64 65 /* Register a page 'mapper' for the given 'fileid'. */ 66 67 void FilePaging::set(fileid_t fileid, PageMapper *mapper) 68 { 69 FileMapping::iterator entry = _mappers.find(fileid); 70 71 if (entry == _mappers.end()) 72 _mappers[fileid] = mapper; 73 } 74 75 76 77 /* Convert opening flags to map-compatible paging flags. */ 78 79 flags_t FilePaging::get_flags(flags_t flags) 80 { 81 return flags & (O_WRONLY | O_RDWR) ? L4RE_DS_MAP_FLAG_RW : L4RE_DS_MAP_FLAG_RO; 82 } 83 84 85 86 /* Obtain a page mapper for the 'fileid' or register a new one in the 87 paging object. */ 88 89 PageMapper *FilePaging::get_mapper(const char *path, fileid_t fileid) 90 { 91 /* Obtain any registered page mapper. */ 92 93 PageMapper *mapper = get(fileid); 94 95 if (mapper != NULL) 96 return mapper; 97 98 /* Make an accessor and page mapper, registering the mapper. */ 99 100 Accessor *accessor = make_accessor(path, fileid); 101 102 if (accessor == NULL) 103 return NULL; 104 105 mapper = new PageMapper(accessor, _pages); 106 107 set(fileid, mapper); 108 109 return mapper; 110 } 111 112 113 114 /* Return a pager initialised with a page mapper. */ 115 116 Pager *FilePaging::get_pager(const char *path, fileid_t fileid, flags_t flags) 117 { 118 std::lock_guard<std::mutex> guard(_lock); 119 120 /* Initialise the pager with the mapper and a reference to this object for 121 closing the mapper and accessor. */ 122 123 PageMapper *mapper = get_mapper(path, fileid); 124 125 if (mapper == NULL) 126 return NULL; 127 128 return new FilePager(fileid, mapper, flags, this); 129 } 130 131 /* Detach a pager, potentially removing its resources. */ 132 133 void FilePaging::detach_pager(fileid_t fileid, PageMapper *mapper) 134 { 135 std::lock_guard<std::mutex> guard(_lock); 136 137 if (!mapper->detach()) 138 remove(fileid, mapper); 139 } 140 141 // vim: tabstop=4 expandtab shiftwidth=4