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