L4Re/departure

libfsserver/lib/mapping/page_mapper.cc

618:7123a7307a82
8 months ago Paul Boddie Introduced some debugging output control.
     1 /*     2  * A page mapper providing memory pages to satisfy file accesses.     3  *     4  * Copyright (C) 2021, 2022, 2023 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 "page_mapper.h"    23     24     25     26 /* Provide mapped pages populated with the given 'accessor', with pages obtained    27    from the given 'pages' collection. */    28     29 PageMapper::PageMapper(Accessor *accessor, Pages *pages)    30 : _accessor(accessor), _pages(pages)    31 {    32 }    33     34 /* Upon deallocation, purge active pages. */    35     36 PageMapper::~PageMapper()    37 {    38     _map.purge(this, _pages);    39 }    40     41 /* Interface for the pager. */    42     43 /* Return a flexpage providing access to the indicated file 'offset'.    44     45    The returned flexpage will either be an existing, compatible flexpage or a    46    completely new flexpage.    47     48    This method locks the mapper to prevent concurrent queries with the same    49    details, with the lock held until the queue operation releases the lock. */    50     51 Flexpage *PageMapper::get(offset_t offset, map_flags_t flags)    52 {    53     _lock.lock();    54     55     Flexpage *f = find(offset);    56     57     if (f == NULL)    58         f = flexpage(offset);    59     60     /* Record a new user of the flexpage and upgrade the access flags. */    61     62     f->increment();    63     f->upgrade(flags);    64     return f;    65 }    66     67 /* Queue the given 'flexpage' in the page collection, making it available for    68    eventual reuse.    69     70    This method unlocks the mapper. */    71     72 void PageMapper::queue(Flexpage *flexpage)    73 {    74     _pages->queue(this, flexpage);    75     76     _lock.unlock();    77 }    78     79 /* Flush pages in the given range from 'start' with 'size'. */    80     81 void PageMapper::flush_all(offset_t start, offset_t size)    82 {    83     std::lock_guard<std::mutex> guard(_lock);    84     85     _map.flush_all(start, size, this, _pages);    86 }    87     88 /* Return the maximum extent of the mapped resource. */    89     90 offset_t PageMapper::get_data_size()    91 {    92     return _accessor->get_size();    93 }    94     95 /* Set the maximum extent of the mapped resource. */    96     97 void PageMapper::set_data_size(offset_t size)    98 {    99     _accessor->set_size(size);   100 }   101    102 /* Internal flexpage retrieval methods. */   103    104 /* Find an existing flexpage for 'offset'. Where the accessor has registered a   105    compatible flexpage, an attempt is made to reserve it in the page collection;   106    if this succeeds, the flexpage is returned. Otherwise, NULL is returned. */   107    108 Flexpage *PageMapper::find(offset_t offset)   109 {   110     Flexpage *flexpage = _map.find(offset);   111    112     /* Between finding and reserving a flexpage, there is a possibility that   113        another accessor might acquire the flexpage, issue it, and even purge   114        it. */   115    116     if ((flexpage != NULL) && _pages->reserve(this, flexpage))   117         return flexpage;   118     else   119         return NULL;   120 }   121    122 /* Obtain a new flexpage for the file 'offset'. If the page collection is unable   123    to obtain a completely new flexpage, an existing flexpage is requested from   124    the page collection and recycled.   125    126    The obtained flexpage is filled with content. */   127    128 Flexpage *PageMapper::flexpage(offset_t offset)   129 {   130     Flexpage *flexpage = _pages->flexpage();   131    132     flexpage->reset(offset);   133    134     fill(flexpage);   135     _map.insert(flexpage);   136     return flexpage;   137 }   138    139 /* Interface for the page collection. */   140    141 /* Remove the record of 'flexpage' in this accessor, flushing its content. */   142    143 void PageMapper::remove(Flexpage *flexpage)   144 {   145     _map.remove(this, flexpage);   146 }   147    148 /* Data transfer methods. */   149    150 void PageMapper::fill(Flexpage *flexpage)   151 {   152     _accessor->fill(flexpage);   153 }   154    155 void PageMapper::flush(Flexpage *flexpage, bool purge)   156 {   157     if (flexpage->decrement() || purge)   158     {   159         /* NOTE: Derived flexpages might potentially support their contents   160                  being merged into the flushed data, although this is a   161                  non-trivial problem. */   162    163         if (flexpage->modified())   164             _accessor->flush(flexpage);   165    166         /* Unmap the flexpage, requiring users of its memory to request another   167            flexpage in future. This also unmaps all derived flexpages, since   168            these rely on the underlying file contents. */   169    170         flexpage->invalidate();   171     }   172 }   173    174 // vim: tabstop=4 expandtab shiftwidth=4