Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| SHA1 Hash: | a0c8ed4b7dc5fa1d6fbe81917e96b26e1b8962f7 |
|---|---|
| Date: | 2010-03-10 16:43:06 |
| User: | stephan |
| Edited Comment: | woohoo! next-free-inode lookups are now O(1) (plus read/modify/write ops on up to two linked neighbors). The inode free-list had to be doubly-linked, whereas the block list is single-linked, because inodes can be opened by numeric ID (whereas blocks are doled out linearly) and that hoses a single-linked list. |
| Original Comment: | woohoo! next-free-inode lookups are not O(1) (plus read/modify/write ops on up to two linked neighbors). The inode free-list had to be doubly-linked, whereas the block list is single-linked, because inodes can be opened by numeric ID (whereas blocks are doled out linearly) and that hoses a single-linked list. |
Tags And Properties
- branch=trunk inherited from [c3e484d316]
- comment=woohoo! next-free-inode lookups are now O(1) (plus read/modify/write ops on up to two linked neighbors). The inode free-list had to be doubly-linked, whereas the block list is single-linked, because inodes can be opened by numeric ID (whereas blocks are doled out linearly) and that hoses a single-linked list. added by [ad6c0f4446] on 2010-03-11 00:43:28
- date=2010-03-10 16:43:06 added by [ad6c0f4446] on 2010-03-11 00:43:28
- sym-trunk inherited from [c3e484d316]
Changes
Changes to include/wh/whio/whio_epfs.h
| Old (532372e7a87a80d1) | New (bf853fe24bc90198) | |||
|---|---|---|---|---|
| 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. */ | |
| 35 hidden lines | ||||
| 41 | - Optimized for low memory usage: normal use cases need to allocate | 41 | - Optimized for low memory usage: normal use cases need to allocate | |
| 42 | less than 1k of dynamic memory at runtime. Clients may provide it with | 42 | less than 1k of dynamic memory at runtime. Clients may provide it with | |
| 43 | their own memory buffer, from which it will "allocate" any memory it | 43 | their own memory buffer, from which it will "allocate" any memory it | |
| 44 | needs. (See whio_epfs_mempool_setup().) | 44 | needs. (See whio_epfs_mempool_setup().) | |
| 45 | 45 | |||
| > | 46 | - As of 20100310, the last of the most performance-significant | ||
| > | 47 | algorithms (finding the next free block and inode) are O(1), plus a | ||
| > | 48 | possible extra write or two to re-link the free-list. The library | ||
| > | 49 | overall now performs quite well. | ||
| > | 50 | |||
| 46 | - Fairly well documented. | 51 | - Fairly well documented. | |
| 47 | 52 | |||
| 48 | - The EFS container file is endian/platform-neutral. Clients can store | 53 | - The EFS container file is endian/platform-neutral. Clients can store | |
| 49 | arbitrary binary data in pseudofiles, and that data may or may not be | 54 | arbitrary binary data in pseudofiles, and that data may or may not be | |
| 50 | endian/platform-dependent. | 55 | endian/platform-dependent. | |
| 30 hidden lines | ||||
| 81 | features can theoretically be added on top of it, however. | 86 | features can theoretically be added on top of it, however. | |
| 82 | 87 | |||
| 83 | - 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 | |
| 84 | shrunk. It needs a vaccuum-like feature. | 89 | shrunk. It needs a vaccuum-like feature. | |
| 85 | 90 | |||
| 86 | - Certain routines (e.g. finding the next free data block or | < | ||
| 87 | inode entry) are linear in nature, and may require a significant | < | ||
| 88 | amount of reading from storage. Internal optimizations cut this | < | ||
| 89 | down considerably (orders of magnitude) for the average cases, | < | ||
| 90 | but some use cases will perform poorly. | < | ||
| 91 | 91 | |||
| 92 | 92 | |||
| 93 | @section page_whio_epfs_main_whefs whio_epfs vs. whefs | 93 | @section page_whio_epfs_main_whefs whio_epfs vs. whefs | |
| 94 | 94 | |||
| 95 | whio_epfs is a spin-off/refactoring of the whefs project: | 95 | whio_epfs is a spin-off/refactoring of the whefs project: | |
| 461 hidden lines | ||||
| 557 | client use. | 557 | client use. | |
| 558 | */ | 558 | */ | |
| 559 | uint32_t cflags; | 559 | uint32_t cflags; | |
| 560 | 560 | |||
| 561 | /** | 561 | /** | |
| 562 | Used only be free inodes, to link to the next free inode. | | | 562 | Used only by free inodes, to link to the next free inode. |
| 563 | */ | 563 | */ | |
| 564 | whio_epfs_id_t nextFree; | 564 | whio_epfs_id_t nextFree; | |
| > | 565 | /** | ||
| > | 566 | Used only by free inodes, to link to the previous free inode. | ||
| > | 567 | |||
| > | 568 | inodes must be dual-linked, unlike blocks, because the ability | ||
| > | 569 | to open them directly by id confuses a single-link list and | ||
| > | 570 | can cause it to have cycles. | ||
| > | 571 | */ | ||
| > | 572 | whio_epfs_id_t prevFree; | ||
| 565 | }; | 573 | }; | |
| 566 | /** Convenience typedef. */ | 574 | /** Convenience typedef. */ | |
| 567 | typedef struct whio_epfs_inode whio_epfs_inode; | 575 | typedef struct whio_epfs_inode whio_epfs_inode; | |
| 568 | 576 | |||
| 569 | /** An empty whio_epfs_inode initialization object. */ | 577 | /** An empty whio_epfs_inode initialization object. */ | |
| 2 hidden lines | ||||
| 572 | 0/*firstBlock*/, \ | 580 | 0/*firstBlock*/, \ | |
| 573 | 0/*mtime*/, \ | 581 | 0/*mtime*/, \ | |
| 574 | 0/*size*/, \ | 582 | 0/*size*/, \ | |
| 575 | 0/*flags*/, \ | 583 | 0/*flags*/, \ | |
| 576 | 0/*cflags*/, \ | 584 | 0/*cflags*/, \ | |
| 577 | 0/*nextFree*/ \ | | | 585 | 0/*nextFree*/, \ |
| 578 | } | | | 586 | 0/*prevFree*/ \ |
| | | 587 | } | ||
| 579 | /** An empty whio_epfs_inode initialization object. */ | 588 | /** An empty whio_epfs_inode initialization object. */ | |
| 580 | extern const whio_epfs_inode whio_epfs_inode_empty; | 589 | extern const whio_epfs_inode whio_epfs_inode_empty; | |
| 581 | 590 | |||
| 582 | /** | 591 | /** | |
| 583 | Container for managing an on-storage chain of whio_epfs_block | 592 | Container for managing an on-storage chain of whio_epfs_block | |
| 291 hidden lines | ||||
| 875 | , | 884 | , | |
| 876 | /** | 885 | /** | |
| 877 | Encoded size of whio_epfs_hints. | 886 | Encoded size of whio_epfs_hints. | |
| 878 | */ | 887 | */ | |
| 879 | whio_epfs_sizeof_hints = 1/*tag byte*/ | 888 | whio_epfs_sizeof_hints = 1/*tag byte*/ | |
| 880 | + (5 * whio_epfs_sizeof_id) /* whio_epfs_hints:: | | | 889 | + (5 * whio_epfs_sizeof_id) /* whio_epfs::whio_epfs_hints::( |
| 881 | nextFreeInode, | | | ||
| 882 | maxEverUsedInode, | 890 | maxEverUsedInode, | |
| > | 891 | freeInodeList, | ||
| 883 | freeBlockList, | 892 | freeBlockList, | |
| 884 | maxEverUsedBlock, | 893 | maxEverUsedBlock, | |
| 885 | blockCount) */ | 894 | blockCount) */ | |
| 886 | , | 895 | , | |
| 887 | /** | 896 | /** | |
| 888 | Encoded size of whio_epfs_inode. | 897 | Encoded size of whio_epfs_inode. | |
| 889 | */ | 898 | */ | |
| 890 | whio_epfs_sizeof_inode = 1/*tag byte*/ | 899 | whio_epfs_sizeof_inode = 1/*tag byte*/ | |
| 891 | + whio_epfs_sizeof_id/*id*/ | 900 | + whio_epfs_sizeof_id/*id*/ | |
| 892 | + whio_sizeof_encoded_uint32/*cflags*/ | < | ||
| 893 | + whio_sizeof_encoded_uint8/*flags*/ | 901 | + whio_sizeof_encoded_uint8/*flags*/ | |
| 894 | + whio_sizeof_encoded_uint32/*mtime*/ | | | 902 | + whio_epfs_sizeof_id/*nextFree*/ |
| | | 903 | + whio_epfs_sizeof_id/*prevFree*/ | ||
| 895 | + whio_epfs_sizeof_id/*firstBlock*/ | 904 | + whio_epfs_sizeof_id/*firstBlock*/ | |
| > | 905 | + whio_sizeof_encoded_uint32/*cflags*/ | ||
| 896 | + whio_sizeof_encoded_size_t/*size*/ | 906 | + whio_sizeof_encoded_size_t/*size*/ | |
| 897 | + whio_epfs_sizeof_id/*nextFree*/ | | | 907 | + whio_sizeof_encoded_uint32/*mtime*/ |
| 898 | , | 908 | , | |
| 899 | /** | 909 | /** | |
| 900 | Encoded size of whio_epfs_block. This is independent of | 910 | Encoded size of whio_epfs_block. This is independent of | |
| 901 | whio_epfs_fsopt::blockSize. | 911 | whio_epfs_fsopt::blockSize. | |
| 902 | */ | 912 | */ | |
| 291 hidden lines | ||||
| 1194 | by client code. Some of these are persistant (stored | 1204 | by client code. Some of these are persistant (stored | |
| 1195 | in an EFS container), some are transient. | 1205 | in an EFS container), some are transient. | |
| 1196 | */ | 1206 | */ | |
| 1197 | struct whio_epfs_hints | 1207 | struct whio_epfs_hints | |
| 1198 | { | 1208 | { | |
| 1199 | /** | < | ||
| 1200 | Starting point when looking for the next free inode. | < | ||
| 1201 | */ | < | ||
| 1202 | whio_epfs_id_t nextFreeInode; | < | ||
| 1203 | 1209 | |||
| 1204 | /** | 1210 | /** | |
| 1205 | This stores the highest used inode ID. This is simply | 1211 | This stores the highest used inode ID. This is simply | |
| 1206 | a slight performance optimization so that we can abort | 1212 | a slight performance optimization so that we can abort | |
| 1207 | certain read-the-next-inode loops earlier than we | 1213 | certain read-the-next-inode loops earlier than we | |
| 1208 | normally would. | 1214 | normally would. | |
| 1209 | */ | 1215 | */ | |
| 1210 | whio_epfs_id_t maxEverUsedInode; | 1216 | whio_epfs_id_t maxEverUsedInode; | |
| > | 1217 | /** | ||
| > | 1218 | ID of the first free block, or 0 if there are none. | ||
| > | 1219 | */ | ||
| > | 1220 | whio_epfs_id_t freeInodeList; | ||
| 1211 | 1221 | |||
| 1212 | /** | 1222 | /** | |
| 1213 | ID of the first free block, or 0 if there are none. | 1223 | ID of the first free block, or 0 if there are none. | |
| 1214 | */ | 1224 | */ | |
| 1215 | whio_epfs_id_t freeBlockList; | 1225 | whio_epfs_id_t freeBlockList; | |
| 66 hidden lines | ||||
| 1282 | 0/*err*/, \ | 1292 | 0/*err*/, \ | |
| 1283 | {/*offsets*/0}, \ | 1293 | {/*offsets*/0}, \ | |
| 1284 | {/*sizes*/0}, \ | 1294 | {/*sizes*/0}, \ | |
| 1285 | whio_epfs_handle_list_empty_m, \ | 1295 | whio_epfs_handle_list_empty_m, \ | |
| 1286 | whio_client_data_empty_m,\ | 1296 | whio_client_data_empty_m,\ | |
| 1287 | {/*hints*/1U/*nextFreeInode*/,\ | | | 1297 | {/*hints*/\ |
| 1288 | 0U/*maxEverUsedInode*/,\ | | | 1298 | 0U/*maxEverUsedInode*/, \ |
| 1289 | 0U/*freeBlockList*/,\ | | | 1299 | 0U/*freeInodeList*/, \ |
| 1290 | 0U/*blockCount*/,\ | | | 1300 | 0U/*freeBlockList*/, \ |
| | | 1301 | 0U/*blockCount*/, \ | ||
| 1291 | 0U/*maxEverUsedBlock*/, \ | 1302 | 0U/*maxEverUsedBlock*/, \ | |
| 1292 | NULL/*allocStamp*/,\ | 1303 | NULL/*allocStamp*/,\ | |
| 1293 | -1/*storageLockingMode*/,\ | 1304 | -1/*storageLockingMode*/,\ | |
| 1294 | }, \ | 1305 | }, \ | |
| 1295 | {/*pool*/ \ | 1306 | {/*pool*/ \ | |
| 481 hidden lines | ||||
| 1777 | 1788 | |||
| 1778 | 1789 | |||
| 1779 | /** | 1790 | /** | |
| 1780 | Please read all of these docs before using this function... | 1791 | Please read all of these docs before using this function... | |
| 1781 | 1792 | |||
| 1782 | First: highly experimental! (But it seems to work.) | | | 1793 | First: HIGHLY EXPERIMENTAL! It normally seems to work, but once |
| | | 1794 | in a while i'm getting memory corruption in objects allocated | ||
| | | 1795 | through the custom allocator, normally via the block array | ||
| | | 1796 | reallocations (which hints at a bug in the realloc impl). | ||
| | | 1797 | |||
| | | 1798 | Until the above warning is gone, please do not use this | ||
| | | 1799 | function or the related functionality built on top of it | ||
| | | 1800 | (e.g. whio_epfs_setup_opt::memory). | ||
| 1783 | 1801 | |||
| 1784 | This function tries to set up a memory pool for fs' own use, so | 1802 | This function tries to set up a memory pool for fs' own use, so | |
| 1785 | that fs does not have to use malloc()/realloc() as much. This | 1803 | that fs does not have to use malloc()/realloc() as much. This | |
| 1786 | reduces calls into the OS and helps provide good locality of | 1804 | reduces calls into the OS and helps provide good locality of | |
| 1787 | reference for various fs-internal objects (which tend to | 1805 | reference for various fs-internal objects (which tend to | |
| 186 hidden lines | ||||
| 1974 | /** | 1992 | /** | |
| 1975 | If fs is opened for read/write then this flushes the storage | 1993 | If fs is opened for read/write then this flushes the storage | |
| 1976 | and returns a storage-dependent non-zero value on error. If fs | 1994 | and returns a storage-dependent non-zero value on error. If fs | |
| 1977 | is read-only then whio_rc.AccessError is returned. If !fs then | 1995 | is read-only then whio_rc.AccessError is returned. If !fs then | |
| 1978 | whio_rc.ArgError is returned. | 1996 | whio_rc.ArgError is returned. | |
| > | 1997 | |||
| > | 1998 | This routine is used to ensure that any persistent fs-internal | ||
| > | 1999 | metadata is flushed to storage. Do not call it too often, | ||
| > | 2000 | though, as it can be relatively slow. | ||
| 1979 | 2001 | |||
| 1980 | Returns 0 on success. | 2002 | Returns 0 on success. | |
| 1981 | */ | 2003 | */ | |
| 1982 | int whio_epfs_flush( whio_epfs * fs ); | 2004 | int whio_epfs_flush( whio_epfs * fs ); | |
| 1983 | 2005 | |||
| 540 hidden lines | ||||
| 2524 | #ifdef __cplusplus | 2546 | #ifdef __cplusplus | |
| 2525 | } /* extern "C" */ | 2547 | } /* extern "C" */ | |
| 2526 | #endif | 2548 | #endif | |
| 2527 | 2549 | |||
| 2528 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_H_INCLUDED */ | 2550 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_H_INCLUDED */ | |
Changes to pfs/EPFSApp.c
| Old (1f409f52b343cd4b) | New (a038bdeeb642979c) | |||
|---|---|---|---|---|
| 1 | /** | 1 | /** | |
| 2 | This file is intended to be #include'd by the whio_epfs tools | 2 | This file is intended to be #include'd by the whio_epfs tools | |
| 3 | code. It is a small framework providing the basic shared | 3 | code. It is a small framework providing the basic shared | |
| 4 | functionality used by those apps: | 4 | functionality used by those apps: | |
| 5 | 5 | |||
| 22 hidden lines | ||||
| 28 | enum { | 28 | enum { | |
| 29 | /** | 29 | /** | |
| 30 | Statically-assigned size of whio_epfs memory pool for EPFS. | 30 | Statically-assigned size of whio_epfs memory pool for EPFS. | |
| 31 | */ | 31 | */ | |
| 32 | AllocatorSize = | 32 | AllocatorSize = | |
| 33 | //4000 // only a very large EFS with lots of opened records, or large pseudofiles with small block sizes, would need this much. | | | 33 | 4000 // only a very large EFS with lots of opened records, or large pseudofiles with small block sizes, would need this much. |
| 34 | //2000 // has worked for me so far (famous last words) | 34 | //2000 // has worked for me so far (famous last words) | |
| 35 | //500 // works for small use cases on 32-bit, but not 64-bit. Good for testing allocation failure. | 35 | //500 // works for small use cases on 32-bit, but not 64-bit. Good for testing allocation failure. | |
| 36 | 0 // uses stdlib allocators | | | 36 | //0 // uses stdlib allocators |
| 37 | , | 37 | , | |
| 38 | /** | 38 | /** | |
| 39 | Statically-assigned size of whio_alloc() memory pool. | 39 | Statically-assigned size of whio_alloc() memory pool. | |
| 40 | 40 | |||
| 41 | Due to static destruction ordering and our use of atexit(), we have | 41 | Due to static destruction ordering and our use of atexit(), we have | |
| 1085 hidden lines | ||||
| 1127 | return whio_rc.OK; | 1127 | return whio_rc.OK; | |
| 1128 | } | 1128 | } | |
| 1129 | 1129 | |||
| 1130 | 1130 | |||
| 1131 | #endif /* WANDERINGHORSE_NET_WHIO_EPFSAPP_C_INCLUDED */ | 1131 | #endif /* WANDERINGHORSE_NET_WHIO_EPFSAPP_C_INCLUDED */ | |
Changes to pfs/block.c
| Old (eb21a33dd6a91117) | New (1e84b7cb082f26a7) | |||
|---|---|---|---|---|
| 1 | /************************************************************************ | 1 | /************************************************************************ | |
| 2 | FAR FROM COMPLETE. | 2 | FAR FROM COMPLETE. | |
| 3 | 3 | |||
| 4 | This is a work-in-progress, porting over parts of the whefs API into | 4 | This is a work-in-progress, porting over parts of the whefs API into | |
| 5 | the whio API... | 5 | the whio API... | |
| 3 hidden lines | ||||
| 9 | License: Public Domain | 9 | License: Public Domain | |
| 10 | ************************************************************************/ | 10 | ************************************************************************/ | |
| 11 | #if 1 | 11 | #if 1 | |
| 12 | #define MARKER(X) | 12 | #define MARKER(X) | |
| 13 | #else | 13 | #else | |
| 14 | #define MARKER(X) printf X | | | 14 | #define MARKER(X) printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); printf X |
| 15 | #define WHIO_DEBUG_ENABLED 1 | 15 | #define WHIO_DEBUG_ENABLED 1 | |
| 16 | #endif | 16 | #endif | |
| 17 | 17 | |||
| 18 | #include <wh/whio/whio_devs.h> | 18 | #include <wh/whio/whio_devs.h> | |
| 19 | #include <wh/whio/whio_encode.h> | 19 | #include <wh/whio/whio_encode.h> | |
| 468 hidden lines | ||||
| 488 | do | 488 | do | |
| 489 | { | 489 | { | |
| 490 | id = fs->hints.maxEverUsedBlock+1; | 490 | id = fs->hints.maxEverUsedBlock+1; | |
| 491 | rc = whio_epfs_block_read( fs, id, &bl ); | 491 | rc = whio_epfs_block_read( fs, id, &bl ); | |
| 492 | if( 0 == rc ) | 492 | if( 0 == rc ) | |
| 493 | { /* block exists */ | | | 493 | { /* block exists? */ |
| | | 494 | if( whio_epfs_block_is_used(&bl) ) | ||
| | | 495 | { | ||
| | | 496 | assert(0 && "next-free-inode got a used inode!"); | ||
| | | 497 | } | ||
| | | 498 | return whio_rc.InternalError; | ||
| 494 | } | 499 | } | |
| 495 | else | 500 | else | |
| 496 | { | 501 | { | |
| 497 | /** Create the block... */ | | | 502 | /** Try to create the block... */ |
| 498 | bl = whio_epfs_block_empty; | 503 | bl = whio_epfs_block_empty; | |
| 499 | bl.id = id; | 504 | bl.id = id; | |
| > | 505 | #if 0 | ||
| > | 506 | rc = whio_epfs_block_set_used( fs, &bl, markAsUsed ) | ||
| > | 507 | /* might update fs->hints.freeBlockList */ | ||
| > | 508 | ; | ||
| > | 509 | if( rc ) return rc; | ||
| > | 510 | #endif | ||
| 500 | rc = whio_epfs_block_flush( fs, &bl ); | 511 | rc = whio_epfs_block_flush( fs, &bl ); | |
| 501 | if( rc ) return rc; | 512 | if( rc ) return rc; | |
| 502 | rc = whio_epfs_block_wipe_data( fs, &bl, 0 ); | 513 | rc = whio_epfs_block_wipe_data( fs, &bl, 0 ); | |
| 503 | if( rc ) return rc; | 514 | if( rc ) return rc; | |
| 504 | } | 515 | } | |
| 317 hidden lines | ||||
| 822 | return rc; | 833 | return rc; | |
| 823 | } | 834 | } | |
| 824 | } | 835 | } | |
| 825 | 836 | |||
| 826 | #undef MARKER | 837 | #undef MARKER | |
Changes to pfs/handle.c
| Old (e1a224989e2bab1d) | New (3ea415da23ddacdc) | |||
|---|---|---|---|---|
| 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> | |
| 369 hidden lines | ||||
| 375 | CLEANUP; | 375 | CLEANUP; | |
| 376 | return whio_rc.AccessError;//need new error code for this??? | 376 | return whio_rc.AccessError;//need new error code for this??? | |
| 377 | } | 377 | } | |
| 378 | if( ! wasUsed ) | 378 | if( ! wasUsed ) | |
| 379 | { | 379 | { | |
| 380 | whio_epfs_inode_set_used( &oni, true ); | | | 380 | whio_epfs_inode_set_used( fs, &oni, true ); |
| 381 | rc = whio_epfs_inode_flush( fs, &oni ); | 381 | rc = whio_epfs_inode_flush( fs, &oni ); | |
| 382 | if( rc ) | 382 | if( rc ) | |
| 383 | { | 383 | { | |
| 384 | /* | 384 | /* | |
| 385 | FIXME: need to unlock here on error. | 385 | FIXME: need to unlock here on error. | |
| 75 hidden lines | ||||
| 461 | #undef XXX | 461 | #undef XXX | |
| 462 | return rc; | 462 | return rc; | |
| 463 | } | 463 | } | |
| 464 | 464 | |||
| 465 | #undef TRY_SORTED_HANDLE_LIST | 465 | #undef TRY_SORTED_HANDLE_LIST | |
Changes to pfs/inode.c
| Old (ee3c237647709ee6) | New (0032a6a00366197d) | |||
|---|---|---|---|---|
| 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 | |||
| 8 hidden lines | ||||
| 14 | #include <wh/whio/whio_encode.h> | 14 | #include <wh/whio/whio_encode.h> | |
| 15 | #include <assert.h> | 15 | #include <assert.h> | |
| 16 | #include <time.h> // time(), gmtime(), mktime() | 16 | #include <time.h> // time(), gmtime(), mktime() | |
| 17 | 17 | |||
| 18 | #include "whio_epfs_internal.h" | 18 | #include "whio_epfs_internal.h" | |
| 19 | #define MARKER printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); printf | | | 19 | #if 1 |
| | | 20 | #define MARKER(X) | ||
| | | 21 | #else | ||
| | | 22 | #define MARKER(X) printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); printf X | ||
| | | 23 | #endif | ||
| 20 | 24 | |||
| 21 | bool whio_epfs_inode_is_used( whio_epfs_inode const * ino ) | 25 | bool whio_epfs_inode_is_used( whio_epfs_inode const * ino ) | |
| 22 | { | 26 | { | |
| 23 | return ino && (ino->flags & WHIO_EPFS_FLAG_IS_USED); | 27 | return ino && (ino->flags & WHIO_EPFS_FLAG_IS_USED); | |
| 24 | } | 28 | } | |
| > | 29 | /** | ||
| > | 30 | Updates fs->hints.freeInodeList to remove ino. | ||
| 25 | 31 | |||
| 26 | int whio_epfs_inode_set_used( whio_epfs_inode * ino, bool u ) | | | 32 | ino and its neighbors are flushed. |
| | | 33 | |||
| | | 34 | Returns 0 on success. On error the free list may be | ||
| | | 35 | in an undefined state. | ||
| | | 36 | */ | ||
| | | 37 | static int whio_epfs_inode_from_freelist( whio_epfs * fs, | ||
| | | 38 | whio_epfs_inode * ino ) | ||
| | | 39 | { | ||
| | | 40 | whio_epfs_inode on = whio_epfs_inode_empty; | ||
| | | 41 | int rc = 0; | ||
| | | 42 | int i = 0; | ||
| | | 43 | if( !ino->nextFree && !ino->prevFree ) | ||
| | | 44 | { | ||
| | | 45 | if( fs->hints.freeInodeList == ino->id ) | ||
| | | 46 | { | ||
| | | 47 | fs->hints.freeInodeList = 0; | ||
| | | 48 | } | ||
| | | 49 | return 0; | ||
| | | 50 | } | ||
| | | 51 | for( ; i < 2; ++i ) | ||
| | | 52 | { | ||
| | | 53 | whio_epfs_id_t nid = (0==i) ? ino->prevFree : ino->nextFree; | ||
| | | 54 | if( ! nid ) continue; | ||
| | | 55 | rc = whio_epfs_inode_read( fs, nid, &on ); | ||
| | | 56 | if( rc ) break; | ||
| | | 57 | if( 0 == i ) | ||
| | | 58 | { /* we're on the left. */ | ||
| | | 59 | on.nextFree = ino->nextFree; | ||
| | | 60 | } | ||
| | | 61 | else | ||
| | | 62 | { /* we're on the right */ | ||
| | | 63 | on.prevFree = ino->prevFree; | ||
| | | 64 | } | ||
| | | 65 | rc = whio_epfs_inode_flush( fs, &on ); | ||
| | | 66 | if( rc ) break; | ||
| | | 67 | } | ||
| | | 68 | if( !rc ) | ||
| | | 69 | { | ||
| | | 70 | if( fs->hints.freeInodeList == ino->id ) | ||
| | | 71 | { | ||
| | | 72 | fs->hints.freeInodeList = ino->prevFree ? ino->prevFree : ino->nextFree; | ||
| | | 73 | } | ||
| | | 74 | |||
| | | 75 | MARKER(("Removed inode #%"WHIO_EPFS_ID_T_PFMT" from free-list. " | ||
| | | 76 | "fs->hints.freeInodeList=%"WHIO_EPFS_ID_T_PFMT"\n", | ||
| | | 77 | ino->id, fs->hints.freeInodeList )); | ||
| | | 78 | ino->nextFree = ino->prevFree = 0; | ||
| | | 79 | rc = whio_epfs_inode_flush( fs, ino ); | ||
| | | 80 | } | ||
| | | 81 | return rc; | ||
| | | 82 | } | ||
| | | 83 | |||
| | | 84 | /** | ||
| | | 85 | Updates fs->hints.freeInodeList to insert ino | ||
| | | 86 | as the first free item. This modifies ino->nextFree | ||
| | | 87 | and ino->prevFree. | ||
| | | 88 | |||
| | | 89 | ino and its neighbors are flushed. | ||
| | | 90 | |||
| | | 91 | Returns 0 on success. On error the free list may be | ||
| | | 92 | in an undefined state. | ||
| | | 93 | */ | ||
| | | 94 | static int whio_epfs_inode_to_freelist( whio_epfs * fs, whio_epfs_inode * ino ) | ||
| | | 95 | { | ||
| | | 96 | |||
| | | 97 | int rc = 0; | ||
| | | 98 | if( fs->hints.freeInodeList == ino->id ) return rc; | ||
| | | 99 | else if( fs->hints.freeInodeList ) | ||
| | | 100 | { | ||
| | | 101 | whio_epfs_inode on = whio_epfs_inode_empty; | ||
| | | 102 | rc = whio_epfs_inode_read( fs, fs->hints.freeInodeList, &on ); | ||
| | | 103 | if( rc ) return rc; | ||
| | | 104 | on.prevFree = ino->id; | ||
| | | 105 | rc = whio_epfs_inode_flush( fs, &on ); | ||
| | | 106 | if( rc ) return rc; | ||
| | | 107 | ino->nextFree = on.id; | ||
| | | 108 | } | ||
| | | 109 | ino->prevFree = 0; | ||
| | | 110 | rc = whio_epfs_inode_flush( fs, ino ); | ||
| | | 111 | if( !rc ) | ||
| | | 112 | { | ||
| | | 113 | fs->hints.freeInodeList = ino->id; | ||
| | | 114 | } | ||
| | | 115 | return rc; | ||
| | | 116 | } | ||
| | | 117 | |||
| | | 118 | int whio_epfs_inode_set_used( whio_epfs * fs, whio_epfs_inode * ino, bool u ) | ||
| 27 | { | 119 | { | |
| 28 | if( ! ino ) return whio_rc.ArgError; | 120 | if( ! ino ) return whio_rc.ArgError; | |
| 29 | else | 121 | else | |
| 30 | { | 122 | { | |
| 31 | if(u) | 123 | if(u) | |
| 32 | { | 124 | { | |
| 33 | ino->flags|=WHIO_EPFS_FLAG_IS_USED; | | | 125 | if( !(ino->flags & WHIO_EPFS_FLAG_IS_USED) ) |
| 34 | if( ! ino->mtime ) | | | ||
| 35 | { | 126 | { | |
| 36 | whio_epfs_inode_touch( ino, -1 ); | | | 127 | whio_epfs_inode_from_freelist( fs, ino ); |
| | | 128 | ino->flags|=WHIO_EPFS_FLAG_IS_USED; | ||
| | | 129 | MARKER(("Setting inode #%"WHIO_EPFS_ID_T_PFMT" as used. " | ||
| | | 130 | "freeInodeList=%"WHIO_EPFS_ID_T_PFMT"\n", | ||
| | | 131 | ino->id, fs->hints.freeInodeList )); | ||
| | | 132 | if( ! ino->mtime ) | ||
| | | 133 | { | ||
| | | 134 | whio_epfs_inode_touch( ino, -1 ); | ||
| | | 135 | } | ||
| 37 | } | 136 | } | |
| 38 | } | 137 | } | |
| 39 | else | 138 | else | |
| 40 | { | 139 | { | |
| 41 | whio_epfs_id_t id = ino->id; | | | 140 | if( ino->flags & WHIO_EPFS_FLAG_IS_USED ) |
| 42 | *ino = whio_epfs_inode_empty; | | | 141 | { |
| 43 | ino->id = id; | | | 142 | whio_epfs_id_t id = ino->id; |
| | | 143 | *ino = whio_epfs_inode_empty; | ||
| | | 144 | ino->id = id; | ||
| | | 145 | whio_epfs_inode_to_freelist( fs, ino ); | ||
| | | 146 | } | ||
| 44 | } | 147 | } | |
| 45 | return whio_rc.OK; | 148 | return whio_rc.OK; | |
| 46 | } | 149 | } | |
| 47 | } | 150 | } | |
| 48 | 151 | |||
| 3 hidden lines | ||||
| 52 | { | 155 | { | |
| 53 | if( ! ino || ! dest ) return 0; | 156 | if( ! ino || ! dest ) return 0; | |
| 54 | *(dest++) = whio_epfs_inode_tag_char; | 157 | *(dest++) = whio_epfs_inode_tag_char; | |
| 55 | dest += whio_epfs_encode_id( dest, ino->id ); | 158 | dest += whio_epfs_encode_id( dest, ino->id ); | |
| 56 | dest += whio_encode_uint8( dest, ino->flags ); | 159 | dest += whio_encode_uint8( dest, ino->flags ); | |
| 57 | dest += whio_epfs_encode_id( dest, ino->firstBlock ); | < | ||
| 58 | dest += whio_epfs_encode_id( dest, ino->nextFree ); | 160 | dest += whio_epfs_encode_id( dest, ino->nextFree ); | |
| > | 161 | dest += whio_epfs_encode_id( dest, ino->prevFree ); | ||
| > | 162 | dest += whio_epfs_encode_id( dest, ino->firstBlock ); | ||
| 59 | dest += whio_encode_uint32( dest, ino->cflags ); | 163 | dest += whio_encode_uint32( dest, ino->cflags ); | |
| 60 | dest += whio_encode_size_t( dest, ino->size ); | 164 | dest += whio_encode_size_t( dest, ino->size ); | |
| 61 | dest += whio_encode_uint32( dest, ino->mtime ); | 165 | dest += whio_encode_uint32( dest, ino->mtime ); | |
| 62 | return whio_epfs_sizeof_inode; | 166 | return whio_epfs_sizeof_inode; | |
| 63 | } | 167 | } | |
| 13 hidden lines | ||||
| 77 | 181 | |||
| 78 | rc = whio_decode_uint8( at, &ino->flags ); | 182 | rc = whio_decode_uint8( at, &ino->flags ); | |
| 79 | if( rc ) return rc; | 183 | if( rc ) return rc; | |
| 80 | at += whio_sizeof_encoded_uint8; | 184 | at += whio_sizeof_encoded_uint8; | |
| 81 | 185 | |||
| 82 | rc = whio_epfs_decode_id( at, &ino->firstBlock ); | | | 186 | rc = whio_epfs_decode_id( at, &ino->nextFree ); |
| | | 187 | if( rc ) return rc; | ||
| | | 188 | at += whio_epfs_sizeof_id; | ||
| | | 189 | |||
| | | 190 | rc = whio_epfs_decode_id( at, &ino->prevFree ); | ||
| 83 | if( rc ) return rc; | 191 | if( rc ) return rc; | |
| 84 | at += whio_epfs_sizeof_id; | 192 | at += whio_epfs_sizeof_id; | |
| 85 | 193 | |||
| 86 | rc = whio_epfs_decode_id( at, &ino->nextFree ); | | | 194 | rc = whio_epfs_decode_id( at, &ino->firstBlock ); |
| 87 | if( rc ) return rc; | 195 | if( rc ) return rc; | |
| 88 | at += whio_epfs_sizeof_id; | 196 | at += whio_epfs_sizeof_id; | |
| 89 | 197 | |||
| 90 | rc = whio_decode_uint32( at, &ino->cflags ); | 198 | rc = whio_decode_uint32( at, &ino->cflags ); | |
| 91 | if( rc ) return rc; | 199 | if( rc ) return rc; | |
| 52 hidden lines | ||||
| 144 | } | 252 | } | |
| 145 | 253 | |||
| 146 | int whio_epfs_inode_next_free( whio_epfs * fs, whio_epfs_inode * dest, bool markAsUsed ) | 254 | int whio_epfs_inode_next_free( whio_epfs * fs, whio_epfs_inode * dest, bool markAsUsed ) | |
| 147 | { | 255 | { | |
| 148 | if( ! fs || ! dest ) return whio_rc.ArgError; | 256 | if( ! fs || ! dest ) return whio_rc.ArgError; | |
| 149 | whio_epfs_id_t id = fs->hints.nextFreeInode; | | | 257 | else if( markAsUsed && !whio_epfs_is_rw(fs) ) |
| 150 | if( ! (id+1) ) | | | ||
| 151 | { | 258 | { | |
| 152 | WHIO_DEBUG("Search for next free inode would overflow counter!\n"); | | | 259 | return whio_rc.AccessError; |
| 153 | return whio_rc.RangeError; | | | ||
| 154 | } | 260 | } | |
| 155 | else if( id >= fs->fsopt.inodeCount ) | < | ||
| 156 | { | < | ||
| 157 | /** | < | ||
| 158 | Re-set the counter to try to see if we can find any | < | ||
| 159 | orphaned inodes in here... | < | ||
| 160 | */ | < | ||
| 161 | id = fs->hints.nextFreeInode = 1; | < | ||
| 162 | } | < | ||
| 163 | else if( ! id ) | < | ||
| 164 | { | < | ||
| 165 | /* inode ID 0 is reserved for not-an-inode. */ | < | ||
| 166 | id = fs->hints.nextFreeInode = 1; | < | ||
| 167 | } | < | ||
| 168 | if( id >= fs->fsopt.inodeCount ) return whio_rc.RangeError; | < | ||
| 169 | int rc = 0; | 261 | int rc = 0; | |
| > | 262 | /** | ||
| > | 263 | This impl would be guaranteed O(1), but the ability to open an | ||
| > | 264 | arbitrary inode number means that our free-list can get | ||
| > | 265 | confused. So we have a potential linear component. | ||
| > | 266 | */ | ||
| 170 | whio_epfs_inode ino = whio_epfs_inode_empty; | 267 | whio_epfs_inode ino = whio_epfs_inode_empty; | |
| 171 | //whio_epfs_id_t origin = id; | | | 268 | whio_epfs_id_t id = fs->hints.freeInodeList; |
| 172 | for( ; id <= fs->fsopt.inodeCount; ++id ) | | | 269 | while(id) |
| 173 | { | 270 | { | |
| 174 | rc = whio_epfs_inode_read( fs, id, &ino ); | 271 | rc = whio_epfs_inode_read( fs, id, &ino ); | |
| 175 | if( rc ) return rc; | 272 | if( rc ) return rc; | |
| 176 | if( whio_epfs_inode_is_used( &ino ) ) continue; | | | 273 | if( whio_epfs_inode_is_used( &ino ) ) |
| 177 | if( markAsUsed ) | | | ||
| 178 | { | 274 | { | |
| 179 | whio_epfs_inode_set_used( &ino, true ); | | | 275 | MARKER(("Is-free check of inode #%"WHIO_EPFS_ID_T_PFMT" failed.\n",ino.id)); |
| 180 | rc = whio_epfs_inode_flush( fs, &ino ); | | | 276 | if( ino.nextFree ) |
| 181 | if( rc ) return rc; | | | ||
| 182 | #if 0 //WHIO_EPFS_CONFIG_AUTO_FLUSH_HINTS | | | ||
| 183 | // done in whio_epfs_inode_read/flush() | | | ||
| 184 | int8_t changes = 0; | | | ||
| 185 | if( origin >= id ) | | | ||
| 186 | { | 277 | { | |
| 187 | fs->hints.nextFreeInode = id + 1; | | | 278 | MARKER(("Trying ino.nextFree #%"WHIO_EPFS_ID_T_PFMT".\n",ino.nextFree)); |
| 188 | ++changes; | | | 279 | if( fs->hints.freeInodeList == ino.id ) |
| | | 280 | { | ||
| | | 281 | fs->hints.freeInodeList = ino.nextFree; | ||
| | | 282 | } | ||
| | | 283 | id = ino.nextFree; | ||
| | | 284 | continue; | ||
| 189 | } | 285 | } | |
| 190 | if( id > fs->hints.maxEverUsedInode ) | < | ||
| 191 | { | < | ||
| 192 | fs->hints.maxEverUsedInode = id; | < | ||
| 193 | ++changes; | < | ||
| 194 | } | < | ||
| 195 | if( changes ) | < | ||
| 196 | { | < | ||
| 197 | rc = whio_epfs_hints_write( fs ); | < | ||
| 198 | if( rc ) return rc; | < | ||
| 199 | } | < | ||
| 200 | #endif | < | ||
| 201 | } | 286 | } | |
| > | 287 | break; | ||
| > | 288 | } | ||
| > | 289 | if( ! id ) | ||
| > | 290 | { /* assume we are full */ | ||
| > | 291 | return whio_rc.DeviceFullError; | ||
| > | 292 | } | ||
| > | 293 | if( markAsUsed ) | ||
| > | 294 | { | ||
| > | 295 | rc = whio_epfs_inode_set_used( fs, &ino, true ); | ||
| > | 296 | //if(!rc) rc = whio_epfs_inode_flush( fs, &ino ); | ||
| > | 297 | if(!rc) rc = whio_epfs_hints_write( fs ); | ||
| > | 298 | } | ||
| > | 299 | if( ! rc ) | ||
| > | 300 | { | ||
| 202 | *dest = ino; | 301 | *dest = ino; | |
| 203 | return whio_rc.OK; | < | ||
| 204 | } | 302 | } | |
| 205 | rc = whio_rc.DeviceFullError; | < | ||
| 206 | return rc; | 303 | return rc; | |
| 207 | } | 304 | } | |
| 208 | 305 | |||
| 209 | 306 | |||
| 210 | int whio_epfs_inode_flush( whio_epfs * fs, | 307 | int whio_epfs_inode_flush( whio_epfs * fs, | |
| 19 hidden lines | ||||
| 230 | if( ino->id > fs->hints.maxEverUsedInode ) | 327 | if( ino->id > fs->hints.maxEverUsedInode ) | |
| 231 | { | 328 | { | |
| 232 | fs->hints.maxEverUsedInode = ino->id; | 329 | fs->hints.maxEverUsedInode = ino->id; | |
| 233 | ++changes; | 330 | ++changes; | |
| 234 | } | 331 | } | |
| 235 | } | < | ||
| 236 | else if( fs->hints.nextFreeInode > ino->id ) | < | ||
| 237 | { | < | ||
| 238 | fs->hints.nextFreeInode = ino->id; | < | ||
| 239 | ++changes; | < | ||
| 240 | } | 332 | } | |
| 241 | #if WHIO_EPFS_CONFIG_AUTO_FLUSH_HINTS | 333 | #if WHIO_EPFS_CONFIG_AUTO_FLUSH_HINTS | |
| 242 | if( changes ) | 334 | if( changes ) | |
| 243 | { | 335 | { | |
| 244 | int rc = whio_epfs_hints_write( fs ); | 336 | int rc = whio_epfs_hints_write( fs ); | |
| 32 hidden lines | ||||
| 277 | if( fs->hints.maxEverUsedInode < ino.id ) | 369 | if( fs->hints.maxEverUsedInode < ino.id ) | |
| 278 | { | 370 | { | |
| 279 | fs->hints.maxEverUsedInode = ino.id; | 371 | fs->hints.maxEverUsedInode = ino.id; | |
| 280 | ++changes; | 372 | ++changes; | |
| 281 | } | 373 | } | |
| 282 | } | < | ||
| 283 | else if( fs->hints.nextFreeInode > ino.id ) | < | ||
| 284 | { | < | ||
| 285 | fs->hints.nextFreeInode = ino.id; | < | ||
| 286 | ++changes; | < | ||
| 287 | } | 374 | } | |
| 288 | #if WHIO_EPFS_CONFIG_AUTO_FLUSH_HINTS | 375 | #if WHIO_EPFS_CONFIG_AUTO_FLUSH_HINTS | |
| 289 | if( changes && whio_epfs_is_rw(fs) ) | 376 | if( changes && whio_epfs_is_rw(fs) ) | |
| 290 | { | 377 | { | |
| 291 | rc = whio_epfs_hints_write( fs ); | 378 | rc = whio_epfs_hints_write( fs ); | |
| 153 hidden lines | ||||
| 445 | } | 532 | } | |
| 446 | return rc; | 533 | return rc; | |
| 447 | } | 534 | } | |
| 448 | 535 | |||
| 449 | #undef MARKER | 536 | #undef MARKER | |
Changes to pfs/ls.c
| Old (9bf1654b37254e30) | New (c9e8d146738a5388) | |||
|---|---|---|---|---|
| 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 | |||
| 208 hidden lines | ||||
| 214 | ); | 214 | ); | |
| 215 | if( EPFSApp.verbose ) | 215 | if( EPFSApp.verbose ) | |
| 216 | { | 216 | { | |
| 217 | printf("\t[inodes=%"WHIO_EPFS_ID_T_PFMT"] [maxEverUsedInodeID==%"WHIO_EPFS_ID_T_PFMT"]\n" | 217 | printf("\t[inodes=%"WHIO_EPFS_ID_T_PFMT"] [maxEverUsedInodeID==%"WHIO_EPFS_ID_T_PFMT"]\n" | |
| 218 | "\t[blockSize=%"WHIO_SIZE_T_PFMT"] [blocksInFS=%"WHIO_EPFS_ID_T_PFMT"] [maxBlocks=%"WHIO_EPFS_ID_T_PFMT"] [maxEverUsedBlockID==%"WHIO_EPFS_ID_T_PFMT"]\n" | 218 | "\t[blockSize=%"WHIO_SIZE_T_PFMT"] [blocksInFS=%"WHIO_EPFS_ID_T_PFMT"] [maxBlocks=%"WHIO_EPFS_ID_T_PFMT"] [maxEverUsedBlockID==%"WHIO_EPFS_ID_T_PFMT"]\n" | |
| 219 | "\t[freeBlockList=%"WHIO_SIZE_T_PFMT"]" | | | 219 | "\t[freeBlockList=%"WHIO_SIZE_T_PFMT"] [freeInodeList=%"WHIO_SIZE_T_PFMT"]" |
| 220 | "\n", | 220 | "\n", | |
| 221 | fopt->inodeCount, EPFSApp.fs->hints.maxEverUsedInode, | 221 | fopt->inodeCount, EPFSApp.fs->hints.maxEverUsedInode, | |
| 222 | fopt->blockSize, EPFSApp.fs->hints.blockCount, fopt->maxBlocks, EPFSApp.fs->hints.maxEverUsedBlock, | 222 | fopt->blockSize, EPFSApp.fs->hints.blockCount, fopt->maxBlocks, EPFSApp.fs->hints.maxEverUsedBlock, | |
| 223 | EPFSApp.fs->hints.freeBlockList | | | 223 | EPFSApp.fs->hints.freeBlockList, EPFSApp.fs->hints.freeInodeList |
| 224 | ); | 224 | ); | |
| 225 | } | 225 | } | |
| 226 | 226 | |||
| 227 | //printf("Magic bytes: "); ls_dump_core_magic(); | 227 | //printf("Magic bytes: "); ls_dump_core_magic(); | |
| 228 | printf("Inode #\t Size\t "); | 228 | printf("Inode #\t Size\t "); | |
| 26 hidden lines | ||||
| 255 | info.blockCount ); | 255 | info.blockCount ); | |
| 256 | } | 256 | } | |
| 257 | puts("."); | 257 | puts("."); | |
| 258 | } | 258 | } | |
| 259 | 259 | |||
| 260 | if( EPFSApp.verbose && AppLs.showBlocks ) | < | ||
| 261 | { | < | ||
| 262 | puts("\nData block free-list: "); | < | ||
| 263 | whio_epfs_id_t f = EPFSApp.fs->hints.freeBlockList; | < | ||
| 264 | if( !f ) | < | ||
| 265 | { | < | ||
| 266 | puts("No explicit unused blocks."); | < | ||
| 267 | } | < | ||
| 268 | else | < | ||
| 269 | while( f ) | < | ||
| 270 | { | < | ||
| 271 | whio_epfs_block bl = whio_epfs_block_empty; | < | ||
| 272 | rc = whio_epfs_block_read( EPFSApp.fs, f, &bl ); | < | ||
| 273 | if( rc ) | < | ||
| 274 | { | < | ||
| 275 | APPERR("Error reading block #%"WHIO_EPFS_ID_T_PFMT"!\n",f); | < | ||
| 276 | break; | < | ||
| 277 | } | < | ||
| 278 | printf("%"WHIO_EPFS_ID_T_PFMT"->%"WHIO_EPFS_ID_T_PFMT"%s", | < | ||
| 279 | bl.id, bl.nextFree, | < | ||
| 280 | (bl.nextFree ? ", " : "") | < | ||
| 281 | ); | < | ||
| 282 | f = bl.nextFree; | < | ||
| 283 | } | < | ||
| 284 | putchar('\n'); | < | ||
| 285 | } | < | ||
| 286 | if( rc ) | 260 | if( rc ) | |
| 287 | { | 261 | { | |
| 288 | APPERR("Got error code %d while looping over inodes!\n", rc ); | 262 | APPERR("Got error code %d while looping over inodes!\n", rc ); | |
| 289 | } | 263 | } | |
| 290 | return rc; | 264 | return rc; | |
| 8 hidden lines | ||||
| 299 | o->inodeCount, | 273 | o->inodeCount, | |
| 300 | EPFSApp.fsName | 274 | EPFSApp.fsName | |
| 301 | ); | 275 | ); | |
| 302 | return 0; | 276 | return 0; | |
| 303 | } | 277 | } | |
| > | 278 | |||
| > | 279 | static int ls_dump_freelists_command() | ||
| > | 280 | { | ||
| > | 281 | int rc = 0; | ||
| > | 282 | int i = 0; | ||
| > | 283 | int span = 4; | ||
| > | 284 | { | ||
| > | 285 | puts("Data block free-list: (Block ID->Next free ID)\n"); | ||
| > | 286 | whio_epfs_id_t f = EPFSApp.fs->hints.freeBlockList; | ||
| > | 287 | if( !f ) | ||
| > | 288 | { | ||
| > | 289 | puts("No explicit unused blocks."); | ||
| > | 290 | } | ||
| > | 291 | else | ||
| > | 292 | { | ||
| > | 293 | putchar('\t'); | ||
| > | 294 | while( f ) | ||
| > | 295 | { | ||
| > | 296 | whio_epfs_block bl = whio_epfs_block_empty; | ||
| > | 297 | rc = whio_epfs_block_read( EPFSApp.fs, f, &bl ); | ||
| > | 298 | if( rc ) | ||
| > | 299 | { | ||
| > | 300 | APPERR("Error reading block #%"WHIO_EPFS_ID_T_PFMT"!\n",f); | ||
| > | 301 | return rc; | ||
| > | 302 | } | ||
| > | 303 | printf("(%"WHIO_EPFS_ID_T_PFMT"->%"WHIO_EPFS_ID_T_PFMT")%s", | ||
| > | 304 | bl.id, bl.nextFree, | ||
| > | 305 | (bl.nextFree ? ", " : "") | ||
| > | 306 | ); | ||
| > | 307 | f = bl.nextFree; | ||
| > | 308 | if( i == (span-1) ) | ||
| > | 309 | { | ||
| > | 310 | i = 0; | ||
| > | 311 | printf("\n%s",(f ? "\t" : "")); | ||
| > | 312 | } | ||
| > | 313 | else ++i; | ||
| > | 314 | } | ||
| > | 315 | } | ||
| > | 316 | putchar('\n'); | ||
| > | 317 | } | ||
| > | 318 | putchar('\n'); | ||
| > | 319 | { | ||
| > | 320 | i = 0; | ||
| > | 321 | puts("Inode free-list: (Previous Free<- Inode ID -> Next Free)\n"); | ||
| > | 322 | whio_epfs_id_t f = EPFSApp.fs->hints.freeInodeList; | ||
| > | 323 | if( !f ) | ||
| > | 324 | { | ||
| > | 325 | puts("No explicit unused inodes."); | ||
| > | 326 | } | ||
| > | 327 | else | ||
| > | 328 | { | ||
| > | 329 | putchar('\t'); | ||
| > | 330 | while( f ) | ||
| > | 331 | { | ||
| > | 332 | whio_epfs_inode ino = whio_epfs_inode_empty; | ||
| > | 333 | rc = whio_epfs_inode_read( EPFSApp.fs, f, &ino ); | ||
| > | 334 | if( rc ) | ||
| > | 335 | { | ||
| > | 336 | APPERR("Error reading inode #%"WHIO_EPFS_ID_T_PFMT"!\n",f); | ||
| > | 337 | break; | ||
| > | 338 | } | ||
| > | 339 | printf("(%"WHIO_EPFS_ID_T_PFMT"<-%"WHIO_EPFS_ID_T_PFMT"->%"WHIO_EPFS_ID_T_PFMT")%s", | ||
| > | 340 | ino.prevFree, ino.id, ino.nextFree, | ||
| > | 341 | (ino.nextFree ? ", " : "") | ||
| > | 342 | ); | ||
| > | 343 | f = ino.nextFree; | ||
| > | 344 | if( i == (span-1) ) | ||
| > | 345 | { | ||
| > | 346 | i = 0; | ||
| > | 347 | printf("\n%s",(f ? "\t" : "")); | ||
| > | 348 | } | ||
| > | 349 | else ++i; | ||
| > | 350 | } | ||
| > | 351 | } | ||
| > | 352 | putchar('\n'); | ||
| > | 353 | } | ||
| > | 354 | putchar('\n'); | ||
| > | 355 | return 0; | ||
| > | 356 | } | ||
| > | 357 | |||
| 304 | 358 | |||
| 305 | /** | 359 | /** | |
| 306 | Proxy for a function pointer, to work around not being able to legally | 360 | Proxy for a function pointer, to work around not being able to legally | |
| 307 | convert a (void const *) to a (ls_command_f). | 361 | convert a (void const *) to a (ls_command_f). | |
| 308 | */ | 362 | */ | |
| 17 hidden lines | ||||
| 326 | } | 380 | } | |
| 327 | 381 | |||
| 328 | static const ls_command_f_pedantic_kludge ls_cmd_dump_options_code = {ls_dump_options_code}; | 382 | static const ls_command_f_pedantic_kludge ls_cmd_dump_options_code = {ls_dump_options_code}; | |
| 329 | static const ls_command_f_pedantic_kludge ls_cmd_dump_inodes = {ls_dump_inodes}; | 383 | static const ls_command_f_pedantic_kludge ls_cmd_dump_inodes = {ls_dump_inodes}; | |
| 330 | static const ls_command_f_pedantic_kludge ls_cmd_dump_mkfs_command = {ls_dump_mkfs_command}; | 384 | static const ls_command_f_pedantic_kludge ls_cmd_dump_mkfs_command = {ls_dump_mkfs_command}; | |
| > | 385 | static const ls_command_f_pedantic_kludge ls_cmd_dump_freelists_command = {ls_dump_freelists_command}; | ||
| 331 | #if 0 | 386 | #if 0 | |
| 332 | static const ls_command_f_pedantic_kludge ls_cmd_dump_blocks = {ls_dump_blocks}; | 387 | static const ls_command_f_pedantic_kludge ls_cmd_dump_blocks = {ls_dump_blocks}; | |
| 333 | static const ls_command_f_pedantic_kludge ls_cmd_dump_blocks_table = {ls_dump_blocks_table}; | 388 | static const ls_command_f_pedantic_kludge ls_cmd_dump_blocks_table = {ls_dump_blocks_table}; | |
| 334 | static const ls_command_f_pedantic_kludge ls_cmd_dump_stats = {ls_dump_stats}; | 389 | static const ls_command_f_pedantic_kludge ls_cmd_dump_stats = {ls_dump_stats}; | |
| 335 | #endif | 390 | #endif | |
| 29 hidden lines | ||||
| 365 | {"g", ArgTypeBool, &AppLs.gmtTime, | 420 | {"g", ArgTypeBool, &AppLs.gmtTime, | |
| 366 | "Same as --gmt.", NULL, NULL }, | 421 | "Same as --gmt.", NULL, NULL }, | |
| 367 | {"time-format", ArgTypeCString, &AppLs.tmfmt, | 422 | {"time-format", ArgTypeCString, &AppLs.tmfmt, | |
| 368 | "Sets the time field output format, in a format supported by strftime(3).", | 423 | "Sets the time field output format, in a format supported by strftime(3).", | |
| 369 | NULL, NULL }, | 424 | NULL, NULL }, | |
| > | 425 | {"list", ArgTypeIgnore, NULL, | ||
| > | 426 | "Forces the listing of inodes even if another option (e.g. --freelist) would normally supress the inode list.", | ||
| > | 427 | ls_arg_push_cb, &ls_cmd_dump_inodes }, | ||
| > | 428 | {"l", ArgTypeIgnore, NULL, | ||
| > | 429 | "Same as --list.", | ||
| > | 430 | ls_arg_push_cb, &ls_cmd_dump_inodes }, | ||
| > | 431 | {"freelist", ArgTypeIgnore, 0, | ||
| > | 432 | "Displays the EFS \"free lists\".", | ||
| > | 433 | ls_arg_push_cb, &ls_cmd_dump_freelists_command }, | ||
| > | 434 | {"F", ArgTypeIgnore, 0, | ||
| > | 435 | "Same as --freelist.", | ||
| > | 436 | ls_arg_push_cb, &ls_cmd_dump_freelists_command }, | ||
| 370 | {"dump-mkfs-command", ArgTypeIgnore, 0, | 437 | {"dump-mkfs-command", ArgTypeIgnore, 0, | |
| 371 | "Dumps the EFS options as arguments for passing to whio-epfs-mkfs.", | 438 | "Dumps the EFS options as arguments for passing to whio-epfs-mkfs.", | |
| 372 | ls_arg_push_cb, &ls_cmd_dump_mkfs_command }, | 439 | ls_arg_push_cb, &ls_cmd_dump_mkfs_command }, | |
| 373 | {"dump-lib-magic", ArgTypeIgnore, 0, | 440 | {"dump-lib-magic", ArgTypeIgnore, 0, | |
| 374 | "Dumps the library's file format version number. This can be used without specifying an EFS.", | 441 | "Dumps the library's file format version number. This can be used without specifying an EFS.", | |
| 75 hidden lines | ||||
| 450 | } | 517 | } | |
| 451 | } | 518 | } | |
| 452 | EPFSApp_verbose_error_code( rc ); | 519 | EPFSApp_verbose_error_code( rc ); | |
| 453 | return rc; | 520 | return rc; | |
| 454 | } | 521 | } | |
Changes to pfs/pfs.c
| Old (f2648eead089b3f3) | New (17e2c59903607ab5) | |||
|---|---|---|---|---|
| 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/) | |
| 51 hidden lines | ||||
| 57 | /** Tag marking the beginning of EFS label storage. */ | 57 | /** Tag marking the beginning of EFS label storage. */ | |
| 58 | static const unsigned char whio_epfs_label_tag_char = 'L'; | 58 | static const unsigned char whio_epfs_label_tag_char = 'L'; | |
| 59 | 59 | |||
| 60 | int whio_epfs_flush( whio_epfs * fs ) | 60 | int whio_epfs_flush( whio_epfs * fs ) | |
| 61 | { | 61 | { | |
| 62 | return (fs && fs->dev) | | | 62 | if(!fs || !fs->dev ) return whio_rc.ArgError; |
| 63 | ? (whio_epfs_is_rw(fs) | | | 63 | else if( !whio_epfs_is_rw(fs) ) return whio_rc.AccessError; |
| 64 | ? fs->dev->api->flush( fs->dev ) | | | 64 | else |
| 65 | : whio_rc.AccessError) | | | 65 | { |
| 66 | : whio_rc.ArgError; | | | 66 | /* FIXME? put this somewhere else? */ |
| | | 67 | int rc = whio_epfs_hints_write(fs); | ||
| | | 68 | if(! rc ) | ||
| | | 69 | { | ||
| | | 70 | rc = fs->dev->api->flush( fs->dev ); | ||
| | | 71 | } | ||
| | | 72 | return rc; | ||
| | | 73 | } | ||
| | | 74 | |||
| 67 | } | 75 | } | |
| 68 | 76 | |||
| 69 | whio_epfs_fsopt const * whio_epfs_options(whio_epfs const * fs) | 77 | whio_epfs_fsopt const * whio_epfs_options(whio_epfs const * fs) | |
| 70 | { | 78 | { | |
| 71 | return fs | 79 | return fs | |
| 150 hidden lines | ||||
| 222 | int whio_epfs_close( whio_epfs *fs ) | 230 | int whio_epfs_close( whio_epfs *fs ) | |
| 223 | { | 231 | { | |
| 224 | if( !fs ) return whio_rc.ArgError; | 232 | if( !fs ) return whio_rc.ArgError; | |
| 225 | if( !fs->err && fs->dev && whio_epfs_is_rw(fs) ) | 233 | if( !fs->err && fs->dev && whio_epfs_is_rw(fs) ) | |
| 226 | { | 234 | { | |
| 227 | whio_epfs_hints_write(fs); | | | 235 | whio_epfs_flush(fs); |
| 228 | } | 236 | } | |
| 229 | if( fs->client.dtor ) | 237 | if( fs->client.dtor ) | |
| 230 | { | 238 | { | |
| 231 | /** | 239 | /** | |
| 232 | Reminder: we have to close this early in case the client | 240 | Reminder: we have to close this early in case the client | |
| 339 hidden lines | ||||
| 572 | memset(buf, 0, Len); | 580 | memset(buf, 0, Len); | |
| 573 | unsigned char * dest = buf; | 581 | unsigned char * dest = buf; | |
| 574 | *(dest++) = whio_epfs_hints_tag_char; | 582 | *(dest++) = whio_epfs_hints_tag_char; | |
| 575 | whio_size_t sz = 1; | 583 | whio_size_t sz = 1; | |
| 576 | whio_size_t rc = 0; | 584 | whio_size_t rc = 0; | |
| 577 | rc = whio_epfs_encode_id( dest, fs->hints.nextFreeInode ); | < | ||
| 578 | dest += rc; | < | ||
| 579 | sz += rc; | < | ||
| 580 | 585 | |||
| 581 | rc = whio_epfs_encode_id( dest, fs->hints.maxEverUsedInode ); | 586 | rc = whio_epfs_encode_id( dest, fs->hints.maxEverUsedInode ); | |
| 582 | dest += rc; | 587 | dest += rc; | |
| 583 | sz += rc; | 588 | sz += rc; | |
| 584 | 589 | |||
| 585 | #if 0 | | | 590 | rc = whio_epfs_encode_id( dest, fs->hints.maxEverUsedBlock ); |
| 586 | rc = whio_epfs_encode_id( dest, fs->hints.nextFreeBlock ); | | | ||
| 587 | dest += rc; | 591 | dest += rc; | |
| 588 | sz += rc; | 592 | sz += rc; | |
| 589 | #endif | | | 593 | |
| 590 | rc = whio_epfs_encode_id( dest, fs->hints.maxEverUsedBlock ); | | | 594 | rc = whio_epfs_encode_id( dest, fs->hints.freeInodeList ); |
| 591 | dest += rc; | 595 | dest += rc; | |
| 592 | sz += rc; | 596 | sz += rc; | |
| 593 | 597 | |||
| 594 | rc = whio_epfs_encode_id( dest, fs->hints.freeBlockList ); | 598 | rc = whio_epfs_encode_id( dest, fs->hints.freeBlockList ); | |
| 595 | dest += rc; | 599 | dest += rc; | |
| 34 hidden lines | ||||
| 630 | return whio_rc.ConsistencyError; | 634 | return whio_rc.ConsistencyError; | |
| 631 | } | 635 | } | |
| 632 | unsigned char * at = buf+1; | 636 | unsigned char * at = buf+1; | |
| 633 | int rc = 0; | 637 | int rc = 0; | |
| 634 | 638 | |||
| 635 | rc = whio_epfs_decode_id( at, &fs->hints.nextFreeInode ); | < | ||
| 636 | at += whio_epfs_sizeof_id; | < | ||
| 637 | if( rc ) return rc; | < | ||
| 638 | < | |||
| 639 | rc = whio_epfs_decode_id( at, &fs->hints.maxEverUsedInode ); | 639 | rc = whio_epfs_decode_id( at, &fs->hints.maxEverUsedInode ); | |
| 640 | at += whio_epfs_sizeof_id; | 640 | at += whio_epfs_sizeof_id; | |
| 641 | if( rc ) return rc; | 641 | if( rc ) return rc; | |
| 642 | 642 | |||
| 643 | #if 0 | | | 643 | rc = whio_epfs_decode_id( at, &fs->hints.maxEverUsedBlock ); |
| 644 | rc = whio_epfs_decode_id( at, &fs->hints.nextFreeBlock ); | | | ||
| 645 | at += whio_epfs_sizeof_id; | 644 | at += whio_epfs_sizeof_id; | |
| 646 | if( rc ) return rc; | 645 | if( rc ) return rc; | |
| 647 | #endif | < | ||
| 648 | 646 | |||
| 649 | rc = whio_epfs_decode_id( at, &fs->hints.maxEverUsedBlock ); | | | 647 | rc = whio_epfs_decode_id( at, &fs->hints.freeInodeList ); |
| 650 | at += whio_epfs_sizeof_id; | 648 | at += whio_epfs_sizeof_id; | |
| 651 | if( rc ) return rc; | 649 | if( rc ) return rc; | |
| 652 | 650 | |||
| 653 | rc = whio_epfs_decode_id( at, &fs->hints.freeBlockList ); | 651 | rc = whio_epfs_decode_id( at, &fs->hints.freeBlockList ); | |
| 654 | at += whio_epfs_sizeof_id; | 652 | at += whio_epfs_sizeof_id; | |
| 7 hidden lines | ||||
| 662 | 660 | |||
| 663 | static int whio_epfs_inodes_table_write( whio_epfs * fs ) | 661 | static int whio_epfs_inodes_table_write( whio_epfs * fs ) | |
| 664 | { | 662 | { | |
| 665 | whio_epfs_inode ino = whio_epfs_inode_empty; | 663 | whio_epfs_inode ino = whio_epfs_inode_empty; | |
| 666 | int rc = 0; | 664 | int rc = 0; | |
| 667 | whio_size_t i; | | | 665 | whio_size_t i = 1; |
| 668 | for( i = 1; (!rc) && (i <= fs->fsopt.inodeCount); ++i ) | | | 666 | fs->hints.freeInodeList = i; |
| | | 667 | for( ; (!rc) && (i <= fs->fsopt.inodeCount); ++i ) | ||
| 669 | { | 668 | { | |
| 670 | ino.id = i; | 669 | ino.id = i; | |
| 671 | ino.nextFree = (i < fs->fsopt.inodeCount) ? (i+1) : 0; | 670 | ino.nextFree = (i < fs->fsopt.inodeCount) ? (i+1) : 0; | |
| > | 671 | ino.prevFree = i-1; | ||
| 672 | rc = whio_epfs_inode_flush( fs, &ino ); | 672 | rc = whio_epfs_inode_flush( fs, &ino ); | |
| 673 | } | 673 | } | |
| 674 | return rc; | 674 | return rc; | |
| 675 | } | 675 | } | |
| 676 | 676 | |||
| 130 hidden lines | ||||
| 807 | CHECKRC; | 807 | CHECKRC; | |
| 808 | #undef CHECKRC | 808 | #undef CHECKRC | |
| 809 | #undef RERR | 809 | #undef RERR | |
| 810 | if( ownsFS ) *fs_ = fs; | 810 | if( ownsFS ) *fs_ = fs; | |
| 811 | whio_epfs_apply_sopt( fs, sopt )/*ignoring error code - not critical.*/; | 811 | whio_epfs_apply_sopt( fs, sopt )/*ignoring error code - not critical.*/; | |
| > | 812 | whio_epfs_flush(fs); | ||
| 812 | return rc; | 813 | return rc; | |
| 813 | } | 814 | } | |
| 814 | 815 | |||
| 815 | int whio_epfs_mkfs2( whio_epfs ** fs_, whio_dev * store, whio_epfs_fsopt const * opt, bool takeStore ) | 816 | int whio_epfs_mkfs2( whio_epfs ** fs_, whio_dev * store, whio_epfs_fsopt const * opt, bool takeStore ) | |
| 816 | { | 817 | { | |
| 228 hidden lines | ||||
| 1045 | whio_epfs_inode ino = whio_epfs_inode_empty; | 1046 | whio_epfs_inode ino = whio_epfs_inode_empty; | |
| 1046 | int rc = whio_epfs_inode_read( fs, inodeID, &ino ); | 1047 | int rc = whio_epfs_inode_read( fs, inodeID, &ino ); | |
| 1047 | if( rc ) return rc; | 1048 | if( rc ) return rc; | |
| 1048 | if( ! whio_epfs_inode_is_used(&ino) ) return whio_rc.RangeError; | 1049 | if( ! whio_epfs_inode_is_used(&ino) ) return whio_rc.RangeError; | |
| 1049 | whio_epfs_id_t firstBlock = ino.firstBlock; | 1050 | whio_epfs_id_t firstBlock = ino.firstBlock; | |
| 1050 | whio_epfs_inode_set_used( &ino, false ); | < | ||
| 1051 | rc = whio_epfs_inode_flush( fs, &ino ); | < | ||
| 1052 | if( rc ) return rc; | < | ||
| 1053 | if( firstBlock ) | 1051 | if( firstBlock ) | |
| 1054 | { | 1052 | { | |
| 1055 | whio_epfs_block bl = whio_epfs_block_empty; | 1053 | whio_epfs_block bl = whio_epfs_block_empty; | |
| 1056 | rc = whio_epfs_block_read( fs, firstBlock, &bl ); | 1054 | rc = whio_epfs_block_read( fs, firstBlock, &bl ); | |
| 1057 | if( rc ) return rc; | 1055 | if( rc ) return rc; | |
| 4 hidden lines | ||||
| 1062 | 1060 | |||
| 1063 | We could fix such cases later if we stored the inode | 1061 | We could fix such cases later if we stored the inode | |
| 1064 | ID in the block. | 1062 | ID in the block. | |
| 1065 | */ | 1063 | */ | |
| 1066 | } | 1064 | } | |
| > | 1065 | if( 0 == rc ) | ||
| > | 1066 | { | ||
| > | 1067 | whio_epfs_inode_set_used( fs, &ino, false ); | ||
| > | 1068 | rc = whio_epfs_inode_flush( fs, &ino ); | ||
| > | 1069 | if( rc ) return rc; | ||
| > | 1070 | } | ||
| > | 1071 | /* FIXME? move this somewhere else? */ | ||
| > | 1072 | rc = whio_epfs_hints_write( fs ); | ||
| > | 1073 | |||
| 1067 | return rc; | 1074 | return rc; | |
| 1068 | } | 1075 | } | |
| 1069 | 1076 | |||
| 1070 | int whio_epfs_parse_id( char const * inp, bool allowExtraChars, whio_epfs_id_t * tgt ) | 1077 | int whio_epfs_parse_id( char const * inp, bool allowExtraChars, whio_epfs_id_t * tgt ) | |
| 1071 | //int whio_epfs_parse_id( char const * inp, whio_epfs_id_t * tgt, char const ** end ) | 1078 | //int whio_epfs_parse_id( char const * inp, whio_epfs_id_t * tgt, char const ** end ) | |
| 59 hidden lines | ||||
| 1131 | return rc; | 1138 | return rc; | |
| 1132 | } | 1139 | } | |
| 1133 | 1140 | |||
| 1134 | 1141 | |||
| 1135 | #undef MARKER | 1142 | #undef MARKER | |
Changes to pfs/test.c
| Old (4afcd569975d14f4) | New (ec49c1ff60aa1564) | |||
|---|---|---|---|---|
| 1 | /************************************************************************ | 1 | /************************************************************************ | |
| 2 | FAR FROM COMPLETE. | 2 | FAR FROM COMPLETE. | |
| 3 | 3 | |||
| 4 | This is a work-in-progress, porting over parts of the whefs API into | 4 | This is a work-in-progress, porting over parts of the whefs API into | |
| 5 | the whio API... | 5 | the whio API... | |
| 48 hidden lines | ||||
| 54 | @endcode | 54 | @endcode | |
| 55 | 55 | |||
| 56 | The address 0x4000300020003 is apparently bogus, but i don't know where it's coming from. | 56 | The address 0x4000300020003 is apparently bogus, but i don't know where it's coming from. | |
| 57 | */ | 57 | */ | |
| 58 | enum { AllocatorSize = | 58 | enum { AllocatorSize = | |
| 59 | //5000 only a very large EFS with lots of opened records would need this much | | | 59 | 5000 //only a very large EFS with lots of opened records would need this much |
| 60 | //2000 | 60 | //2000 | |
| 61 | //500 // works for small use cases on 32-bit, but not 64-bit. | 61 | //500 // works for small use cases on 32-bit, but not 64-bit. | |
| 62 | 0 // uses stdlib allocators | | | 62 | //0 // uses stdlib allocators |
| 63 | }; | 63 | }; | |
| 64 | static struct Application | 64 | static struct Application | |
| 65 | { | 65 | { | |
| 66 | whio_stream * cout; | 66 | whio_stream * cout; | |
| 67 | unsigned char buffer[AllocatorSize ? AllocatorSize : 1]; | 67 | unsigned char buffer[AllocatorSize ? AllocatorSize : 1]; | |
| 449 hidden lines | ||||
| 517 | SO(ThisApp.buffer); | 517 | SO(ThisApp.buffer); | |
| 518 | #undef SO | 518 | #undef SO | |
| 519 | MARKER("Done. rc=%d\n",rc); | 519 | MARKER("Done. rc=%d\n",rc); | |
| 520 | return rc; | 520 | return rc; | |
| 521 | } | 521 | } | |
Changes to pfs/touch.c
| Old (65b86d820e03e9aa) | New (2b41841b6e151714) | |||
|---|---|---|---|---|
| 1 | /************************************************************************ | 1 | /************************************************************************ | |
| 2 | A "touch"-like program for use with whio_epfs. | 2 | A "touch"-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 | |||
| 80 hidden lines | ||||
| 86 | APPERR("--no-create is in effect, so unused inode #%"WHIO_EPFS_ID_T_PFMT" cannot be touched.\n", | 86 | APPERR("--no-create is in effect, so unused inode #%"WHIO_EPFS_ID_T_PFMT" cannot be touched.\n", | |
| 87 | ino->id ); | 87 | ino->id ); | |
| 88 | return whio_rc.AccessError; | 88 | return whio_rc.AccessError; | |
| 89 | } | 89 | } | |
| 90 | // Create a zero-byte entry, like Unix touch. | 90 | // Create a zero-byte entry, like Unix touch. | |
| 91 | whio_epfs_inode_set_used( ino, true ); | | | 91 | whio_epfs_inode_set_used( EPFSApp.fs, ino, true ); |
| 92 | } | 92 | } | |
| 93 | rc = whio_epfs_inode_touch( ino, AppTouch.mtime ); | 93 | rc = whio_epfs_inode_touch( ino, AppTouch.mtime ); | |
| 94 | if( !rc ) | 94 | if( !rc ) | |
| 95 | { | 95 | { | |
| 96 | rc = whio_epfs_inode_flush( EPFSApp.fs, ino ); | 96 | rc = whio_epfs_inode_flush( EPFSApp.fs, ino ); | |
| 190 hidden lines | ||||
| 287 | return rc; | 287 | return rc; | |
| 288 | } | 288 | } | |
| 289 | 289 | |||
| 290 | #undef TOUCH_DEFAULT_STRPFMT | 290 | #undef TOUCH_DEFAULT_STRPFMT | |
| 291 | #undef TOUCH_DEFAULT_STRPFMT_HUMAN | 291 | #undef TOUCH_DEFAULT_STRPFMT_HUMAN | |
Changes to pfs/whio_epfs_internal.h
| Old (43ec21d3d412a462) | New (59f4708000a3b808) | |||
|---|---|---|---|---|
| 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 | |||
| 52 hidden lines | ||||
| 58 | 58 | |||
| 59 | Sets or unsets the is-used flag for ino. Returns 0 on success, | 59 | Sets or unsets the is-used flag for ino. Returns 0 on success, | |
| 60 | but it can only fail if !ino. If !u then ino is zeroed out | 60 | but it can only fail if !ino. If !u then ino is zeroed out | |
| 61 | except for its id. | 61 | except for its id. | |
| 62 | 62 | |||
| 63 | If (u && !ino->mtime) then whio_epfs_inode_touch(ino) is also | | | 63 | If (u && !ino->mtime) then whio_epfs_inode_touch(ino) is also |
| 64 | called. | | | 64 | called. |
| 65 | 65 | |||
| 66 | Does not flush the inode to storage. | | | 66 | This function may have to flush ino to storage in order to update |
| | | 67 | the free-inode list. | ||
| | | 68 | |||
| | | 69 | Returns 0 on success. If an error comes from the free-list handling | ||
| | | 70 | part then the state of the free list is undefined and we're in all | ||
| | | 71 | sorts of crap from then on out. Possibly. Our we might just get | ||
| | | 72 | device-full errors when trying to allocate new inodes even though | ||
| | | 73 | there are free items. | ||
| 67 | */ | 74 | */ | |
| 68 | int whio_epfs_inode_set_used( whio_epfs_inode * ino, bool u ); | | | 75 | int whio_epfs_inode_set_used( whio_epfs * fs, whio_epfs_inode * ino, bool u ); |
| 69 | 76 | |||
| 70 | /** @internal | 77 | /** @internal | |
| 71 | 78 | |||
| 72 | Encodes ino to dest, which must be at least | 79 | Encodes ino to dest, which must be at least | |
| 73 | whio_epfs_sizeof_inode bytes long. Returns | 80 | whio_epfs_sizeof_inode bytes long. Returns | |
| 71 hidden lines | ||||
| 145 | whio_client_data * whio_epfs_client_data( whio_epfs * fs ); | 152 | whio_client_data * whio_epfs_client_data( whio_epfs * fs ); | |
| 146 | 153 | |||
| 147 | /** @internal | 154 | /** @internal | |
| 148 | 155 | |||
| 149 | Searches the inode table for the next free element. On success | 156 | Searches the inode table for the next free element. On success | |
| 150 | it returns 0 and dest is populated with the inode data. If | | | 157 | it returns 0 and dest is populated with a copy of the inode |
| 151 | markAsUsed is true then the record is marked as used and | | | 158 | data. If markAsUsed is true then the record is marked as used |
| 152 | flushed to disk, otherwise the same record might be returned | | | 159 | and flushed to disk, otherwise the same record might be |
| 153 | again on the next call to this function. | | | 160 | returned again on the next call to this function. |
| 154 | 161 | |||
| 155 | Error conditions include: | 162 | Error conditions include: | |
| 156 | 163 | |||
| 157 | - !fs or !dest (whio_rc.ArgError). | 164 | - !fs or !dest (whio_rc.ArgError). | |
| 158 | - No more free inodes (whio_rc.DeviceFullError). | 165 | - No more free inodes (whio_rc.DeviceFullError). | |
| 159 | - Any potential errors via reading or writing the inode. | 166 | - Any potential errors via reading or writing the inode. | |
| 160 | - There's a whio_rc.RangeError for one theoretically impossible case. | | | 167 | - There's a whio_rc.RangeError for one theoretically impossible case.\ |
| | | 168 | - markAsUsed is true but fs is opened for read-only more: whio_rc.AccessError. | ||
| 161 | 169 | |||
| 162 | In principal this is an O(N) operation | | | 170 | |
| 163 | (N=fs->fsopt.inodeCount), but a cached number | | | 171 | As of 20100310, this is a essentially an O(1) operation if we |
| 164 | (fs->hints.nextFreeInode) allow us to cut this down to O(1) | | | 172 | discount the i/o it must potentially do to update the inode |
| 165 | for many cases, and O(N) worst-case, and be O(N) with a | | | 173 | free-list. If markAsUsed is true it must read, at most, 2 |
| 166 | somewhat smaller N for some high-use cases (where | | | 174 | additional inodes, update their free-list links, and flush |
| 167 | inodes are often unlinked and later re-used). | | | 175 | them. The ids (and therefore on-storage positions) of all |
| | | 176 | inodes involved are known in advance, so this routine has to | ||
| | | 177 | do no search-related i/o. Note that such re-linking pays no | ||
| | | 178 | attention whatsoever to whether an inode or its neighbors are | ||
| | | 179 | opened (and therefore have their inode state cached somewhere | ||
| | | 180 | in memory). If the API is used properly then by the time an | ||
| | | 181 | inode can be opened, all links to/from the inode and the | ||
| | | 182 | free-list are severed. | ||
| 168 | */ | 183 | */ | |
| 169 | int whio_epfs_inode_next_free( whio_epfs * fs, whio_epfs_inode * dest, bool markAsUsed ); | 184 | int whio_epfs_inode_next_free( whio_epfs * fs, whio_epfs_inode * dest, bool markAsUsed ); | |
| 170 | 185 | |||
| 171 | /** @internal | 186 | /** @internal | |
| 172 | 187 | |||
| 865 hidden lines | ||||
| 1038 | #ifdef __cplusplus | 1053 | #ifdef __cplusplus | |
| 1039 | } /* extern "C" */ | 1054 | } /* extern "C" */ | |
| 1040 | #endif | 1055 | #endif | |
| 1041 | 1056 | |||
| 1042 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_INTERNAL_H_INCLUDED */ | 1057 | #endif /* WANDERINGHORSE_NET_WHIO_EPFS_INTERNAL_H_INCLUDED */ | |