L4Re/departure

Annotated libfsserver/lib/generic/resource_registry.cc

224:4fb242f7d360
2021-10-18 Paul Boddie Renamed the registry classes to be more descriptive.
paul@93 1
/*
paul@224 2
 * Filesystem resource registry incorporating opening functionality.
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@202 22
#include "directory_resource.h"
paul@79 23
#include "file_pager.h"
paul@224 24
#include "resource_registry.h"
paul@9 25
paul@85 26
#include <systypes/fcntl.h>
paul@85 27
paul@79 28
paul@79 29
paul@209 30
/* The file object registry provides a memory page collection to the page
paul@200 31
   mappers it creates. */
paul@200 32
paul@224 33
ResourceRegistry::ResourceRegistry(Pages *pages)
paul@200 34
: _pages(pages)
paul@94 35
{
paul@94 36
}
paul@94 37
paul@85 38
paul@85 39
paul@87 40
/* Convert opening flags to map-compatible paging flags. */
paul@85 41
paul@224 42
map_flags_t ResourceRegistry::get_flags(flags_t flags)
paul@85 43
{
paul@87 44
    return flags & (O_WRONLY | O_RDWR) ? L4RE_DS_MAP_FLAG_RW : L4RE_DS_MAP_FLAG_RO;
paul@85 45
}
paul@85 46
paul@85 47
paul@85 48
paul@220 49
/* Make a directory provider. */
paul@202 50
paul@224 51
long ResourceRegistry::make_directory_provider(FileOpening *opening,
paul@224 52
                                               const char *path, flags_t flags,
paul@224 53
                                               fileid_t fileid,
paul@224 54
                                               Provider **provider)
paul@208 55
{
paul@202 56
    /* Make an accessor and a provider to encapsulate it. */
paul@202 57
paul@202 58
    DirectoryAccessor *accessor;
paul@220 59
    long err = opening->make_directory_accessor(path, flags, fileid, &accessor);
paul@202 60
paul@202 61
    if (err)
paul@202 62
        return err;
paul@202 63
paul@221 64
    *provider = new DirectoryProvider(fileid, this, accessor);
paul@202 65
    return L4_EOK;
paul@202 66
}
paul@202 67
paul@220 68
/* Make a file provider. */
paul@202 69
paul@224 70
long ResourceRegistry::make_file_provider(FileOpening *opening,
paul@224 71
                                          const char *path, flags_t flags,
paul@224 72
                                          fileid_t fileid,
paul@224 73
                                          Provider **provider)
paul@220 74
{
paul@200 75
    /* Make an accessor, page mapper, and a provider to encapsulate them. */
paul@79 76
paul@143 77
    Accessor *accessor;
paul@144 78
    long err = opening->make_accessor(path, flags, fileid, &accessor);
paul@106 79
paul@143 80
    if (err)
paul@143 81
        return err;
paul@106 82
paul@200 83
    PageMapper *mapper = new PageMapper(accessor, _pages);
paul@221 84
    *provider = new FileProvider(fileid, get_flags(flags), this, mapper);
paul@143 85
    return L4_EOK;
paul@79 86
}
paul@79 87
paul@220 88
/* Make a provider of the appropriate type. */
paul@220 89
paul@224 90
long ResourceRegistry::make_provider(FileOpening *opening,
paul@224 91
                                     const char *path, flags_t flags,
paul@224 92
                                     fileid_t fileid,
paul@224 93
                                     Provider **provider)
paul@220 94
{
paul@223 95
    long err = -L4_EIO;
paul@223 96
paul@220 97
    if (opening->accessing_directory(path, flags, fileid))
paul@223 98
        err = make_directory_provider(opening, path, flags, fileid, provider);
paul@220 99
    else if (opening->accessing_file(path, flags, fileid))
paul@223 100
        err = make_file_provider(opening, path, flags, fileid, provider);
paul@223 101
paul@223 102
    if (err)
paul@223 103
        return err;
paul@223 104
paul@223 105
    /* Register the provider. */
paul@223 106
paul@223 107
    set(fileid, *provider);
paul@223 108
    return L4_EOK;
paul@220 109
}
paul@220 110
paul@79 111
paul@79 112
paul@224 113
/* Obtain any active provider for the given 'fileid'. */
paul@224 114
paul@224 115
long ResourceRegistry::find_provider(fileid_t fileid, Provider **provider)
paul@224 116
{
paul@224 117
    /* Obtain any registered provider. */
paul@224 118
paul@224 119
    Accountable *accountable = get(fileid);
paul@224 120
paul@224 121
    if (accountable != NULL)
paul@224 122
    {
paul@224 123
        *provider = dynamic_cast<Provider *>(accountable);
paul@224 124
paul@224 125
        if ((*provider) != NULL)
paul@224 126
            return L4_EOK;
paul@224 127
        else
paul@224 128
            return -L4_EIO;
paul@224 129
    }
paul@224 130
paul@224 131
    return -L4_ENOENT;
paul@224 132
}
paul@224 133
paul@224 134
paul@224 135
paul@218 136
/* Return a resource for a filesystem object. */
paul@218 137
paul@224 138
long ResourceRegistry::get_resource(FileOpening *opening, const char *path,
paul@224 139
                                    flags_t flags, offset_t *size,
paul@224 140
                                    object_flags_t *object_flags,
paul@224 141
                                    Resource **resource)
paul@218 142
{
paul@218 143
    std::lock_guard<std::mutex> guard(_lock);
paul@218 144
paul@220 145
    /* Obtain an identifier for the object, even for new files (subject to use
paul@220 146
       of the appropriate flag). */
paul@218 147
paul@218 148
    fileid_t fileid;
paul@218 149
    long err = opening->get_fileid(path, flags, &fileid);
paul@218 150
paul@218 151
    if (err)
paul@218 152
        return err;
paul@218 153
paul@220 154
    /* Obtain a provider for the object. */
paul@220 155
paul@220 156
    Provider *provider;
paul@220 157
    err = find_provider(fileid, &provider);
paul@220 158
paul@220 159
    /* Make a new provider if necessary. */
paul@220 160
paul@220 161
    if (err == -L4_ENOENT)
paul@220 162
        err = make_provider(opening, path, flags, fileid, &provider);
paul@220 163
paul@220 164
    if (err)
paul@220 165
        return err;
paul@220 166
paul@220 167
    /* Make a resource for the provider. */
paul@220 168
paul@221 169
    return provider->make_resource(size, object_flags, resource);
paul@220 170
}
paul@220 171
paul@9 172
// vim: tabstop=4 expandtab shiftwidth=4