L4Re/departure

Annotated libfsserver/lib/mapping/copied_page_mapper.cc

645:3047b11cc814
7 months ago Paul Boddie Fixed the file_data_available result to return zero if the populated span has somehow become less than the current position in the memory region.
paul@342 1
/*
paul@342 2
 * A page mapper providing copied memory pages or deferring to another page
paul@342 3
 * mapper to satisfy file accesses.
paul@342 4
 *
paul@342 5
 * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk>
paul@342 6
 *
paul@342 7
 * This program is free software; you can redistribute it and/or
paul@342 8
 * modify it under the terms of the GNU General Public License as
paul@342 9
 * published by the Free Software Foundation; either version 2 of
paul@342 10
 * the License, or (at your option) any later version.
paul@342 11
 *
paul@342 12
 * This program is distributed in the hope that it will be useful,
paul@342 13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@342 14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@342 15
 * GNU General Public License for more details.
paul@342 16
 *
paul@342 17
 * You should have received a copy of the GNU General Public License
paul@342 18
 * along with this program; if not, write to the Free Software
paul@342 19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@342 20
 * Boston, MA  02110-1301, USA
paul@342 21
 */
paul@342 22
paul@342 23
#include <l4/re/c/dataspace.h>
paul@342 24
paul@342 25
#include <string.h>
paul@342 26
paul@342 27
#include "copied_page_mapper.h"
paul@342 28
paul@342 29
paul@342 30
paul@342 31
/* Provide mapped pages populated with the given 'mapper', with pages obtained
paul@342 32
   from the given 'pages' collection. */
paul@342 33
paul@342 34
CopiedPageMapper::CopiedPageMapper(GenericPageMapper *mapper)
paul@342 35
: _mapper(mapper)
paul@342 36
{
paul@342 37
    _size = _mapper->get_data_size();
paul@342 38
}
paul@342 39
paul@345 40
/* Upon deallocation, release allocated flexpages. */
paul@342 41
paul@342 42
CopiedPageMapper::~CopiedPageMapper()
paul@342 43
{
paul@345 44
    while (!_queue.empty())
paul@345 45
    {
paul@345 46
        Flexpage *flexpage = _queue.front();
paul@345 47
paul@345 48
        _queue.pop_front();
paul@345 49
        _memory.release(flexpage->region);
paul@345 50
        delete flexpage;
paul@345 51
    }
paul@342 52
}
paul@342 53
paul@342 54
/* Interface for the pager. */
paul@342 55
paul@342 56
/* Return a flexpage providing access to the indicated file 'offset'.
paul@342 57
paul@342 58
   The returned flexpage will either provide direct access to the underlying
paul@342 59
   file content or be a completely new flexpage modified through writes to
paul@342 60
   memory. */
paul@342 61
paul@342 62
Flexpage *CopiedPageMapper::get(offset_t offset, map_flags_t flags)
paul@342 63
{
paul@342 64
    Flexpage *f = find(offset);
paul@342 65
paul@342 66
    /* Defer to the underlying page mapper if no flexpage was found. */
paul@342 67
paul@342 68
    if (f == NULL)
paul@342 69
    {
paul@342 70
        f = _mapper->get(offset, flags);
paul@342 71
paul@342 72
        /* Replicate the underlying flexpage if writing. */
paul@342 73
paul@342 74
        if (flags & L4RE_DS_F_W)
paul@342 75
        {
paul@342 76
            Flexpage *rf = replicate_flexpage(offset, f);
paul@342 77
            _mapper->queue(f);
paul@342 78
            f = rf;
paul@342 79
        }
paul@342 80
    }
paul@342 81
paul@342 82
    /* Upgrade the access flags. */
paul@342 83
paul@342 84
    f->upgrade(flags);
paul@342 85
    return f;
paul@342 86
}
paul@342 87
paul@342 88
/* Queue the given 'flexpage'. */
paul@342 89
paul@342 90
void CopiedPageMapper::queue(Flexpage *flexpage)
paul@342 91
{
paul@342 92
    if (dynamic_cast<CopiedFlexpage *>(flexpage) == NULL)
paul@342 93
        _mapper->queue(flexpage);
paul@342 94
}
paul@342 95
paul@342 96
/* Flush pages in the given range from 'start' with 'size'. */
paul@342 97
paul@342 98
void CopiedPageMapper::flush_all(offset_t start, offset_t size)
paul@342 99
{
paul@342 100
    /* NOTE: This might be superfluous since copy-on-write regions should not
paul@342 101
             update content. */
paul@342 102
paul@342 103
    _mapper->flush_all(start, size);
paul@342 104
}
paul@342 105
paul@342 106
/* Return the maximum extent of the mapped resource. */
paul@342 107
paul@342 108
offset_t CopiedPageMapper::get_data_size()
paul@342 109
{
paul@342 110
    return _size;
paul@342 111
}
paul@342 112
paul@342 113
/* Set the maximum extent of the mapped resource. */
paul@342 114
paul@342 115
void CopiedPageMapper::set_data_size(offset_t size)
paul@342 116
{
paul@342 117
    _size = size;
paul@342 118
}
paul@342 119
paul@342 120
/* Internal flexpage retrieval methods. */
paul@342 121
paul@342 122
/* Find an existing flexpage for 'offset'. */
paul@342 123
paul@342 124
Flexpage *CopiedPageMapper::find(offset_t offset)
paul@342 125
{
paul@342 126
    return _map.find(offset);
paul@342 127
}
paul@342 128
paul@342 129
/* Replicate an underlying flexpage for the file 'offset' using the given
paul@342 130
   'flexpage'. */
paul@342 131
paul@342 132
Flexpage *CopiedPageMapper::replicate_flexpage(offset_t offset, Flexpage *flexpage)
paul@342 133
{
paul@342 134
    /* Obtain a new memory region and a new flexpage. */
paul@342 135
paul@342 136
    Region *region = _memory.region(flexpage->size);
paul@342 137
    Flexpage *replicated = new CopiedFlexpage(region);
paul@342 138
paul@342 139
    /* Configure the flexpage for the file region. */
paul@342 140
paul@342 141
    replicated->reset(offset);
paul@342 142
paul@342 143
    /* Copy the contents of the underlying flexpage. */
paul@342 144
paul@342 145
    memcpy((void *) region->start, (const void *) flexpage->region->start, flexpage->size);
paul@342 146
paul@345 147
    /* Register the flexpage for future accesses and for deallocation. */
paul@342 148
paul@342 149
    _map.insert(replicated);
paul@345 150
    _queue.push_back(replicated);
paul@342 151
    return replicated;
paul@342 152
}
paul@342 153
paul@342 154
paul@342 155
paul@342 156
/* Copied flexpage constructor. */
paul@342 157
paul@342 158
CopiedFlexpage::CopiedFlexpage(Region *region)
paul@342 159
: Flexpage(region)
paul@342 160
{
paul@342 161
}
paul@342 162
paul@342 163
// vim: tabstop=4 expandtab shiftwidth=4