L4Re/departure

Annotated libfsserver/lib/mapping/access_map.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@93 1
/*
paul@93 2
 * An access map providing memory corresponding to file regions.
paul@93 3
 *
paul@93 4
 * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
paul@93 5
 *
paul@93 6
 * This program is free software; you can redistribute it and/or
paul@93 7
 * modify it under the terms of the GNU General Public License as
paul@93 8
 * published by the Free Software Foundation; either version 2 of
paul@93 9
 * the License, or (at your option) any later version.
paul@93 10
 *
paul@93 11
 * This program is distributed in the hope that it will be useful,
paul@93 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@93 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@93 14
 * GNU General Public License for more details.
paul@93 15
 *
paul@93 16
 * You should have received a copy of the GNU General Public License
paul@93 17
 * along with this program; if not, write to the Free Software
paul@93 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@93 19
 * Boston, MA  02110-1301, USA
paul@93 20
 */
paul@93 21
paul@6 22
#include "access_map.h"
paul@6 23
paul@6 24
/* Return the flexpage supporting 'position'. */
paul@6 25
paul@6 26
Flexpage *AccessMap::find(offset_t position)
paul@6 27
{
paul@6 28
    std::lock_guard<std::mutex> guard(_lock);
paul@6 29
paul@6 30
    _AccessMap::iterator it = _flexpages.upper_bound(position);
paul@6 31
paul@6 32
    if ((_flexpages.size() > 0) && (it != _flexpages.begin()))
paul@6 33
    {
paul@6 34
        it--;
paul@6 35
paul@6 36
        if (it->second->supports_position(position))
paul@6 37
            return it->second;
paul@6 38
    }
paul@6 39
paul@6 40
    return NULL;
paul@6 41
}
paul@6 42
paul@6 43
/* Insert a mapping for 'flexpage'. */
paul@6 44
paul@6 45
void AccessMap::insert(Flexpage *flexpage)
paul@6 46
{
paul@6 47
    std::lock_guard<std::mutex> guard(_lock);
paul@6 48
paul@6 49
    _flexpages.insert(_AccessMapEntry(flexpage->base_offset, flexpage));
paul@6 50
}
paul@6 51
paul@6 52
/* Remove the mapping supported by 'flexpage'.
paul@6 53
paul@6 54
   The flexpage may have obtained by another mapper before being purged from
paul@6 55
   this object's mapping and before being purged from the queue (and thus
paul@6 56
   disassociated from this mapper), leaving an opportunity for another mapper to
paul@6 57
   now be removing it here. In such a situation, flushing has already occurred
paul@6 58
   and will not be performed again. */
paul@6 59
paul@6 60
bool AccessMap::remove(PageOwner *owner, Flexpage *flexpage)
paul@6 61
{
paul@6 62
    std::lock_guard<std::mutex> guard(_lock);
paul@6 63
paul@6 64
    _AccessMap::iterator it = _flexpages.find(flexpage->base_offset);
paul@6 65
paul@6 66
    if (it != _flexpages.end())
paul@6 67
    {
paul@6 68
        owner->flush(flexpage, true);
paul@6 69
        _flexpages.erase(flexpage->base_offset);
paul@6 70
        return true;
paul@6 71
    }
paul@6 72
paul@6 73
    return false;
paul@6 74
}
paul@6 75
paul@6 76
/* Purge all flexpages, using the 'owner' to flush their contents and
paul@6 77
   'pages' to make the flexpages available to other accessors. */
paul@6 78
paul@72 79
void AccessMap::purge(PageOwner *owner, Pages *pages)
paul@6 80
{
paul@6 81
    std::lock_guard<std::mutex> guard(_lock);
paul@6 82
paul@6 83
    _AccessMap::iterator it = _flexpages.begin(), entry;
paul@6 84
paul@6 85
    while (it != _flexpages.end())
paul@6 86
    {
paul@6 87
        entry = it;
paul@6 88
        it++;
paul@6 89
paul@6 90
        Flexpage *flexpage = entry->second;
paul@6 91
paul@6 92
        /* Some flexpages may be unavailable in the queue. Only those
paul@6 93
           that can be reserved should be flushed and made available
paul@6 94
           again. */
paul@6 95
paul@6 96
        if (pages->reserve(owner, flexpage))
paul@6 97
        {
paul@6 98
            owner->flush(flexpage, true);
paul@6 99
            pages->release(flexpage);
paul@6 100
            _flexpages.erase(entry);
paul@6 101
        }
paul@6 102
    }
paul@6 103
}
paul@6 104
paul@6 105
/* Flush flexpages in the given range from 'start' with 'size', using 'owner'
paul@6 106
   and 'pages'. */
paul@6 107
paul@72 108
void AccessMap::flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages)
paul@6 109
{
paul@6 110
    offset_t end = start + size;
paul@6 111
paul@6 112
    std::lock_guard<std::mutex> guard(_lock);
paul@6 113
paul@6 114
    /* The start may be within an existing flexpage where the flexpage size is a
paul@6 115
       page multiple. */
paul@6 116
paul@6 117
    _AccessMap::iterator it = _flexpages.upper_bound(start), entry;
paul@6 118
paul@6 119
    if ((_flexpages.size() > 0) && (it != _flexpages.begin()))
paul@6 120
        it--;
paul@6 121
paul@6 122
    /* Inspect flexpages at or after start until end. */
paul@6 123
paul@6 124
    while (it != _flexpages.end())
paul@6 125
    {
paul@6 126
        entry = it;
paul@6 127
        it++;
paul@6 128
paul@6 129
        Flexpage *flexpage = entry->second;
paul@6 130
paul@6 131
        if (flexpage->base_offset >= end)
paul@6 132
            break;
paul@6 133
paul@6 134
        /* Attempt to flush each flexpage, releasing ones that are no longer
paul@6 135
           needed. */
paul@6 136
paul@6 137
        if (pages->reserve(owner, flexpage))
paul@6 138
        {
paul@6 139
            owner->flush(flexpage, false);
paul@6 140
paul@6 141
            /* Where no users of the flexpage persist, release the flexpage for
paul@6 142
               reuse and remove this entry. */
paul@6 143
paul@6 144
            if (!flexpage->valid())
paul@6 145
            {
paul@6 146
                pages->release(flexpage);
paul@6 147
                _flexpages.erase(entry);
paul@6 148
            }
paul@6 149
            else
paul@6 150
                pages->queue(owner, flexpage);
paul@6 151
        }
paul@6 152
    }
paul@6 153
}
paul@6 154
paul@6 155
// vim: tabstop=4 expandtab shiftwidth=4