Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| SHA1 Hash: | 3812109bfcf52d99745fc33bd12d34ccea99fd02 |
|---|---|
| Date: | 2010-03-10 19:37:13 |
| User: | stephan |
| Comment: | minor tinkering and doc updates. |
Tags And Properties
- branch=trunk inherited from [c3e484d316]
- sym-trunk inherited from [c3e484d316]
Changes
Changes to include/wh/whio/whio_epfs.h
| Old (bf853fe24bc90198) | New (3aba8bcf9cd4e359) | |||
|---|---|---|---|---|
| 1 | #ifndef WANDERINGHORSE_NET_WHIO_EPFS_H_INCLUDED | 1 | #ifndef WANDERINGHORSE_NET_WHIO_EPFS_H_INCLUDED | |
| 2 | #define WANDERINGHORSE_NET_WHIO_EPFS_H_INCLUDED | 2 | #define WANDERINGHORSE_NET_WHIO_EPFS_H_INCLUDED | |
| 3 | #include "whio_dev.h" /* core whio_dev API. */ | 3 | #include "whio_dev.h" /* core whio_dev API. */ | |
| 4 | #include "whio_encode.h" /* for whio_sizeof_encoded_xxx */ | 4 | #include "whio_encode.h" /* for whio_sizeof_encoded_xxx */ | |
| 5 | #include "whio_epfs_config.h" /* EPFS compile-time config options. */ | 5 | #include "whio_epfs_config.h" /* EPFS compile-time config options. */ | |
| 81 hidden lines | ||||
| 87 | 87 | |||
| 88 | - An EFS can add data blocks on demand, but cannot currently be | 88 | - An EFS can add data blocks on demand, but cannot currently be | |
| 89 | shrunk. It needs a vaccuum-like feature. | 89 | shrunk. It needs a vaccuum-like feature. | |
| 90 | 90 | |||
| 91 | 91 | |||
| 92 | | | 92 | <b>EPFS vs. whefs</b> | |
| 93 | @section page_whio_epfs_main_whefs whio_epfs vs. whefs | | | ||
| 94 | 93 | |||
| 95 | whio_epfs is a spin-off/refactoring of the whefs project: | 94 | whio_epfs is a spin-off/refactoring of the whefs project: | |
| 96 | 95 | |||
| 97 | http://code.google.com/p/whefs/ | 96 | http://code.google.com/p/whefs/ | |
| 98 | 97 | |||
| 15 hidden lines | ||||
| 114 | 113 | |||
| 115 | - It is structured to allow stack allocation of most of its data, to | 114 | - It is structured to allow stack allocation of most of its data, to | |
| 116 | help client code reduce calls to malloc(). | 115 | help client code reduce calls to malloc(). | |
| 117 | 116 | |||
| 118 | 117 | |||
| 119 | @section whio_epfs_main_concepts EFS Concepts | | | 118 | <b>Concepts Overview</b> |
| 120 | 119 | |||
| 121 | Here is an overview of the core concepts encapsulated by this | 120 | Here is an overview of the core concepts encapsulated by this | |
| 122 | embedded (pseudo-)filesystem (EFS) API: | 121 | embedded (pseudo-)filesystem (EFS) API: | |
| 123 | 122 | |||
| 124 | - The whio_epfs class manages a single EFS container file. | 123 | - The whio_epfs class manages a single EFS container file. | |
| 13 hidden lines | ||||
| 138 | waiting to be used. The inode ID 0 is reserved as the not-an-inode | 137 | waiting to be used. The inode ID 0 is reserved as the not-an-inode | |
| 139 | sentry value. | 138 | sentry value. | |
| 140 | 139 | |||
| 141 | - Each inode is associated with 0 or more data blocks. All blocks are | 140 | - Each inode is associated with 0 or more data blocks. All blocks are | |
| 142 | the same size, as determined when the EFS is created (via | 141 | the same size, as determined when the EFS is created (via | |
| 143 | whio_epfs_mkfs2()). Each inode records the ID of its initial data block | | | 142 | whio_epfs_mkfs()). Each inode records the ID of its initial data block |
| 144 | also records its virtual size (which may span a partial block). | 143 | also records its virtual size (which may span a partial block). | |
| 145 | 144 | |||
| 146 | - Each data block contains a few bytes of bookkeeping and up to N | 145 | - Each data block contains a few bytes of bookkeeping and up to N | |
| 147 | bytes of user data (as defined via whio_epfs_mkfs2()). | | | 146 | bytes of user data (as defined via whio_epfs_mkfs()). |
| 148 | 147 | |||
| 149 | - Clients open inodes as whio_dev objects, and then access them via | 148 | - Clients open inodes as whio_dev objects, and then access them via | |
| 150 | the whio_dev API. Thus they can be used in any generic algorithms | 149 | the whio_dev API. Thus they can be used in any generic algorithms | |
| 151 | written for that API, e.g. whio_dev_writef(). They can be used with | 150 | written for that API, e.g. whio_dev_writef(). They can be used with | |
| 152 | the whio_stream interface by using whio_stream_for_dev(). | 151 | the whio_stream interface by using whio_stream_for_dev(). | |
| 153 | 152 | |||
| 154 | */ | | | 153 | **/ |
| 155 | 154 | |||
| 156 | /** @page page_whio_epfs_layout whio_epfs filesystem layout | 155 | /** @page page_whio_epfs_layout whio_epfs filesystem layout | |
| 157 | 156 | |||
| 158 | A whio_epfs filesystem (EFS) is contained in a so-called container | 157 | A whio_epfs filesystem (EFS) is contained in a so-called container | |
| 159 | file. The container file has the following internal layout: | 158 | file. The container file has the following internal layout: | |
| 12 hidden lines | ||||
| 172 | FS OPTIONS: see the whio_epfs_fsopt type. | 171 | FS OPTIONS: see the whio_epfs_fsopt type. | |
| 173 | 172 | |||
| 174 | FS HINTS: some internal hints for the EFS to help optimize certain | 173 | FS HINTS: some internal hints for the EFS to help optimize certain | |
| 175 | operations (see whio_epfs::hints). | 174 | operations (see whio_epfs::hints). | |
| 176 | 175 | |||
| 177 | INODES TABLE: each inode (EFS entry) contains the following data: | | | 176 | INODES TABLE: each inode (EFS entry) contains the following data (not necessarily |
| | | 177 | in this order): | ||
| 178 | 178 | |||
| 179 | - The numeric ID of the inode, staring with 1. | | | 179 | - The numeric ID of the inode, staring with 1. (ID 0="not an inode") |
| | | 180 | |||
| 180 | - Timestamp, in Unix-epoch format, of the last change to the inode. | 181 | - Timestamp, in Unix-epoch format, of the last change to the inode. | |
| 181 | - The logical size of the file, in bytes. | | | 182 | |
| 182 | - ID of the first data block. | | | 183 | - The virtual size of the pseudofile, in bytes. |
| | | 184 | |||
| | | 185 | - ID of the first data block, or 0 if (size==0). | ||
| | | 186 | |||
| 183 | - Internal flags. | 187 | - Internal flags. | |
| 184 | 188 | |||
| 185 | The inodes table is whio_epfs::fsopt.inodeCount entries long. | | | 189 | - IDs of the next and previous free inodes (or 0 if this inode is |
| | | 190 | used). The next/previous free inode IDs are used for managing a | ||
| | | 191 | linked list so that we can allocate new inodes to the client from | ||
| | | 192 | the free-list O(1) time. | ||
| | | 193 | |||
| | | 194 | The inodes table is whio_epfs::fsopt.inodeCount entries long, and | ||
| | | 195 | each entry takes up whio_epfs_sizeof_inode bytes in the storage. | ||
| 186 | 196 | |||
| 187 | The BLOCKS TABLE contains a list of metadata and client data. Each | 197 | The BLOCKS TABLE contains a list of metadata and client data. Each | |
| 188 | block contains: | 198 | block contains: | |
| 189 | 199 | |||
| 190 | - The numeric ID of the block, staring with 1. | 200 | - The numeric ID of the block, staring with 1. | |
| 191 | - ID of next block in the chain | 201 | - ID of next block in the chain | |
| 192 | - Internal flags. | 202 | - Internal flags. | |
| 193 | - Client data | 203 | - Client data | |
| > | 204 | - ID of next free block (or 0 if this block is used). See the notes | ||
| > | 205 | above regarding inode free-list links. | ||
| 194 | 206 | |||
| 195 | The client data part of each block is whio_epfs::fsopt::blockSize | | | 207 | The client-data part of each block is whio_epfs::fsopt::blockSize |
| 196 | bytes long. If whio_epfs::fsopt::maxBlocks is not 0 then a EFS | 208 | bytes long. If whio_epfs::fsopt::maxBlocks is not 0 then a EFS | |
| 197 | will not be allowed to expand beyond that many blocks, otherwise | 209 | will not be allowed to expand beyond that many blocks, otherwise | |
| 198 | it may grow to an arbitrary number of blocks (within the numeric | 210 | it may grow to an arbitrary number of blocks (within the numeric | |
| 199 | limits of whio_size_t). | | | 211 | limits of whio_epfs_id_t). |
| 200 | 212 | |||
| 201 | The block and inode ID 0 is reserved for "not a block" resp. "not | 213 | The block and inode ID 0 is reserved for "not a block" resp. "not | |
| 202 | an inode." | 214 | an inode." | |
| > | 215 | |||
| > | 216 | The blocks and inodes are structured as a linked list (blocks, | ||
| > | 217 | singly, and inodes, doubly). These links do not imply any sort of | ||
| > | 218 | relationship between the object, except that we use it to arrange | ||
| > | 219 | all "unused" objects in a list so that we can dole then out later | ||
| > | 220 | on. | ||
| > | 221 | |||
| > | 222 | Initially (just after EFS creation), all blocks/inodes are | ||
| > | 223 | "unused", ready to be doled out to the client. As blocks/inodes | ||
| > | 224 | are allocated to the client, the free-list link(s) is (are) | ||
| > | 225 | modified to "remove" the object from the free-list. The managing | ||
| > | 226 | whio_epfs object must simply know the ID of the first object in | ||
| > | 227 | the free-list in order to allocate, in O(1) time, the | ||
| > | 228 | object. Managing the links adds a small i/o factor to that O(1), | ||
| > | 229 | but not much: at most, read/modify/write of 1 other blocks or up | ||
| > | 230 | to 2 other inodes. | ||
| > | 231 | |||
| > | 232 | Most management is done directly at the head of the list (the | ||
| > | 233 | exception being inodes opened via an explicit ID, which require | ||
| > | 234 | manipulation later in the chain), and the free-lists operate is | ||
| > | 235 | LIFO order. The most recently "freed" object will be the next one | ||
| > | 236 | allocated. This is part of what makes the list processing quite | ||
| > | 237 | cheap and the lookup O(1). When the EFS is constructed, the | ||
| > | 238 | initialization process goes out of its way to ensure that the | ||
| > | 239 | initial list is ordered from lowest to highest record ID. | ||
| 203 | */ | 240 | */ | |
| 204 | 241 | |||
| 205 | /** @page page_whio_epfs_memcosts whio_epfs memory costs | 242 | /** @page page_whio_epfs_memcosts whio_epfs memory costs | |
| 206 | 243 | |||
| 207 | Here are some notes about the memory costs of whio_epfs, mainly | 244 | Here are some notes about the memory costs of whio_epfs, mainly | |
| 208 | for use in finding good values for use with | 245 | for use in finding good values for use with | |
| 209 | whio_epfs_mempool_setup()... | 246 | whio_epfs_mempool_setup()... | |
| > | 247 | |||
| > | 248 | For typical use, where only a couple handles are opened at once | ||
| > | 249 | and data block chains for the opened handles do not grow really | ||
| > | 250 | long, a whio_epfs object can get by with less than half a | ||
| > | 251 | kilobyte(!) of memory in use at any given time. | ||
| 210 | 252 | |||
| 211 | An opened EFS which has not opened any handles takes up | 253 | An opened EFS which has not opened any handles takes up | |
| 212 | sizeof(whio_epfs) bytes (which is, as of this writing, smaller | 254 | sizeof(whio_epfs) bytes (which is, as of this writing, smaller | |
| 213 | than sizeof(FILE)). They do not dynamically allocate any memory | 255 | than sizeof(FILE)). They do not dynamically allocate any memory | |
| 214 | until they have to open a handle. | 256 | until they have to open a handle. | |
| 215 | 257 | |||
| 216 | Each opened handle costs approximately: | 258 | Each opened handle costs approximately: | |
| 217 | 259 | |||
| 218 | - sizeof(whio_epfs_handle) | 260 | - sizeof(whio_epfs_handle) | |
| 219 | 261 | |||
| 220 | - plus (sizeof(whio_epfs_block)*N), where N is approximately equal | | | 262 | - plus (sizeof(whio_epfs_block)*N), where N is approximately |
| 221 | to the number of blocks owned by that handle. N may be larger | | | 263 | equal to the number of blocks owned by that handle. N may be |
| 222 | than the current block count due to | | | 264 | larger than the current block count due to |
| 223 | pre-allocation/reservation. The blocks list is not allocated | 265 | pre-allocation/reservation. The blocks list is not allocated | |
| 224 | until the blocks are actually read from or written to. Simply | 266 | until the blocks are actually read from or written to. Simply | |
| 225 | opening an inode will not allocate its block chain. | | | 267 | opening an inode will not allocate its block chain. There is no |
| | | 268 | client-side mechanism to determine the number of blocks | ||
| | | 269 | associated with an inode, but it can be calculated by dividing | ||
| | | 270 | the inode's size by the fs' block size. | ||
| 226 | 271 | |||
| 227 | When multiple handles are opened for the same inode: | 272 | When multiple handles are opened for the same inode: | |
| 228 | 273 | |||
| 229 | - One list of blocks is shared amongst them. | 274 | - One list of blocks is shared amongst them. | |
| 230 | 275 | |||
| 231 | - Closing the handle may not free its memory immediately - it | 276 | - Closing the handle may not free its memory immediately - it | |
| 232 | cannot be destroyed until the last opened handle pointing to it | 277 | cannot be destroyed until the last opened handle pointing to it | |
| 233 | is closed. | | | 278 | is closed. This is a side-effect of how handle sharing is |
| 234 | | | 279 | implemented (but i'd like to replace this model eventually). | |
| 235 | 280 | |||
| 236 | Using whio_epfs_dev_open() opens a handle (with the above costs) | 281 | Using whio_epfs_dev_open() opens a handle (with the above costs) | |
| 237 | and allocates about sizeof(whio_dev)+(about)20 bytes for its | 282 | and allocates about sizeof(whio_dev)+(about)20 bytes for its | |
| 238 | implementation data. | 283 | implementation data. | |
| 239 | < | |||
| 240 | For typical use, where only a few handles are opened at once and | < | ||
| 241 | block chains do not grow insanely long, a whio_epfs object can get | < | ||
| 242 | by with less than half a kilobyte of memory in use at any given | < | ||
| 243 | time. If it runs out of memory, it can be configured to fall back | < | ||
| 244 | to malloc(), realloc(), and free(), or to return allocation | < | ||
| 245 | (out-of-memory) errors. | < | ||
| 246 | < | |||
| 247 | */ | 284 | */ | |
| 248 | 285 | |||
| 249 | /** @page page_whio_epfs_conventions whio_epfs Conventions | 286 | /** @page page_whio_epfs_conventions whio_epfs Conventions | |
| 250 | 287 | |||
| 251 | 288 | |||
| 252 | Naming conventions: | | | 289 | <b>Naming conventions:</b> |
| 253 | 290 | |||
| 254 | - Types and free functions are named in lower_case_with_underscore. | 291 | - Types and free functions are named in lower_case_with_underscore. | |
| 255 | 292 | |||
| 256 | - Struct member function pointers typically use lower_with_underscore, | 293 | - Struct member function pointers typically use lower_with_underscore, | |
| 257 | but this is not a rule. | 294 | but this is not a rule. | |
| 11 hidden lines | ||||
| 269 | 306 | |||
| 270 | - Public API header files live in <wh/whio/...> and should follow the | 307 | - Public API header files live in <wh/whio/...> and should follow the | |
| 271 | same naming conventions as for Types. Private header files may be | 308 | same naming conventions as for Types. Private header files may be | |
| 272 | named or located wherever the implementor prefers. | 309 | named or located wherever the implementor prefers. | |
| 273 | 310 | |||
| 274 | ======================================================================== | | | 311 | |
| 275 | Pointer-to-pointer parameters for functions with flexible allocation | | | 312 | <b>Pointer-to-pointer parameters for functions with flexible allocation |
| 276 | rules: | | | 313 | rules:</b> |
| 277 | 314 | |||
| 278 | Many functions in the API which deal with object initialization allow | 315 | Many functions in the API which deal with object initialization allow | |
| 279 | the caller to either provide his own memory or to allow the library to | 316 | the caller to either provide his own memory or to allow the library to | |
| 280 | allocate it for him. Such functions have a signature which looks | 317 | allocate it for him. Such functions have a signature which looks | |
| 281 | something like: | 318 | something like: | |
| 5 hidden lines | ||||
| 287 | Most functions using this convention allow both of these calling options: | 324 | Most functions using this convention allow both of these calling options: | |
| 288 | 325 | |||
| 289 | Client-allocated object (stack or otherwise): | 326 | Client-allocated object (stack or otherwise): | |
| 290 | 327 | |||
| 291 | @code | 328 | @code | |
| 292 | some_type st; | | | 329 | some_type st = { ... sane values ... }; |
| 293 | some_type * ptr = &st; | 330 | some_type * ptr = &st; | |
| 294 | int rc = init_func( &ptr, ... ); | 331 | int rc = init_func( &ptr, ... ); | |
| 295 | @endcode | 332 | @endcode | |
| 296 | 333 | |||
| 297 | In that case, such functions will assume that the st object was | 334 | In that case, such functions will assume that the st object was | |
| 11 hidden lines | ||||
| 309 | @code | 346 | @code | |
| 310 | some_type * ptr = NULL; | 347 | some_type * ptr = NULL; | |
| 311 | int rc = init_func( &ptr, ... ); | 348 | int rc = init_func( &ptr, ... ); | |
| 312 | @endcode | 349 | @endcode | |
| 313 | 350 | |||
| 314 | In this case, the library will (somehow) allocate a some_type object | | | 351 | In this case, the library will (somehow try to) allocate a some_type |
| 315 | and assign *ptr to that (on success - it does not do so on error). | | | 352 | object and assign *ptr to that (on success - it does not do so on |
| 316 | The caller takes over ownership and must destroy the object as | | | 353 | error). The caller takes over ownership and must destroy the object |
| 317 | described in the documentation for init_func(). | | | 354 | as described in the documentation for init_func(). |
| 318 | | | |||
| 319 | 355 | |||
| 320 | The reasons such routines are set up this way, as opposed to simply | 356 | The reasons such routines are set up this way, as opposed to simply | |
| 321 | returning a pointer to the created resource, are: | 357 | returning a pointer to the created resource, are: | |
| 322 | 358 | |||
| 323 | - A core project goal is keeping memory costs low and reducing the | 359 | - A core project goal is keeping memory costs low and reducing the | |
| 147 hidden lines | ||||
| 471 | WHIO_EPFS_MODE_FLAG_CREATE = 0x10, | 507 | WHIO_EPFS_MODE_FLAG_CREATE = 0x10, | |
| 472 | /** | 508 | /** | |
| 473 | Convenience equivalent of (WHIO_EPFS_MODE_WRITE | WHIO_EPFS_MODE_FLAG_CREATE). | 509 | Convenience equivalent of (WHIO_EPFS_MODE_WRITE | WHIO_EPFS_MODE_FLAG_CREATE). | |
| 474 | */ | 510 | */ | |
| 475 | WHIO_EPFS_MODE_RWC = WHIO_EPFS_MODE_WRITE | WHIO_EPFS_MODE_FLAG_CREATE, | 511 | WHIO_EPFS_MODE_RWC = WHIO_EPFS_MODE_WRITE | WHIO_EPFS_MODE_FLAG_CREATE, | |
| 476 | /* | | | 512 | /** |
| 477 | Not yet used. | | | 513 | Not yet implemented. |
| 478 | 514 | |||
| 479 | Equivalent of O_EXCL (meaning fail if inode is already used). | 515 | Equivalent of O_EXCL (meaning fail if inode is already used). | |
| 480 | */ | 516 | */ | |
| 481 | WHIO_EPFS_MODE_FLAG_FAIL_IF_USED = 0x20, | 517 | WHIO_EPFS_MODE_FLAG_FAIL_IF_USED = 0x20, | |
| 482 | /** | 518 | /** | |
| 325 hidden lines | ||||
| 808 | 844 | |||
| 809 | fs->offsets[whio_epfs_index_fsopt] == offset into EFS of whio_epfs_fsopt. | 845 | fs->offsets[whio_epfs_index_fsopt] == offset into EFS of whio_epfs_fsopt. | |
| 810 | 846 | |||
| 811 | fs->sizes[whio_epfs_index_fsopt] == encoded size of whio_epfs_fsopt. | 847 | fs->sizes[whio_epfs_index_fsopt] == encoded size of whio_epfs_fsopt. | |
| 812 | */ | 848 | */ | |
| 813 | whio_epfs_index_fsopt = 1, | | | 849 | whio_epfs_index_fsopt, |
| 814 | /** whio_epfs_hints entry. | 850 | /** whio_epfs_hints entry. | |
| 815 | 851 | |||
| 816 | 852 | |||
| 817 | fs->offsets[whio_epfs_index_hints] == offset into EFS of internal fs hints. | 853 | fs->offsets[whio_epfs_index_hints] == offset into EFS of internal fs hints. | |
| 818 | 854 | |||
| 819 | fs->sizes[whio_epfs_index_hints] == encoded size of internal fs hints. | 855 | fs->sizes[whio_epfs_index_hints] == encoded size of internal fs hints. | |
| 820 | */ | 856 | */ | |
| 821 | whio_epfs_index_hints = 2, | | | 857 | whio_epfs_index_hints, |
| 822 | /** EFS label entry. | 858 | /** EFS label entry. | |
| 823 | < | |||
| 824 | Not yet used. | < | ||
| 825 | 859 | |||
| 826 | fs->offsets[whio_epfs_index_label] == offset into EFS of label string. | 860 | fs->offsets[whio_epfs_index_label] == offset into EFS of label string. | |
| 827 | 861 | |||
| 828 | fs->sizes[whio_epfs_index_label] == maximum encoded size of label string. | 862 | fs->sizes[whio_epfs_index_label] == maximum encoded size of label string. | |
| 829 | */ | 863 | */ | |
| 830 | whio_epfs_index_label = 3, | | | 864 | whio_epfs_index_label, |
| 831 | /** Inode table entry. | 865 | /** Inode table entry. | |
| 832 | 866 | |||
| 833 | fs->offsets[whio_epfs_index_inode] == offset into EFS of inode table. | 867 | fs->offsets[whio_epfs_index_inode] == offset into EFS of inode table. | |
| 834 | 868 | |||
| 835 | fs->sizes[whio_epfs_index_inode] == encoded size of whio_epfs_inode. | 869 | fs->sizes[whio_epfs_index_inode] == encoded size of whio_epfs_inode. | |
| 836 | */ | 870 | */ | |
| 837 | whio_epfs_index_inode = 4, | | | 871 | whio_epfs_index_inode, |
| 838 | /** Block table entry. | 872 | /** Block table entry. | |
| 839 | 873 | |||
| 840 | fs->offsets[whio_epfs_index_blockMeta] == offset into EFS of blocks table. | 874 | fs->offsets[whio_epfs_index_blockMeta] == offset into EFS of blocks table. | |
| 841 | 875 | |||
| 842 | fs->sizes[whio_epfs_index_blockMeta] == encoded size of whio_epfs_block. | 876 | fs->sizes[whio_epfs_index_blockMeta] == encoded size of whio_epfs_block. | |
| 843 | */ | 877 | */ | |
| 844 | whio_epfs_index_blockMeta = 5, | | | 878 | whio_epfs_index_blockMeta, |
| 845 | /** MUST be the last entry in this enum. */ | 879 | /** MUST be the last entry in this enum. */ | |
| 846 | whio_epfs_index_count = 6 | 880 | whio_epfs_index_count = 6 | |
| 847 | }; | 881 | }; | |
| 848 | /** | 882 | /** | |
| 849 | The whio_epfs_sizeof enum defines the on-storage sizes of | 883 | The whio_epfs_sizeof enum defines the on-storage sizes of | |
| 35 hidden lines | ||||
| 885 | /** | 919 | /** | |
| 886 | Encoded size of whio_epfs_hints. | 920 | Encoded size of whio_epfs_hints. | |
| 887 | */ | 921 | */ | |
| 888 | whio_epfs_sizeof_hints = 1/*tag byte*/ | 922 | whio_epfs_sizeof_hints = 1/*tag byte*/ | |
| 889 | + (5 * whio_epfs_sizeof_id) /* whio_epfs::whio_epfs_hints::( | 923 | + (5 * whio_epfs_sizeof_id) /* whio_epfs::whio_epfs_hints::( | |
| > | 924 | maxEverUsedBlock, | ||
| 890 | maxEverUsedInode, | 925 | maxEverUsedInode, | |
| 891 | freeInodeList, | 926 | freeInodeList, | |
| 892 | freeBlockList, | 927 | freeBlockList, | |
| 893 | maxEverUsedBlock, | < | ||
| 894 | blockCount) */ | 928 | blockCount) */ | |
| 895 | , | 929 | , | |
| 896 | /** | 930 | /** | |
| 897 | Encoded size of whio_epfs_inode. | 931 | Encoded size of whio_epfs_inode. | |
| 898 | */ | 932 | */ | |
| 207 hidden lines | ||||
| 1106 | whio_impl_data impl; | 1140 | whio_impl_data impl; | |
| 1107 | }; | 1141 | }; | |
| 1108 | /** Convenience typedef. */ | 1142 | /** Convenience typedef. */ | |
| 1109 | typedef struct whio_epfs_namer whio_epfs_namer; | 1143 | typedef struct whio_epfs_namer whio_epfs_namer; | |
| 1110 | /** @def whio_epfs_namer_empty_m | 1144 | /** @def whio_epfs_namer_empty_m | |
| > | 1145 | |||
| 1111 | Empty initialization whio_epfs_namer object. | 1146 | Empty initialization whio_epfs_namer object. | |
| 1112 | */ | 1147 | */ | |
| 1113 | #define whio_epfs_namer_empty_m {NULL,whio_impl_data_empty_m} | 1148 | #define whio_epfs_namer_empty_m {NULL,whio_impl_data_empty_m} | |
| 1114 | /** Empty initialization whio_epfs_namer object. */ | 1149 | /** Empty initialization whio_epfs_namer object. */ | |
| 1115 | extern const whio_epfs_namer whio_epfs_namer_empty; | 1150 | extern const whio_epfs_namer whio_epfs_namer_empty; | |
| 103 hidden lines | ||||
| 1219 | */ | 1254 | */ | |
| 1220 | whio_epfs_id_t freeInodeList; | 1255 | whio_epfs_id_t freeInodeList; | |
| 1221 | 1256 | |||
| 1222 | /** | 1257 | /** | |
| 1223 | ID of the first free block, or 0 if there are none. | 1258 | ID of the first free block, or 0 if there are none. | |
| > | 1259 | |||
| > | 1260 | Each block contains a member | ||
| > | 1261 | (whio_epfs_block::nextFree) which points to the next | ||
| > | 1262 | free item in the chain, or 0 if the block itself is | ||
| > | 1263 | used (and no longer in the free chain). | ||
| 1224 | */ | 1264 | */ | |
| 1225 | whio_epfs_id_t freeBlockList; | 1265 | whio_epfs_id_t freeBlockList; | |
| 1226 | /** | 1266 | /** | |
| 1227 | The highest block ID which has been added to the EFS. | 1267 | The highest block ID which has been added to the EFS. | |
| 1228 | */ | 1268 | */ | |
| 39 hidden lines | ||||
| 1268 | /** Memory reserved for use as an allocation source. */ | 1308 | /** Memory reserved for use as an allocation source. */ | |
| 1269 | unsigned char * mem; | 1309 | unsigned char * mem; | |
| 1270 | /** Length of mem, in bytes. */ | 1310 | /** Length of mem, in bytes. */ | |
| 1271 | whio_size_t size; | 1311 | whio_size_t size; | |
| 1272 | } pool; | 1312 | } pool; | |
| 1273 | /** Will replace the pool meember. */ | | | 1313 | /** |
| | | 1314 | Allocator used for de/re/allocating EFS-internal | ||
| | | 1315 | memory. Will someday completely replace the pool member. | ||
| | | 1316 | */ | ||
| 1274 | whio_allocator alloc; | 1317 | whio_allocator alloc; | |
| 1275 | /** Not yet used. */ | 1318 | /** Not yet used. */ | |
| 1276 | struct whio_epfs_namer_ | 1319 | struct whio_epfs_namer_ | |
| 1277 | { | 1320 | { | |
| 1278 | whio_epfs_namer * n; | 1321 | whio_epfs_namer * n; | |
| 264 hidden lines | ||||
| 1543 | to *fs, else fs is assumed to point to a clean, | 1586 | to *fs, else fs is assumed to point to a clean, | |
| 1544 | client-allocated whio_epfs object. | 1587 | client-allocated whio_epfs object. | |
| 1545 | 1588 | |||
| 1546 | How sopt is interpreted, and possibly changed, is described in | 1589 | How sopt is interpreted, and possibly changed, is described in | |
| 1547 | whio_epfs_openfs(), so please see that function for how to | 1590 | whio_epfs_openfs(), so please see that function for how to | |
| 1548 | intialize and populate it. | | | 1591 | intialize and populate it, and regarding ownership of objects |
| | | 1592 | stored in the sopt parameter. | ||
| 1549 | 1593 | |||
| 1550 | The fsopt parameter describes the basic parameters of the | 1594 | The fsopt parameter describes the basic parameters of the | |
| 1551 | filesystem. If certain ranges or combinations are violated | 1595 | filesystem. If certain ranges or combinations are violated | |
| 1552 | then whio_rc.RangeError may be returned. | 1596 | then whio_rc.RangeError may be returned. | |
| 1553 | 1597 | |||
| 2 hidden lines | ||||
| 1556 | must eventually free the returned object using | 1600 | must eventually free the returned object using | |
| 1557 | whio_epfs_finalize(). If he passed in his own object then it | 1601 | whio_epfs_finalize(). If he passed in his own object then it | |
| 1558 | must be cleaned up as appropriate (whio_epfs_finalize() for | 1602 | must be cleaned up as appropriate (whio_epfs_finalize() for | |
| 1559 | heap-allocated and whio_epfs_close() for stack-allocated). | 1603 | heap-allocated and whio_epfs_close() for stack-allocated). | |
| 1560 | 1604 | |||
| > | 1605 | Example: | ||
| > | 1606 | |||
| > | 1607 | @code | ||
| > | 1608 | // Set up general fs options: | ||
| > | 1609 | whio_epfs_fsopt fo = whio_epfs_fsopt_empty; | ||
| > | 1610 | fo.maxBlocks = 1000; // 0=grow on demand | ||
| > | 1611 | fo.blockSize = 1024 * 16; | ||
| > | 1612 | fo.inodeCount = 250; | ||
| > | 1613 | |||
| > | 1614 | // Open/mkfs-specific options, including the storage device: | ||
| > | 1615 | whio_epfs_setup_opt so = whio_epfs_setup_opt_empty; | ||
| > | 1616 | so.storage.dev = whio_dev_for_filename("my.epfs","w+"); | ||
| > | 1617 | so.storage.takeDevOnSuccess = whio_dev_for_filename("my.epfs","w+"); | ||
| > | 1618 | |||
| > | 1619 | // Create the fs: | ||
| > | 1620 | whio_efps * fs = NULL; | ||
| > | 1621 | rc = whio_epfs_mkfs( &fs, &so, &fo ); | ||
| > | 1622 | if( rc ) { //error | ||
| > | 1623 | // We need to clean up the storage device: | ||
| > | 1624 | so.storage.dev->api->finalize( so.storage.dev ); | ||
| > | 1625 | return ...; | ||
| > | 1626 | } | ||
| > | 1627 | ... use fs ... | ||
| > | 1628 | whio_epfs_finalize( fs ); | ||
| > | 1629 | @endcode | ||
| > | 1630 | |||
| > | 1631 | See also the convenience function whio_epfs_mkfs_file(), which | ||
| > | 1632 | takes a slightly higher-level set of parameters. | ||
| > | 1633 | |||
| 1561 | @see whio_epfs_mkfs2() | 1634 | @see whio_epfs_mkfs2() | |
| 1562 | @see whio_epfs_openfs() | 1635 | @see whio_epfs_openfs() | |
| > | 1636 | @see whio_epfs_mkfs_file() | ||
| 1563 | */ | 1637 | */ | |
| 1564 | int whio_epfs_mkfs( whio_epfs ** fs, whio_epfs_setup_opt * sopt, whio_epfs_fsopt const * fsopt ); | 1638 | int whio_epfs_mkfs( whio_epfs ** fs, whio_epfs_setup_opt * sopt, whio_epfs_fsopt const * fsopt ); | |
| 1565 | 1639 | |||
| 1566 | /** | 1640 | /** | |
| 1567 | This is a short-hand form of whio_epfs_mkfs() which uses | 1641 | This is a short-hand form of whio_epfs_mkfs() which uses | |
| 87 hidden lines | ||||
| 1655 | 1729 | |||
| 1656 | 1730 | |||
| 1657 | Lifetime of the opt object: | 1731 | Lifetime of the opt object: | |
| 1658 | 1732 | |||
| 1659 | After this function returns, fs does not directly point to any | 1733 | After this function returns, fs does not directly point to any | |
| 1660 | which is still set in the opt object (remember that pointers in | | | 1734 | memory which is still set in the opt object (remember that |
| 1661 | the opt object may be modified by this function - see above), and | | | 1735 | pointers in the opt object may be modified by this function - |
| 1662 | the opt object need not outlive fs. | | | 1736 | see above), and the opt object need not outlive fs. |
| 1663 | 1737 | |||
| 1664 | 1738 | |||
| 1665 | Return codes: | 1739 | Return codes: | |
| 1666 | 1740 | |||
| 1667 | Returns 0 on success. On error, the fs will be internally | 1741 | Returns 0 on success. On error, the fs will be internally | |
| 89 hidden lines | ||||
| 1757 | If writeMode is true then the device is opened in read/write mode, | 1831 | If writeMode is true then the device is opened in read/write mode, | |
| 1758 | otherwise it is opened in read-only mode. | 1832 | otherwise it is opened in read-only mode. | |
| 1759 | 1833 | |||
| 1760 | Returns 0 on success. On error non-zero is returned and *fs is | 1834 | Returns 0 on success. On error non-zero is returned and *fs is | |
| 1761 | never modified. | 1835 | never modified. | |
| > | 1836 | |||
| > | 1837 | |||
| > | 1838 | @see whio_epfs_mkfs_file() | ||
| > | 1839 | @see whio_epfs_mkfs() | ||
| > | 1840 | @see whio_epfs_open() | ||
| 1762 | */ | 1841 | */ | |
| 1763 | int whio_epfs_openfs_file( whio_epfs ** fs, char const * filename, bool writeMode ); | 1842 | int whio_epfs_openfs_file( whio_epfs ** fs, char const * filename, bool writeMode ); | |
| > | 1843 | |||
| 1764 | /** | 1844 | /** | |
| 1765 | Tries to initialize a file as an EPFS container. | 1845 | Tries to initialize a file as an EPFS container. | |
| 1766 | 1846 | |||
| 1767 | None of the parameters may be 0. | 1847 | None of the parameters may be 0. | |
| 1768 | 1848 | |||
| 9 hidden lines | ||||
| 1778 | to make a new EPFS filesystem. | 1858 | to make a new EPFS filesystem. | |
| 1779 | 1859 | |||
| 1780 | If creation of the fs fails then the file may be left in an | 1860 | If creation of the fs fails then the file may be left in an | |
| 1781 | inconsistent state and should be removed (or analysed, or | 1861 | inconsistent state and should be removed (or analysed, or | |
| 1782 | whatever) by the client. | 1862 | whatever) by the client. | |
| > | 1863 | |||
| > | 1864 | @see whio_epfs_mkfs() | ||
| > | 1865 | @see whio_epfs_open() | ||
| > | 1866 | @see whio_epfs_openfs_file() | ||
| 1783 | */ | 1867 | */ | |
| 1784 | int whio_epfs_mkfs_file( whio_epfs ** fs, | 1868 | int whio_epfs_mkfs_file( whio_epfs ** fs, | |
| 1785 | whio_epfs_fsopt const * fsopt, | 1869 | whio_epfs_fsopt const * fsopt, | |
| 1786 | char const * filename, | 1870 | char const * filename, | |
| 1787 | bool allowOverwrite ); | 1871 | bool allowOverwrite ); | |
| 2 hidden lines | ||||
| 1790 | /** | 1874 | /** | |
| 1791 | Please read all of these docs before using this function... | 1875 | Please read all of these docs before using this function... | |
| 1792 | 1876 | |||
| 1793 | First: HIGHLY EXPERIMENTAL! It normally seems to work, but once | 1877 | First: HIGHLY EXPERIMENTAL! It normally seems to work, but once | |
| 1794 | in a while i'm getting memory corruption in objects allocated | 1878 | in a while i'm getting memory corruption in objects allocated | |
| 1795 | through the custom allocator, normally via the block array | | | 1879 | through the custom allocator, seemingly via the block array |
| 1796 | reallocations (which hints at a bug in the realloc impl). | 1880 | reallocations (which hints at a bug in the realloc impl). | |
| 1797 | 1881 | |||
| 1798 | Until the above warning is gone, please do not use this | 1882 | Until the above warning is gone, please do not use this | |
| 1799 | function or the related functionality built on top of it | 1883 | function or the related functionality built on top of it | |
| 1800 | (e.g. whio_epfs_setup_opt::memory). | 1884 | (e.g. whio_epfs_setup_opt::memory). | |
| 73 hidden lines | ||||
| 1874 | The following list contains the ONLY functions which may | 1958 | The following list contains the ONLY functions which may | |
| 1875 | legally be called _before_ whio_epfs_mempool_setup(). All | 1959 | legally be called _before_ whio_epfs_mempool_setup(). All | |
| 1876 | others may indirectly induce undefined behaviour if | 1960 | others may indirectly induce undefined behaviour if | |
| 1877 | whio_epfs_mempool_setup() is called after they are called: | 1961 | whio_epfs_mempool_setup() is called after they are called: | |
| 1878 | 1962 | |||
| 1879 | - whio_epfs_mkfs2() | | | 1963 | - whio_epfs_mkfs() (not whio_epfs_mkfs2()) |
| 1880 | - whio_epfs_openfs2() | | | 1964 | - whio_epfs_openfs() (not whio_epfs_openfs2()) |
| 1881 | 1965 | |||
| 1882 | To set up a memory pool at the time the fs is initialized, as | 1966 | To set up a memory pool at the time the fs is initialized, as | |
| 1883 | opposed to afterwards, use whio_epfs_mkfs() or | 1967 | opposed to afterwards, use whio_epfs_mkfs() or | |
| 1884 | whio_epfs_openfs(). Doing so removes any concerns about legal | 1968 | whio_epfs_openfs(). Doing so removes any concerns about legal | |
| 1885 | call ordering. | 1969 | call ordering. | |
| 1886 | 1970 | |||
| 1887 | If you actually read this far, you have my blessing to use this | 1971 | If you actually read this far, you have my blessing to use this | |
| 1888 | function. If you skipped to the end, please go back and read | 1972 | function. If you skipped to the end, please go back and read | |
| 1889 | these docs before using it. | | | 1973 | these docs before using it. And then if you see weird behaviour |
| | | 1974 | please try not using this, to be sure that the allocator is not | ||
| | | 1975 | the problem. | ||
| 1890 | */ | 1976 | */ | |
| 1891 | int whio_epfs_mempool_setup( whio_epfs * fs, void * mem, whio_size_t size, bool fallback ); | 1977 | int whio_epfs_mempool_setup( whio_epfs * fs, void * mem, whio_size_t size, bool fallback ); | |
| 1892 | 1978 | |||
| 1893 | /** | 1979 | /** | |
| 1894 | A type for collecting certain metrics from a whio_epfs memory | 1980 | A type for collecting certain metrics from a whio_epfs memory | |
| 79 hidden lines | ||||
| 1974 | 2060 | |||
| 1975 | If fs was not created with whio_epfs_alloc() then results | 2061 | If fs was not created with whio_epfs_alloc() then results | |
| 1976 | are technically undefined. That said, the implementation | 2062 | are technically undefined. That said, the implementation | |
| 1977 | tries to detect if fs was allocated via whio_epfs_alloc(), | 2063 | tries to detect if fs was allocated via whio_epfs_alloc(), | |
| 1978 | and does not actually free it if it was not (which may lead | 2064 | and does not actually free it if it was not (which may lead | |
| 1979 | to a leak). | | | 2065 | to a leak, but won't immediately crash on you). |
| 1980 | 2066 | |||
| 1981 | Returns 0 on success. The only reported error condition is when | 2067 | Returns 0 on success. The only reported error condition is when | |
| 1982 | !fs. However, if fs was not allocated by whio_epfs_alloc(), this | 2068 | !fs. However, if fs was not allocated by whio_epfs_alloc(), this | |
| 1983 | routine will effectively close it, but also _not_ deallocate it, | | | 2069 | routine will effectively close it, but will _not_ deallocate it, |
| 1984 | and will report success. | 2070 | and will report success. | |
| 1985 | */ | 2071 | */ | |
| 1986 | int whio_epfs_finalize( whio_epfs *fs ); | 2072 | int whio_epfs_finalize( whio_epfs *fs ); | |
| 1987 | 2073 | |||
| 1988 | /** Returns true only if fs is not null and is opened for | | | 2074 | /** Returns true only if fs is not null and is opened in |
| 1989 | read/write. */ | | | 2075 | read/write mode. |
| | | 2076 | */ | ||
| 1990 | bool whio_epfs_is_rw( whio_epfs const * const fs ); | 2077 | bool whio_epfs_is_rw( whio_epfs const * const fs ); | |
| 1991 | 2078 | |||
| 1992 | /** | 2079 | /** | |
| 1993 | If fs is opened for read/write then this flushes the storage | 2080 | If fs is opened for read/write then this flushes the storage | |
| 1994 | and returns a storage-dependent non-zero value on error. If fs | 2081 | and returns a storage-dependent non-zero value on error. If fs | |
| 1995 | is read-only then whio_rc.AccessError is returned. If !fs then | 2082 | is read-only then whio_rc.AccessError is returned. If !fs then | |
| 1996 | whio_rc.ArgError is returned. | 2083 | whio_rc.ArgError is returned. | |
| 1997 | 2084 | |||
| 1998 | This routine is used to ensure that any persistent fs-internal | | | 2085 | The difference between calling this and, say, the flush() |
| 1999 | metadata is flushed to storage. Do not call it too often, | | | 2086 | member of a device returned from whio_epfs_dev_open(), is that |
| 2000 | though, as it can be relatively slow. | | | 2087 | this flushes the underlying storage of the EFS container, |
| | | 2088 | whereas the latter only ensures that the current inode state is | ||
| | | 2089 | written to that storage (but not necessarily flushed). | ||
| | | 2090 | |||
| | | 2091 | Do not call it too often, as it can be relatively slow. | ||
| | | 2092 | |||
| | | 2093 | It is not normally necessary for client code to call this, | ||
| | | 2094 | but internals which muck with persistent | ||
| 2001 | 2095 | |||
| 2002 | Returns 0 on success. | 2096 | Returns 0 on success. | |
| 2003 | */ | 2097 | */ | |
| 2004 | int whio_epfs_flush( whio_epfs * fs ); | 2098 | int whio_epfs_flush( whio_epfs * fs ); | |
| 2005 | 2099 | |||
| 11 hidden lines | ||||
| 2017 | whio_epfs_id_t whio_epfs_block_count( whio_epfs const * fs ); | 2111 | whio_epfs_id_t whio_epfs_block_count( whio_epfs const * fs ); | |
| 2018 | 2112 | |||
| 2019 | /** | 2113 | /** | |
| 2020 | Opens the given inode for random access with the given | 2114 | Opens the given inode for random access with the given | |
| 2021 | read/write mode. If inodeID is 0 then mode must include | 2115 | read/write mode. If inodeID is 0 then mode must include | |
| 2022 | WHIO_EPFS_MODE_FLAG_CREATE, and the next available (free/unused) | | | 2116 | WHIO_EPFS_MODE_FLAG_CREATE and the next available (free/unused) |
| 2023 | inode will be opened for read/write access. | 2117 | inode will be opened for read/write access. | |
| 2024 | 2118 | |||
| 2025 | dev must be non-null and *dev must either point to null or | 2119 | dev must be non-null and *dev must either point to null or | |
| 2026 | an empty-initialized objects. On success, the created whio_dev object will | 2120 | an empty-initialized objects. On success, the created whio_dev object will | |
| 2027 | be stored there. It must be closed or finalized as described in | 2121 | be stored there. It must be closed or finalized as described in | |
| 17 hidden lines | ||||
| 2045 | "create" because of its logical similarity to the O_CREAT flag | 2139 | "create" because of its logical similarity to the O_CREAT flag | |
| 2046 | for the open(2) system call. In this mode, if id==0 and no | 2140 | for the open(2) system call. In this mode, if id==0 and no | |
| 2047 | unused inodes are found then this function will fail | 2141 | unused inodes are found then this function will fail | |
| 2048 | with whio_rc.DeviceFullError. | 2142 | with whio_rc.DeviceFullError. | |
| 2049 | 2143 | |||
| 2050 | - The WHIO_EPFS_MODE_FLAG_RWC flag is equivalent to | | | 2144 | - The WHIO_EPFS_MODE_RWC flag is equivalent to |
| 2051 | (WHIO_EPFS_MODE_FLAG_RW | WHIO_EPFS_MODE_FLAG_CREATE). | | | 2145 | (WHIO_EPFS_MODE_RW | WHIO_EPFS_MODE_FLAG_CREATE). |
| 2052 | 2146 | |||
| 2053 | - WHIO_EPFS_MODE_FLAG_TRUNCATE can be OR'd together with | 2147 | - WHIO_EPFS_MODE_FLAG_TRUNCATE can be OR'd together with | |
| 2054 | WHIO_EPFS_MODE_WRITE to signify that the device should be | 2148 | WHIO_EPFS_MODE_WRITE to signify that the device should be | |
| 2055 | truncated to 0 bytes after it is opened. Under very tight | 2149 | truncated to 0 bytes after it is opened. Under very tight | |
| 2056 | memory conditions truncation can actually fail (because it must | 2150 | memory conditions truncation can actually fail (because it must | |
| 34 hidden lines | ||||
| 2091 | allocation method). | 2185 | allocation method). | |
| 2092 | 2186 | |||
| 2093 | Closing/finalizing dev after fs is closed will lead to | 2187 | Closing/finalizing dev after fs is closed will lead to | |
| 2094 | undefined behaviour. | 2188 | undefined behaviour. | |
| 2095 | 2189 | |||
| > | 2190 | Example: | ||
| > | 2191 | |||
| > | 2192 | @code | ||
| > | 2193 | whio_dev * d = NULL | ||
| > | 2194 | int rc = whio_epfs_dev_open( myfs, &d, 0, WHIO_EPFS_MODE_RWC ); | ||
| > | 2195 | if( rc ) { ... error ... } | ||
| > | 2196 | else { | ||
| > | 2197 | whio_epfs_id_t id = whio_epfs_dev_inode_id(d); | ||
| > | 2198 | // ... use device, then destroy it ... | ||
| > | 2199 | d->api->finalize(d); | ||
| > | 2200 | } | ||
| > | 2201 | @endcode | ||
| > | 2202 | |||
| 2096 | whio_dev interface notes: | 2203 | whio_dev interface notes: | |
| 2097 | 2204 | |||
| 2098 | Peculiarities of the returned whio_dev device vis-a-vis the | 2205 | Peculiarities of the returned whio_dev device vis-a-vis the | |
| 2099 | whio_dev standard interface: | 2206 | whio_dev standard interface: | |
| 2100 | 2207 | |||
| 14 hidden lines | ||||
| 2115 | fetch it.) | 2222 | fetch it.) | |
| 2116 | 2223 | |||
| 2117 | - Calling whio_dev_ioctl(dev,...) with a second argument of | 2224 | - Calling whio_dev_ioctl(dev,...) with a second argument of | |
| 2118 | whio_epfs_ioctl_INODE_PTR and a third argument of type | 2225 | whio_epfs_ioctl_INODE_PTR and a third argument of type | |
| 2119 | (whio_epfs_inode**) will set the 3rd argument to the pointer | 2226 | (whio_epfs_inode**) will set the 3rd argument to the pointer | |
| 2120 | to the inode associated with the device. (Or use | | | 2227 | to the inode associated with the device. (Or use whio_epfs_dev_inode() |
| | | 2228 | to fetch it.) | ||
| 2121 | 2229 | |||
| 2122 | - Calling whio_dev_ioctl(dev,...) with a second argument of | 2230 | - Calling whio_dev_ioctl(dev,...) with a second argument of | |
| 2123 | whio_epfs_ioctl_HANDLE_PTR and a third argument of type | 2231 | whio_epfs_ioctl_HANDLE_PTR and a third argument of type | |
| 2124 | (whio_epfs_HANDLE**) will set the 3rd argument to the pointer | 2232 | (whio_epfs_HANDLE**) will set the 3rd argument to the pointer | |
| 2125 | to the handle associated with the device. NOTE that handle->inode | | | 2233 | to the handle associated with the device. NOTE that |
| 2126 | might not be the real inode entry used by the handle (this | | | 2234 | handle->inode might not be the real inode entry used by the |
| 2127 | happens when a handle is opened multiple times), and thus the | | | 2235 | handle (this happens when a handle is opened multiple times), |
| 2128 | whio_epfs_ioctl_INODE_PTR ioctl should be used to fetch the | | | 2236 | and thus the whio_epfs_dev_inode() should be used to fetch the |
| 2129 | inode, instead of using handle->inode directly. | | | 2237 | inode, if needed, instead of using handle->inode directly. |
| 2130 | 2238 | |||
| 2131 | - The dev->client member is not used by this API, and can be | 2239 | - The dev->client member is not used by this API, and can be | |
| 2132 | used by the client as described in the documentation for | 2240 | used by the client as described in the documentation for | |
| 2133 | whio_dev::client. | 2241 | whio_dev::client. | |
| 2134 | 2242 | |||
| 2135 | OPENING AN INODE MULTIPLE TIMES: | | | 2243 | Having said all of that about getting a pointer to the device's |
| | | 2244 | internal inode and handle data... don't do it unless you are | ||
| | | 2245 | writing a tool for use with this library and you are aware that | ||
| | | 2246 | any incorrect fiddling of the inode/handle objects can corrupt | ||
| | | 2247 | the EFS, leak memory, or otherwise cause Undefined Behaviour. | ||
| | | 2248 | |||
| | | 2249 | |||
| | | 2250 | Opening an inode multiple times: | ||
| 2136 | 2251 | |||
| 2137 | If a given inode is opened multiple times, all opened | 2252 | If a given inode is opened multiple times, all opened | |
| 2138 | references to it share the same underlying inode object and | 2253 | references to it share the same underlying inode object and | |
| 2139 | block chain but each has their own logical file position cursor | 2254 | block chain but each has their own logical file position cursor | |
| 2140 | and access mode. Thus when updating a given inode, read-only | 2255 | and access mode. Thus when updating a given inode, read-only | |
| 9 hidden lines | ||||
| 2150 | closed. This is required so that the inode instance which is | 2265 | closed. This is required so that the inode instance which is | |
| 2151 | shared amongst linked handles does not change memory locations | 2266 | shared amongst linked handles does not change memory locations | |
| 2152 | at runtime (which would invalidate pointers to it). | 2267 | at runtime (which would invalidate pointers to it). | |
| 2153 | 2268 | |||
| 2154 | By the way, no inode can be opened more than | 2269 | By the way, no inode can be opened more than | |
| 2155 | (2^(sizeof(whio_epfs_handle::openCount))) times | | | 2270 | (2^(8*sizeof(whio_epfs_handle::openCount))) times |
| 2156 | concurrently. Trying to open it more times than that will fail | 2271 | concurrently. Trying to open it more times than that will fail | |
| 2157 | with error code whio_rc.RangeError. | 2272 | with error code whio_rc.RangeError. | |
| 2158 | 2273 | |||
| 2159 | MISFEATURES: | | | 2274 | Misfeatures: |
| 2160 | 2275 | |||
| 2161 | - If *dev is closed after fs is closed, there is a potential | 2276 | - If *dev is closed after fs is closed, there is a potential | |
| 2162 | crash condition. Fixing this is on the TODO list but requires | 2277 | crash condition. Fixing this is on the TODO list but requires | |
| 2163 | more infrastructure in the whio_epfs class to maintain the | 2278 | more infrastructure in the whio_epfs class to maintain the | |
| 2164 | object links. | | | 2279 | object links. In any case, closing the device after fs is |
| | | 2280 | closed is in Direct Violation of the API documentation, so i'm | ||
| | | 2281 | in no hurry to add that infrastructure :). (That said, in | ||
| | | 2282 | script-engine binding cases lifetimes can prove more | ||
| | | 2283 | problematic, so this will likely eventually be fixed.) | ||
| 2165 | */ | 2284 | */ | |
| 2166 | int whio_epfs_dev_open( whio_epfs * fs, whio_dev ** dev, whio_epfs_id_t inodeID, enum whio_epfs_iomodes mode ); | 2285 | int whio_epfs_dev_open( whio_epfs * fs, whio_dev ** dev, whio_epfs_id_t inodeID, enum whio_epfs_iomodes mode ); | |
| 2167 | 2286 | |||
| 2168 | /** | 2287 | /** | |
| 2169 | If d was initialized via whio_epfs_dev_open() then its associated | 2288 | If d was initialized via whio_epfs_dev_open() then its associated | |
| 10 hidden lines | ||||
| 2180 | If dev was initialized for read/write access via | 2299 | If dev was initialized for read/write access via | |
| 2181 | whio_epfs_open_dev() then its associated inode is returned. In | 2300 | whio_epfs_open_dev() then its associated inode is returned. In | |
| 2182 | any other case, NULL is returned. | 2301 | any other case, NULL is returned. | |
| 2183 | 2302 | |||
| 2184 | It is up to the caller to behave responsibly with the inode's | 2303 | It is up to the caller to behave responsibly with the inode's | |
| 2185 | data. Changing certain fields (especially | | | 2304 | data. Changing certain fields (especially whio_epfs_inode::size |
| 2186 | whio_epfs_inode::firstBlock) could lead to data loss or EFS | | | 2305 | or whio_epfs_inode::firstBlock) could lead to data loss or EFS |
| 2187 | corruption. | 2306 | corruption. | |
| 2188 | 2307 | |||
| 2189 | The returned inode is owned by the containing EPFS engine, and | 2308 | The returned inode is owned by the containing EPFS engine, and | |
| 2190 | must not be deallocated nor dereferenced after dev has been | 2309 | must not be deallocated nor dereferenced after dev has been | |
| 2191 | closed. | 2310 | closed. | |
| 354 hidden lines | ||||
| 2546 | #ifdef __cplusplus | 2665 | #ifdef __cplusplus | |
| 2547 | } /* extern "C" */ | 2666 | } /* extern "C" */ | |
| 2548 | #endif | 2667 | #endif | |
| 2549 | 2668 | |||
| 2550 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_H_INCLUDED */ | 2669 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_H_INCLUDED */ | |
Changes to include/wh/whio/whio_epfs_config.h
| Old (45c31476abd10faa) | New (35a2cdeb0af140f5) | |||
|---|---|---|---|---|
| 1 | #ifndef WANDERINGHORSE_NET_WHIO_EPFS_CONFIG_H_INCLUDED | 1 | #ifndef WANDERINGHORSE_NET_WHIO_EPFS_CONFIG_H_INCLUDED | |
| 2 | #define WANDERINGHORSE_NET_WHIO_EPFS_CONFIG_H_INCLUDED | 2 | #define WANDERINGHORSE_NET_WHIO_EPFS_CONFIG_H_INCLUDED | |
| 3 | /** @file whio_epfs_config.h | 3 | /** @file whio_epfs_config.h | |
| 4 | 4 | |||
| 5 | This file contains the compile-time-configurable parts of whio_epfs. | 5 | This file contains the compile-time-configurable parts of whio_epfs. | |
| 143 hidden lines | ||||
| 149 | 149 | |||
| 150 | @see to WHIO_EPFS_ID_T_PFMT | 150 | @see to WHIO_EPFS_ID_T_PFMT | |
| 151 | @see to WHIO_EPFS_ID_T_SFMT | 151 | @see to WHIO_EPFS_ID_T_SFMT | |
| 152 | */ | 152 | */ | |
| 153 | 153 | |||
| > | 154 | /** @typedef SOME_UNSIGNED_INTEGER_TYPE whio_epfs_id_t | ||
| > | 155 | |||
| > | 156 | whio_epfs_id_t is a fixed-sized unsigned integer type | ||
| > | 157 | whose size is WHIO_EPFS_ID_T_BITS/8 bytes. | ||
| > | 158 | */ | ||
| 154 | #if WHIO_EPFS_ID_T_BITS == 8 | 159 | #if WHIO_EPFS_ID_T_BITS == 8 | |
| 155 | /* | 160 | /* | |
| 156 | For very, very limited filesystems. There's lots of room for | 161 | For very, very limited filesystems. There's lots of room for | |
| 157 | overflows here! Completely untested! | 162 | overflows here! Completely untested! | |
| 158 | */ | 163 | */ | |
| 32 hidden lines | ||||
| 191 | #ifdef __cplusplus | 196 | #ifdef __cplusplus | |
| 192 | } /* extern "C" */ | 197 | } /* extern "C" */ | |
| 193 | #endif | 198 | #endif | |
| 194 | 199 | |||
| 195 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_CONFIG_H_INCLUDED */ | 200 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_CONFIG_H_INCLUDED */ | |
Changes to pfs/handle.c
| Old (3ea415da23ddacdc) | New (b2007569278a8d76) | |||
|---|---|---|---|---|
| 1 | //#define WHIO_DEBUG_ENABLED 1 | 1 | //#define WHIO_DEBUG_ENABLED 1 | |
| 2 | #include "whio_epfs_internal.h" | 2 | #include "whio_epfs_internal.h" | |
| 3 | #include <stdlib.h> // malloc() and friends. | 3 | #include <stdlib.h> // malloc() and friends. | |
| 4 | #include <string.h> // memmove() and friends | 4 | #include <string.h> // memmove() and friends | |
| 5 | #include <assert.h> | 5 | #include <assert.h> | |
| 284 hidden lines | ||||
| 290 | { /* fs is r/o but caller asked for r/w. */ | 290 | { /* fs is r/o but caller asked for r/w. */ | |
| 291 | return whio_rc.AccessError; | 291 | return whio_rc.AccessError; | |
| 292 | } | 292 | } | |
| 293 | whio_epfs_inode oni = whio_epfs_inode_empty; | 293 | whio_epfs_inode oni = whio_epfs_inode_empty; | |
| 294 | int rc = 0; | 294 | int rc = 0; | |
| 295 | whio_epfs_handle * h = 0; | | | 295 | whio_epfs_handle * h = NULL; |
| 296 | whio_epfs_handle * origin = 0; | | | 296 | whio_epfs_handle * origin = NULL; |
| 297 | whio_epfs_id_t i = 0; | 297 | whio_epfs_id_t i = 0; | |
| 298 | if(id) for( ; i < fs->handles.count; ++i ) | 298 | if(id) for( ; i < fs->handles.count; ++i ) | |
| 299 | { // FIXME: keep list sorted on inode id to make this faster. | 299 | { // FIXME: keep list sorted on inode id to make this faster. | |
| 300 | h = fs->handles.list[i]; | 300 | h = fs->handles.list[i]; | |
| 301 | #if 0 | 301 | #if 0 | |
| 102 hidden lines | ||||
| 404 | ? whio_epfs_inode_empty /* we don't want that inode to ever be used. */ | 404 | ? whio_epfs_inode_empty /* we don't want that inode to ever be used. */ | |
| 405 | : oni; | 405 | : oni; | |
| 406 | h->pfs = fs; | 406 | h->pfs = fs; | |
| 407 | whio_epfs_handle_list_append( &fs->handles, h ); | 407 | whio_epfs_handle_list_append( &fs->handles, h ); | |
| 408 | if( ownsHandle ) *tgt = h; | 408 | if( ownsHandle ) *tgt = h; | |
| > | 409 | #if 0 | ||
| > | 410 | whio_epfs_flush( fs ) | ||
| > | 411 | /*Ensure recent free-list changes are written, but adds a | ||
| > | 412 | noticable about to runtime to some uses cases (just over 30% | ||
| > | 413 | in my quick tests). | ||
| > | 414 | */ | ||
| > | 415 | ; | ||
| > | 416 | #endif | ||
| 409 | return whio_rc.OK; | 417 | return whio_rc.OK; | |
| 410 | } | 418 | } | |
| 411 | 419 | |||
| 412 | int whio_epfs_handle_close( whio_epfs_handle * h ) | 420 | int whio_epfs_handle_close( whio_epfs_handle * h ) | |
| 413 | { | 421 | { | |
| 29 hidden lines | ||||
| 443 | if( ! h->openCount ) | 451 | if( ! h->openCount ) | |
| 444 | { | 452 | { | |
| 445 | #if XXX | 453 | #if XXX | |
| 446 | WHIO_DEBUG("Freeing handle #%"WHIO_EPFS_ID_T_PFMT" @%p\n", origin->inode.id, (void const *)h ); | 454 | WHIO_DEBUG("Freeing handle #%"WHIO_EPFS_ID_T_PFMT" @%p\n", origin->inode.id, (void const *)h ); | |
| 447 | #endif | 455 | #endif | |
| 448 | whio_epfs_handle_search( &h->pfs->handles, h, true ); | | | 456 | //whio_epfs * fs = origin->pfs; |
| | | 457 | whio_epfs_handle_search( &origin->pfs->handles, h, true ); | ||
| 449 | whio_epfs_handle_free(h); | 458 | whio_epfs_handle_free(h); | |
| > | 459 | #if 0 | ||
| > | 460 | whio_epfs_flush( fs ) /* ensure recent free-list changes are written.*/; | ||
| > | 461 | #endif | ||
| 450 | rc = whio_rc.OK; | 462 | rc = whio_rc.OK; | |
| 451 | } | 463 | } | |
| 452 | if( (origin != h) ) | 464 | if( (origin != h) ) | |
| 453 | { | 465 | { | |
| 454 | { | 466 | { | |
| 6 hidden lines | ||||
| 461 | #undef XXX | 473 | #undef XXX | |
| 462 | return rc; | 474 | return rc; | |
| 463 | } | 475 | } | |
| 464 | 476 | |||
| 465 | #undef TRY_SORTED_HANDLE_LIST | 477 | #undef TRY_SORTED_HANDLE_LIST | |
Changes to pfs/inode.c
| Old (0032a6a00366197d) | New (307b61ef63d19816) | |||
|---|---|---|---|---|
| 1 | /************************************************************************ | 1 | /************************************************************************ | |
| 2 | This file contains most of the inode-specific whio_epfs routines. | 2 | This file contains most of the inode-specific whio_epfs routines. | |
| 3 | 3 | |||
| 4 | Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) | 4 | Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) | |
| 5 | 5 | |||
| 274 hidden lines | ||||
| 280 | { | 280 | { | |
| 281 | fs->hints.freeInodeList = ino.nextFree; | 281 | fs->hints.freeInodeList = ino.nextFree; | |
| 282 | } | 282 | } | |
| 283 | id = ino.nextFree; | 283 | id = ino.nextFree; | |
| 284 | continue; | 284 | continue; | |
| > | 285 | } | ||
| > | 286 | else | ||
| > | 287 | { | ||
| > | 288 | return whio_rc.ConsistencyError/*???*/; | ||
| 285 | } | 289 | } | |
| 286 | } | 290 | } | |
| 287 | break; | 291 | break; | |
| 288 | } | 292 | } | |
| 289 | if( ! id ) | 293 | if( ! id ) | |
| 242 hidden lines | ||||
| 532 | } | 536 | } | |
| 533 | return rc; | 537 | return rc; | |
| 534 | } | 538 | } | |
| 535 | 539 | |||
| 536 | #undef MARKER | 540 | #undef MARKER | |
Changes to pfs/ls.c
| Old (c9e8d146738a5388) | New (3108401899ca70b3) | |||
|---|---|---|---|---|
| 1 | /************************************************************************ | 1 | /************************************************************************ | |
| 2 | An "ls"-like program for use with whio_epfs. | 2 | An "ls"-like program for use with whio_epfs. | |
| 3 | 3 | |||
| 4 | Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) | 4 | Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) | |
| 5 | 5 | |||
| 89 hidden lines | ||||
| 95 | 0U /*blockCount*/, | 95 | 0U /*blockCount*/, | |
| 96 | 0U /*inodeCount*/ | 96 | 0U /*inodeCount*/ | |
| 97 | }; | 97 | }; | |
| 98 | 98 | |||
| 99 | /** | 99 | /** | |
| 100 | Appends f to AppLs.funcs. | | | 100 | Appends f to AppLs.funcs. exit()s on error (called |
| | | 101 | AppLs_MAX_COMMANDS times). | ||
| 101 | */ | 102 | */ | |
| 102 | static int AppLs_push_command( ls_command_f f ) | 103 | static int AppLs_push_command( ls_command_f f ) | |
| 103 | { | 104 | { | |
| 104 | assert( AppLs.funcs.count < AppLs_MAX_COMMANDS ); | | | 105 | if( AppLs.funcs.count >= AppLs_MAX_COMMANDS ) |
| | | 106 | { | ||
| | | 107 | APPERR("Internal range error: too many (%u) operations!\n",(unsigned int) AppLs.funcs.count); | ||
| | | 108 | exit(whio_rc.InternalError); | ||
| | | 109 | } | ||
| 105 | AppLs.funcs.f[AppLs.funcs.count++] = f; | 110 | AppLs.funcs.f[AppLs.funcs.count++] = f; | |
| 106 | return 0; | 111 | return 0; | |
| 107 | } | 112 | } | |
| 108 | 113 | |||
| 109 | /** | 114 | /** | |
| 132 hidden lines | ||||
| 242 | int rc = whio_epfs_foreach_inode( EPFSApp.fs, NULL, NULL, inode_foreach_ls, &info ); | 247 | int rc = whio_epfs_foreach_inode( EPFSApp.fs, NULL, NULL, inode_foreach_ls, &info ); | |
| 243 | 248 | |||
| 244 | 249 | |||
| 245 | if( ! AppLs.oneMode ) | 250 | if( ! AppLs.oneMode ) | |
| 246 | { | 251 | { | |
| 247 | printf("\nTotal: %"WHIO_EPFS_ID_T_PFMT" of %"WHIO_EPFS_ID_T_PFMT" inodes take up " | | | 252 | printf("\nTotals: %"WHIO_EPFS_ID_T_PFMT" of %"WHIO_EPFS_ID_T_PFMT" inodes take up " |
| 248 | "%"WHIO_SIZE_T_PFMT" bytes", | 253 | "%"WHIO_SIZE_T_PFMT" bytes", | |
| 249 | info.inodeCount, o->inodeCount, | 254 | info.inodeCount, o->inodeCount, | |
| 250 | info.totalSize | 255 | info.totalSize | |
| 251 | ); | 256 | ); | |
| 252 | if( AppLs.showBlocks ) | 257 | if( AppLs.showBlocks ) | |
| 253 | { | 258 | { | |
| 254 | printf(" in %"WHIO_EPFS_ID_T_PFMT" blocks", | 259 | printf(" in %"WHIO_EPFS_ID_T_PFMT" blocks", | |
| 255 | info.blockCount ); | 260 | info.blockCount ); | |
| 256 | } | 261 | } | |
| 257 | puts("."); | | | 262 | puts(".\n"); |
| 258 | } | 263 | } | |
| 259 | 264 | |||
| 260 | if( rc ) | 265 | if( rc ) | |
| 261 | { | 266 | { | |
| 262 | APPERR("Got error code %d while looping over inodes!\n", rc ); | 267 | APPERR("Got error code %d while looping over inodes!\n", rc ); | |
| 15 hidden lines | ||||
| 278 | 283 | |||
| 279 | static int ls_dump_freelists_command() | 284 | static int ls_dump_freelists_command() | |
| 280 | { | 285 | { | |
| 281 | int rc = 0; | 286 | int rc = 0; | |
| 282 | int i = 0; | 287 | int i = 0; | |
| 283 | int span = 4; | | | 288 | const int span = 4; |
| 284 | { | 289 | { | |
| 285 | puts("Data block free-list: (Block ID->Next free ID)\n"); | | | 290 | puts("Data block free-list: (blockID->nextFreeBlock)\n"); |
| 286 | whio_epfs_id_t f = EPFSApp.fs->hints.freeBlockList; | 291 | whio_epfs_id_t f = EPFSApp.fs->hints.freeBlockList; | |
| 287 | if( !f ) | 292 | if( !f ) | |
| 288 | { | 293 | { | |
| 289 | puts("No explicit unused blocks."); | | | 294 | if( !EPFSApp.fs->fsopt.maxBlocks ) |
| | | 295 | { | ||
| | | 296 | puts("\tNo free blocks, but this EFS can grow on demand."); | ||
| | | 297 | } | ||
| | | 298 | else | ||
| | | 299 | { | ||
| | | 300 | puts("\tNo unused blocks - this EFS is full."); | ||
| | | 301 | } | ||
| 290 | } | 302 | } | |
| 291 | else | 303 | else | |
| 292 | { | 304 | { | |
| > | 305 | unsigned int count = 0; | ||
| 293 | putchar('\t'); | 306 | putchar('\t'); | |
| 294 | while( f ) | 307 | while( f ) | |
| 295 | { | 308 | { | |
| > | 309 | ++count; | ||
| 296 | whio_epfs_block bl = whio_epfs_block_empty; | 310 | whio_epfs_block bl = whio_epfs_block_empty; | |
| 297 | rc = whio_epfs_block_read( EPFSApp.fs, f, &bl ); | 311 | rc = whio_epfs_block_read( EPFSApp.fs, f, &bl ); | |
| 298 | if( rc ) | 312 | if( rc ) | |
| 299 | { | 313 | { | |
| 300 | APPERR("Error reading block #%"WHIO_EPFS_ID_T_PFMT"!\n",f); | 314 | APPERR("Error reading block #%"WHIO_EPFS_ID_T_PFMT"!\n",f); | |
| 9 hidden lines | ||||
| 310 | i = 0; | 324 | i = 0; | |
| 311 | printf("\n%s",(f ? "\t" : "")); | 325 | printf("\n%s",(f ? "\t" : "")); | |
| 312 | } | 326 | } | |
| 313 | else ++i; | 327 | else ++i; | |
| 314 | } | 328 | } | |
| > | 329 | printf("\n%s\t= %u unused blocks in free-list\n",(i?"\n":""),count); | ||
| 315 | } | 330 | } | |
| 316 | putchar('\n'); | < | ||
| 317 | } | 331 | } | |
| 318 | putchar('\n'); | 332 | putchar('\n'); | |
| 319 | { | 333 | { | |
| 320 | i = 0; | 334 | i = 0; | |
| 321 | puts("Inode free-list: (Previous Free<- Inode ID -> Next Free)\n"); | | | 335 | puts("Inode free-list: (previous<-current->next)\n"); |
| 322 | whio_epfs_id_t f = EPFSApp.fs->hints.freeInodeList; | 336 | whio_epfs_id_t f = EPFSApp.fs->hints.freeInodeList; | |
| 323 | if( !f ) | 337 | if( !f ) | |
| 324 | { | 338 | { | |
| 325 | puts("No explicit unused inodes."); | | | 339 | puts("\tNo free inodes."); |
| 326 | } | 340 | } | |
| 327 | else | 341 | else | |
| 328 | { | 342 | { | |
| > | 343 | unsigned int count = 0; | ||
| 329 | putchar('\t'); | 344 | putchar('\t'); | |
| 330 | while( f ) | 345 | while( f ) | |
| 331 | { | 346 | { | |
| > | 347 | ++count; | ||
| 332 | whio_epfs_inode ino = whio_epfs_inode_empty; | 348 | whio_epfs_inode ino = whio_epfs_inode_empty; | |
| 333 | rc = whio_epfs_inode_read( EPFSApp.fs, f, &ino ); | 349 | rc = whio_epfs_inode_read( EPFSApp.fs, f, &ino ); | |
| 334 | if( rc ) | 350 | if( rc ) | |
| 335 | { | 351 | { | |
| 336 | APPERR("Error reading inode #%"WHIO_EPFS_ID_T_PFMT"!\n",f); | 352 | APPERR("Error reading inode #%"WHIO_EPFS_ID_T_PFMT"!\n",f); | |
| 9 hidden lines | ||||
| 346 | i = 0; | 362 | i = 0; | |
| 347 | printf("\n%s",(f ? "\t" : "")); | 363 | printf("\n%s",(f ? "\t" : "")); | |
| 348 | } | 364 | } | |
| 349 | else ++i; | 365 | else ++i; | |
| 350 | } | 366 | } | |
| > | 367 | printf("\n%s\t= %u unused inodes in free-list\n",(i?"\n":""),count); | ||
| 351 | } | 368 | } | |
| 352 | putchar('\n'); | 369 | putchar('\n'); | |
| 353 | } | 370 | } | |
| 354 | putchar('\n'); | 371 | putchar('\n'); | |
| 355 | return 0; | 372 | return 0; | |
| 161 hidden lines | ||||
| 517 | } | 534 | } | |
| 518 | } | 535 | } | |
| 519 | EPFSApp_verbose_error_code( rc ); | 536 | EPFSApp_verbose_error_code( rc ); | |
| 520 | return rc; | 537 | return rc; | |
| 521 | } | 538 | } | |
Changes to pfs/pfs.c
| Old (17e2c59903607ab5) | New (4cc13ad50e092b5c) | |||
|---|---|---|---|---|
| 1 | /************************************************************************ | 1 | /************************************************************************ | |
| 2 | This is a work-in-progress, porting over parts of the whefs API into | 2 | This is a work-in-progress, porting over parts of the whefs API into | |
| 3 | the whio API... | 3 | the whio API... | |
| 4 | 4 | |||
| 5 | Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) | 5 | Author: Stephan Beal (http://wanderinghorse.net/home/stephan/) | |
| 56 hidden lines | ||||
| 62 | if(!fs || !fs->dev ) return whio_rc.ArgError; | 62 | if(!fs || !fs->dev ) return whio_rc.ArgError; | |
| 63 | else if( !whio_epfs_is_rw(fs) ) return whio_rc.AccessError; | 63 | else if( !whio_epfs_is_rw(fs) ) return whio_rc.AccessError; | |
| 64 | else | 64 | else | |
| 65 | { | 65 | { | |
| 66 | /* FIXME? put this somewhere else? */ | 66 | /* FIXME? put this somewhere else? */ | |
| 67 | int rc = whio_epfs_hints_write(fs); | | | 67 | int rc = |
| | | 68 | #if 1 | ||
| | | 69 | 0 | ||
| | | 70 | #else | ||
| | | 71 | whio_epfs_hints_write(fs) | ||
| | | 72 | #endif | ||
| | | 73 | ; | ||
| 68 | if(! rc ) | 74 | if(! rc ) | |
| 69 | { | 75 | { | |
| 70 | rc = fs->dev->api->flush( fs->dev ); | 76 | rc = fs->dev->api->flush( fs->dev ); | |
| 71 | } | 77 | } | |
| 72 | return rc; | 78 | return rc; | |
| 157 hidden lines | ||||
| 230 | int whio_epfs_close( whio_epfs *fs ) | 236 | int whio_epfs_close( whio_epfs *fs ) | |
| 231 | { | 237 | { | |
| 232 | if( !fs ) return whio_rc.ArgError; | 238 | if( !fs ) return whio_rc.ArgError; | |
| 233 | if( !fs->err && fs->dev && whio_epfs_is_rw(fs) ) | 239 | if( !fs->err && fs->dev && whio_epfs_is_rw(fs) ) | |
| 234 | { | 240 | { | |
| > | 241 | whio_epfs_hints_write(fs); | ||
| 235 | whio_epfs_flush(fs); | 242 | whio_epfs_flush(fs); | |
| 236 | } | 243 | } | |
| 237 | if( fs->client.dtor ) | 244 | if( fs->client.dtor ) | |
| 238 | { | 245 | { | |
| 239 | /** | 246 | /** | |
| 432 hidden lines | ||||
| 672 | rc = whio_epfs_inode_flush( fs, &ino ); | 679 | rc = whio_epfs_inode_flush( fs, &ino ); | |
| 673 | } | 680 | } | |
| 674 | return rc; | 681 | return rc; | |
| 675 | } | 682 | } | |
| 676 | 683 | |||
| 677 | /** | | | 684 | /** @internal |
| 678 | Internal code-duplication remover. It assumes fs is fully (but just | 685 | Internal code-duplication remover. It assumes fs is fully (but just | |
| 679 | recently) initialized, and that sopt is properly set up. It also | 686 | recently) initialized, and that sopt is properly set up. It also | |
| 680 | assumes that initialization of fs is at its end phase, and the fs | 687 | assumes that initialization of fs is at its end phase, and the fs | |
| 681 | object has already suceeded through initialization except for these | | | 688 | object has already succeeded through initialization except for these |
| 682 | house-keeping bits. | 689 | house-keeping bits. | |
| 683 | 690 | |||
| 684 | If sopt->memory.mem is not null then whio_epfs_mempool_setup() is | 691 | If sopt->memory.mem is not null then whio_epfs_mempool_setup() is | |
| 685 | called and on success sopt->memory.mem is set to NULL. If mempool | 692 | called and on success sopt->memory.mem is set to NULL. If mempool | |
| 686 | initialization fails, that error code is returned from this | 693 | initialization fails, that error code is returned from this | |
| 687 | function. | 694 | function. | |
| 688 | 695 | |||
| 689 | If sopt->storage.takeDevOnSuccess is true then fs has its owns-the-device flag | | | 696 | If sopt->storage.takeDevOnSuccess is true then fs has its |
| 690 | set and sopt->storage.dev is set to NULL. It is assumed that fs | | | 697 | owns-the-device flag set and sopt->storage.dev is set to NULL to |
| | | 698 | signify to the caller that ownership was taken. | ||
| 691 | 699 | |||
| 692 | Returns non-zero if any part of setup fails, but these parts are | 700 | Returns non-zero if any part of setup fails, but these parts are | |
| 693 | not considered critical, and should not cause init of the fs to | 701 | not considered critical, and should not cause init of the fs to | |
| 694 | fail (i.e., ignore the return code, and the client can check sopt's | 702 | fail (i.e., ignore the return code, and the client can check sopt's | |
| 695 | state if he NEEDs to know if certain part failed). | 703 | state if he NEEDs to know if certain part failed). | |
| 442 hidden lines | ||||
| 1138 | return rc; | 1146 | return rc; | |
| 1139 | } | 1147 | } | |
| 1140 | 1148 | |||
| 1141 | 1149 | |||
| 1142 | #undef MARKER | 1150 | #undef MARKER | |
Changes to pfs/whio_epfs_internal.h
| Old (59f4708000a3b808) | New (cca5cec5d5a97ed8) | |||
|---|---|---|---|---|
| 1 | #ifndef WANDERINGHORSE_NET_WHIO_EPFS_INTERNAL_H_INCLUDED | 1 | #ifndef WANDERINGHORSE_NET_WHIO_EPFS_INTERNAL_H_INCLUDED | |
| 2 | #define WANDERINGHORSE_NET_WHIO_EPFS_INTERNAL_H_INCLUDED | 2 | #define WANDERINGHORSE_NET_WHIO_EPFS_INTERNAL_H_INCLUDED | |
| 3 | 3 | |||
| 4 | /** @file whio_epfs_internal.h | 4 | /** @file whio_epfs_internal.h | |
| 5 | 5 | |||
| 131 hidden lines | ||||
| 137 | Tries to read the given inode ID from storage. On success 0 is | 137 | Tries to read the given inode ID from storage. On success 0 is | |
| 138 | returned and dest is populated with the fetched values. On | 138 | returned and dest is populated with the fetched values. On | |
| 139 | error dest is not modified. | 139 | error dest is not modified. | |
| 140 | */ | 140 | */ | |
| 141 | int whio_epfs_inode_read( whio_epfs * fs, | 141 | int whio_epfs_inode_read( whio_epfs * fs, | |
| 142 | whio_epfs_id_t id, | | | 142 | whio_epfs_id_t id, |
| 143 | whio_epfs_inode * dest ); | | | 143 | whio_epfs_inode * dest ); |
| 144 | 144 | |||
| 145 | /** @internal | 145 | /** @internal | |
| 146 | 146 | |||
| 147 | Returns the client data container object for fs. The client | 147 | Returns the client data container object for fs. The client | |
| 148 | may alter its contents (if he is certain what he is doing) but | 148 | may alter its contents (if he is certain what he is doing) but | |
| 11 hidden lines | ||||
| 160 | returned again on the next call to this function. | 160 | returned again on the next call to this function. | |
| 161 | 161 | |||
| 162 | Error conditions include: | 162 | Error conditions include: | |
| 163 | 163 | |||
| 164 | - !fs or !dest (whio_rc.ArgError). | 164 | - !fs or !dest (whio_rc.ArgError). | |
| > | 165 | |||
| 165 | - No more free inodes (whio_rc.DeviceFullError). | 166 | - No more free inodes (whio_rc.DeviceFullError). | |
| 166 | - Any potential errors via reading or writing the inode. | | | 167 | |
| 167 | - There's a whio_rc.RangeError for one theoretically impossible case.\ | | | 168 | - Any potential errors via reading or writing the inode and |
| 168 | - markAsUsed is true but fs is opened for read-only more: whio_rc.AccessError. | | | 169 | updating the free-inode list. |
| 169 | | | 170 | ||
| 170 | | | 171 | - markAsUsed is true but fs is opened for read-only more: | |
| 171 | As of 20100310, this is a essentially an O(1) operation if we | | | 172 | whio_rc.AccessError. |
| 172 | discount the i/o it must potentially do to update the inode | | | 173 | |
| 173 | free-list. If markAsUsed is true it must read, at most, 2 | | | 174 | As of 20100310, the actual search is an O(1) operation but |
| 174 | additional inodes, update their free-list links, and flush | | | 175 | there is (if markAsUsed is true) a small i/o overhead to |
| 175 | them. The ids (and therefore on-storage positions) of all | | | 176 | update the inode free-list. If markAsUsed is true it must |
| 176 | inodes involved are known in advance, so this routine has to | | | 177 | read, at most, 2 additional inodes, update their free-list |
| 177 | do no search-related i/o. Note that such re-linking pays no | | | 178 | links, and flush them. The ids (and therefore on-storage |
| 178 | attention whatsoever to whether an inode or its neighbors are | | | 179 | positions) of all inodes involved are known in advance, so |
| 179 | opened (and therefore have their inode state cached somewhere | | | 180 | this routine has to do no search-related i/o. Note that such |
| 180 | in memory). If the API is used properly then by the time an | | | 181 | re-linking pays no attention whatsoever to whether an inode or |
| 181 | inode can be opened, all links to/from the inode and the | | | 182 | its neighbors are opened (and therefore have their inode state |
| 182 | free-list are severed. | | | 183 | cached somewhere in memory!). If the API is used properly then |
| | | 184 | by the time an inode can be opened, all links to/from the | ||
| | | 185 | inode and the free-list are severed. | ||
| | | 186 | |||
| | | 187 | The down-side of the O(1) search guaranty is that if an i/o | ||
| | | 188 | error happens while updating the free-list links, it could | ||
| | | 189 | leave the free-list in an undefined state. That will either | ||
| | | 190 | lead to prematurely "running out" of inodes (when there are | ||
| | | 191 | actually some left) or to this routine taking longer to find | ||
| | | 192 | the next free inode (it double-checks to ensure that the | ||
| | | 193 | search led it to an unused inode). Or both. Probably both. | ||
| | | 194 | |||
| | | 195 | TODO: add the above-mentioned potential corruption case to the | ||
| | | 196 | future fsck-like functionality. We could theoretically rebuild | ||
| | | 197 | the free list from scratch by linearly scanning for | ||
| | | 198 | explicitly-marked used inodes. | ||
| 183 | */ | 199 | */ | |
| 184 | int whio_epfs_inode_next_free( whio_epfs * fs, whio_epfs_inode * dest, bool markAsUsed ); | 200 | int whio_epfs_inode_next_free( whio_epfs * fs, whio_epfs_inode * dest, bool markAsUsed ); | |
| 185 | 201 | |||
| 186 | /** @internal | 202 | /** @internal | |
| 187 | 203 | |||
| 865 hidden lines | ||||
| 1053 | #ifdef __cplusplus | 1069 | #ifdef __cplusplus | |
| 1054 | } /* extern "C" */ | 1070 | } /* extern "C" */ | |
| 1055 | #endif | 1071 | #endif | |
| 1056 | 1072 | |||
| 1057 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_INTERNAL_H_INCLUDED */ | 1073 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_INTERNAL_H_INCLUDED */ | |