L4Re/departure

docs/wiki/FilesystemAccess

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