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