L4Re/departure

Annotated docs/wiki/Mechanisms

304:eae169ac85c0
2022-03-25 Paul Boddie Adjusted the resource description, also adding filesystem-related opener configuration details.
paul@233 1
= Mechanisms =
paul@233 2
paul@233 3
Within the filesystem server library, a number of different abstractions and
paul@233 4
mechanisms are employed to provide access to filesystem objects.
paul@233 5
paul@233 6
<<TableOfContents(2,3)>>
paul@233 7
paul@233 8
The abstractions or components used in the library are organised as follows.
paul@233 9
paul@233 10
######## A graph showing the relationships between library components
paul@233 11
paul@233 12
{{{#!graphviz
paul@233 13
#format svg
paul@233 14
#transform notugly
paul@233 15
digraph components {
paul@233 16
  node [fontsize="12.0",fontname="sans-serif",shape=box];
paul@233 17
  edge [fontsize="12.0",fontname="sans-serif"];
paul@233 18
  rankdir=LR;
paul@233 19
paul@233 20
  subgraph {
paul@233 21
    rank=same;
paul@233 22
paul@233 23
    Resource -> DirectoryResource -> FilePager
paul@233 24
    [dir=none,style=dotted];
paul@233 25
  }
paul@233 26
paul@233 27
  subgraph {
paul@233 28
    rank=same;
paul@233 29
paul@233 30
    Provider -> DirectoryProvider -> FileProvider
paul@233 31
    [dir=none,style=dotted];
paul@233 32
  }
paul@233 33
paul@233 34
  subgraph {
paul@233 35
    rank=same;
paul@233 36
paul@233 37
    Accessor -> Ext2FileAccessor
paul@233 38
    [dir=none,style=dotted];
paul@233 39
  }
paul@233 40
paul@233 41
  subgraph {
paul@233 42
    rank=same;
paul@233 43
paul@233 44
    DirectoryAccessor -> Ext2DirectoryAccessor
paul@233 45
    [dir=none,style=dotted];
paul@233 46
  }
paul@233 47
paul@233 48
  subgraph {
paul@233 49
    node [shape=ellipse];
paul@233 50
    rank=same;
paul@233 51
paul@233 52
    Directory [label="dir"];
paul@233 53
    File [label="dir/file"];
paul@233 54
  }
paul@233 55
paul@233 56
  DirectoryResource -> DirectoryProvider -> Ext2DirectoryAccessor -> Directory;
paul@233 57
  FilePager -> FileProvider -> Ext2FileAccessor -> File;
paul@233 58
}
paul@233 59
}}}
paul@233 60
paul@233 61
########
paul@233 62
paul@233 63
== Accountable ==
paul@233 64
paul@233 65
This interface provides the following operations:
paul@233 66
paul@233 67
{{{
paul@233 68
attach()
paul@233 69
detach(out unsigned int count)
paul@233 70
}}}
paul@233 71
paul@233 72
Its purpose is to provide reference counting for components, with the `attach`
paul@233 73
operation incrementing the number of users of a component, and with the
paul@233 74
`detach` operation decrementing the number of users. When components no longer
paul@233 75
have any attached users, they may perform operations to tidy up after
paul@233 76
themselves and permit their deallocation.
paul@233 77
paul@233 78
== Accessors ==
paul@233 79
paul@233 80
Accessors provide the means of accessing filesystem object data and metadata.
paul@233 81
Conceptually, files and directories are both exposed by accessors, although
paul@233 82
the interfaces and mechanisms may differ between these types of objects.
paul@233 83
paul@233 84
=== Directory Accessors ===
paul@233 85
paul@233 86
Currently, directory accessors provide support for traversing directory
paul@233 87
listings, obtaining the relevant filesystem metadata using the underlying
paul@233 88
filesystem access library.
paul@233 89
paul@233 90
=== File Accessors ===
paul@233 91
paul@233 92
File content is accessed through an interface with the following operations:
paul@233 93
paul@233 94
{{{
paul@233 95
close()
paul@233 96
fill(inout Flexpage flexpage)
paul@233 97
flush(inout Flexpage flexpage)
paul@233 98
get_size(out offset_t size)
paul@233 99
set_size(in offset_t size)
paul@233 100
}}}
paul@233 101
paul@233 102
The operations need to be supported with actual filesystem operations. For
paul@233 103
example, ext2-based filesystems employ a specific abstraction which invokes
paul@233 104
library functions provided by the `libext2fs` package.
paul@233 105
paul@233 106
== Providers ==
paul@233 107
paul@233 108
Providers encapsulate the essential functionality for accessing filesystem
paul@233 109
objects. Implementing the `Accountable` interface, they are shared by
paul@233 110
resources and discarded when no resources are using them.
paul@233 111
paul@233 112
The following operations are supported by providers:
paul@233 113
paul@233 114
{{{
paul@233 115
registry(out ProviderRegistry *registry)
paul@233 116
make_resource(out offset_t size, out object_flags_t object_flags, out Resource *resource)
paul@233 117
}}}
paul@233 118
paul@233 119
Providers are associated with filesystem objects in a registry which can be
paul@233 120
obtained from each provider.
paul@233 121
paul@233 122
Providers also support the creation of resources through which each user of a
paul@233 123
provider exercises its use of that provider.
paul@233 124
paul@233 125
== Resources ==
paul@233 126
paul@304 127
Resources are objects accessed by clients that support a basic level of
paul@304 128
accounting and management.
paul@233 129
paul@233 130
The base interface of a resource is as follows:
paul@233 131
paul@233 132
{{{
paul@233 133
activate()
paul@233 134
close()
paul@233 135
}}}
paul@233 136
paul@233 137
Activation of a resource is an optional operation that performs any
paul@233 138
initialisation before a resource is made available to its user.
paul@233 139
paul@233 140
In practice, other operations are required to make resources useful.
paul@233 141
paul@304 142
In some cases, resources provide the mechanism by which each user of a
paul@304 143
filesystem object may access that object independently. They would then
paul@304 144
effectively provide a session in which accesses can occur.
paul@304 145
paul@233 146
=== Directory Resources ===
paul@233 147
paul@233 148
Directory resources primarily expose the contents of directories in the
paul@304 149
filesystem to a user. They employ directory accessors which concern themselves
paul@304 150
with the actual filesystem content.
paul@233 151
paul@233 152
[[Components#Directories|Directory components]] are provided using directory
paul@233 153
resources.
paul@233 154
paul@304 155
=== Pagers or File Resources ===
paul@233 156
paul@233 157
Pagers are resources that support dataspace access operations, thus allowing
paul@304 158
the resources to expose filesystem content in mapped memory regions to a
paul@304 159
particular user of the object providing the content.
paul@233 160
paul@233 161
[[Components#Files|File components]] and [[Components#Pipes|pipe components]]
paul@233 162
are provided using pagers.
paul@233 163
paul@304 164
=== Filesystem Resources ===
paul@304 165
paul@304 166
Filesystem resources provide the entry point for access to a filesystem by
paul@304 167
other components or programs. Since filesystems often enforce identity-based
paul@304 168
access controls, a filesystem resource will typically support the
paul@304 169
`open_for_user` operation in various forms, with the result of this operation
paul@304 170
being the instantiation of an `OpenerResource` configured for the indicated
paul@304 171
user identity.
paul@304 172
paul@233 173
== Registries ==
paul@233 174
paul@233 175
The basic mechanism for obtaining a resource involves a registry, as
paul@233 176
illustrated by the following diagram.
paul@233 177
paul@233 178
######## A graph showing the use of a registry in obtaining resources
paul@233 179
paul@233 180
{{{#!graphviz
paul@233 181
#format svg
paul@233 182
#transform notugly
paul@233 183
digraph registry {
paul@233 184
  node [fontsize="12.0",fontname="sans-serif",shape=box];
paul@233 185
  edge [fontsize="12.0",fontname="sans-serif"];
paul@233 186
  rankdir=LR;
paul@233 187
paul@233 188
  subgraph {
paul@233 189
    node [label="OpenerContextResource"];
paul@233 190
    rank=same;
paul@233 191
paul@233 192
    OpenerContextResource1 -> OpenerContextResource2 [dir=none,style=dotted];
paul@233 193
  }
paul@233 194
paul@233 195
  subgraph {
paul@233 196
    node [label="OpenerResource"];
paul@233 197
    rank=same;
paul@233 198
paul@233 199
    OpenerResource1 -> OpenerResource2 [dir=none,style=dotted];
paul@233 200
  }
paul@233 201
paul@233 202
  subgraph {
paul@233 203
    rank=same;
paul@233 204
paul@233 205
    ResourceRegistry -> Resource;
paul@233 206
  }
paul@233 207
paul@233 208
  subgraph {
paul@233 209
    rank=same;
paul@233 210
paul@233 211
    ProviderRegistry -> Provider;
paul@233 212
  }
paul@233 213
paul@233 214
  OpenerContextResource1 -> OpenerResource1 [label="open"];
paul@233 215
  OpenerResource1 -> ResourceRegistry [label="get_resource"];
paul@233 216
  ResourceRegistry -> ProviderRegistry [label="get/set"];
paul@233 217
paul@233 218
  Provider -> Resource -> OpenerResource2 -> OpenerContextResource2;
paul@233 219
}
paul@233 220
}}}
paul@233 221
paul@233 222
########
paul@303 223
paul@303 224
The `ResourceRegistry` coordinates access to filesystem resources and, through
paul@303 225
synchronisation, prevents conflicting operations from occurring concurrently.
paul@303 226
For example, a removal operation on a file may not be allowed to occur while
paul@303 227
an opening operation is in progress.
paul@303 228
paul@303 229
To achieve this, a common lock is employed to serialise access, with any
paul@303 230
underlying filesystem operations being initiated from the registry while the
paul@303 231
lock is held. An object providing the `FileOpening` interface for a filesystem
paul@303 232
provides such operations, and the following interaction pattern is thereby
paul@303 233
employed:
paul@303 234
paul@303 235
######## A graph showing the registry coordinating filesystem operations
paul@303 236
paul@303 237
{{{#!graphviz
paul@303 238
#format svg
paul@303 239
#transform notugly
paul@303 240
digraph registry_operations {
paul@303 241
  node [fontsize="12.0",fontname="sans-serif",shape=box];
paul@303 242
  edge [fontsize="12.0",fontname="sans-serif"];
paul@303 243
  rankdir=LR;
paul@303 244
paul@303 245
  OpenerContextResource -> OpenerResource -> ResourceRegistry -> FileOpening;
paul@303 246
}
paul@303 247
}}}
paul@303 248
paul@303 249
########
paul@303 250
paul@303 251
Since the `ResourceRegistry` functionality is generic, it could be specialised
paul@303 252
for each filesystem or be configured with an appropriate reference to a
paul@303 253
`FileOpening` object. The `OpenerResource` would then be generic, invoking the
paul@303 254
registry which would, in turn, invoke the opening object.
paul@303 255
paul@303 256
However, the chosen approach is to permit `OpenerResource` objects to
paul@303 257
implement the `FileOpening` interface for each filesystem, meaning that the
paul@303 258
`ResourceRegistry` will end up being called by the opener and then invoking
paul@304 259
the opener in return. This is slightly more convenient than the alternative
paul@304 260
since the opener can be configured with a given user identity, and such
paul@304 261
identity details will ultimately be employed when accessing the underlying
paul@304 262
filesystem itself.