1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libfsserver/lib/mapping/copied_page_mapper.cc Sat May 28 00:59:04 2022 +0200
1.3 @@ -0,0 +1,154 @@
1.4 +/*
1.5 + * A page mapper providing copied memory pages or deferring to another page
1.6 + * mapper to satisfy file accesses.
1.7 + *
1.8 + * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk>
1.9 + *
1.10 + * This program is free software; you can redistribute it and/or
1.11 + * modify it under the terms of the GNU General Public License as
1.12 + * published by the Free Software Foundation; either version 2 of
1.13 + * the License, or (at your option) any later version.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful,
1.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.18 + * GNU General Public License for more details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License
1.21 + * along with this program; if not, write to the Free Software
1.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.23 + * Boston, MA 02110-1301, USA
1.24 + */
1.25 +
1.26 +#include <l4/re/c/dataspace.h>
1.27 +
1.28 +#include <string.h>
1.29 +
1.30 +#include "copied_page_mapper.h"
1.31 +
1.32 +
1.33 +
1.34 +/* Provide mapped pages populated with the given 'mapper', with pages obtained
1.35 + from the given 'pages' collection. */
1.36 +
1.37 +CopiedPageMapper::CopiedPageMapper(GenericPageMapper *mapper)
1.38 +: _mapper(mapper)
1.39 +{
1.40 + _size = _mapper->get_data_size();
1.41 +}
1.42 +
1.43 +/* Upon deallocation, purge active pages. */
1.44 +
1.45 +CopiedPageMapper::~CopiedPageMapper()
1.46 +{
1.47 +}
1.48 +
1.49 +/* Interface for the pager. */
1.50 +
1.51 +/* Return a flexpage providing access to the indicated file 'offset'.
1.52 +
1.53 + The returned flexpage will either provide direct access to the underlying
1.54 + file content or be a completely new flexpage modified through writes to
1.55 + memory. */
1.56 +
1.57 +Flexpage *CopiedPageMapper::get(offset_t offset, map_flags_t flags)
1.58 +{
1.59 + Flexpage *f = find(offset);
1.60 +
1.61 + /* Defer to the underlying page mapper if no flexpage was found. */
1.62 +
1.63 + if (f == NULL)
1.64 + {
1.65 + f = _mapper->get(offset, flags);
1.66 +
1.67 + /* Replicate the underlying flexpage if writing. */
1.68 +
1.69 + if (flags & L4RE_DS_F_W)
1.70 + {
1.71 + Flexpage *rf = replicate_flexpage(offset, f);
1.72 + _mapper->queue(f);
1.73 + f = rf;
1.74 + }
1.75 + }
1.76 +
1.77 + /* Upgrade the access flags. */
1.78 +
1.79 + f->upgrade(flags);
1.80 + return f;
1.81 +}
1.82 +
1.83 +/* Queue the given 'flexpage'. */
1.84 +
1.85 +void CopiedPageMapper::queue(Flexpage *flexpage)
1.86 +{
1.87 + if (dynamic_cast<CopiedFlexpage *>(flexpage) == NULL)
1.88 + _mapper->queue(flexpage);
1.89 +}
1.90 +
1.91 +/* Flush pages in the given range from 'start' with 'size'. */
1.92 +
1.93 +void CopiedPageMapper::flush_all(offset_t start, offset_t size)
1.94 +{
1.95 + /* NOTE: This might be superfluous since copy-on-write regions should not
1.96 + update content. */
1.97 +
1.98 + _mapper->flush_all(start, size);
1.99 +}
1.100 +
1.101 +/* Return the maximum extent of the mapped resource. */
1.102 +
1.103 +offset_t CopiedPageMapper::get_data_size()
1.104 +{
1.105 + return _size;
1.106 +}
1.107 +
1.108 +/* Set the maximum extent of the mapped resource. */
1.109 +
1.110 +void CopiedPageMapper::set_data_size(offset_t size)
1.111 +{
1.112 + _size = size;
1.113 +}
1.114 +
1.115 +/* Internal flexpage retrieval methods. */
1.116 +
1.117 +/* Find an existing flexpage for 'offset'. */
1.118 +
1.119 +Flexpage *CopiedPageMapper::find(offset_t offset)
1.120 +{
1.121 + return _map.find(offset);
1.122 +}
1.123 +
1.124 +/* Replicate an underlying flexpage for the file 'offset' using the given
1.125 + 'flexpage'. */
1.126 +
1.127 +Flexpage *CopiedPageMapper::replicate_flexpage(offset_t offset, Flexpage *flexpage)
1.128 +{
1.129 + /* Obtain a new memory region and a new flexpage. */
1.130 +
1.131 + Region *region = _memory.region(flexpage->size);
1.132 + Flexpage *replicated = new CopiedFlexpage(region);
1.133 +
1.134 + /* Configure the flexpage for the file region. */
1.135 +
1.136 + replicated->reset(offset);
1.137 +
1.138 + /* Copy the contents of the underlying flexpage. */
1.139 +
1.140 + memcpy((void *) region->start, (const void *) flexpage->region->start, flexpage->size);
1.141 +
1.142 + /* Register the flexpage for future accesses. */
1.143 +
1.144 + _map.insert(replicated);
1.145 + return replicated;
1.146 +}
1.147 +
1.148 +
1.149 +
1.150 +/* Copied flexpage constructor. */
1.151 +
1.152 +CopiedFlexpage::CopiedFlexpage(Region *region)
1.153 +: Flexpage(region)
1.154 +{
1.155 +}
1.156 +
1.157 +// vim: tabstop=4 expandtab shiftwidth=4