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