diff options
author | Christopher Haster <chaster@utexas.edu> | 2018-09-12 09:50:21 +0300 |
---|---|---|
committer | Christopher Haster <chaster@utexas.edu> | 2018-10-18 18:00:49 +0300 |
commit | cf87ba537598d13b0884751bee8d4ad71e782450 (patch) | |
tree | 755b9ea3d11d78761bd5e9344ccfa834c6cfe9ca | |
parent | 7bacf9b1e01b9bf56fec9fc481e2078c4424c2d7 (diff) |
Combined superblock scan and fetch of xored-globals during mount
Conceptually these are two separate operations. However, they are both
only needed during mount, both require iteration over the linked-list of
metadata-pairs, and both are independent from each other.
Combining these into one gives us a nice code savings.
Additionally, this greatly simplifies the lookup of the root directory.
Initially we used a flag to indicate which superblock was root, since we
didn't want to fetch more pairs than we needed to. But since we're going
to fetch all metadata-pairs anyways, we can just use the last superblock
we find as the indicator of our root directory.
-rw-r--r-- | lfs.c | 153 | ||||
-rw-r--r-- | lfs.h | 8 | ||||
-rwxr-xr-x | tests/debug.py | 1 |
3 files changed, 78 insertions, 84 deletions
@@ -3116,7 +3116,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { lfs_superblock_tole32(&superblock); err = lfs_dir_commit(lfs, &root, - LFS_MKATTR(LFS_TYPE_ROOT, 0, &superblock, sizeof(superblock), + LFS_MKATTR(LFS_TYPE_SUPERBLOCK, 0, &superblock, sizeof(superblock), NULL)); if (err) { goto cleanup; @@ -3139,97 +3139,94 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { return err; } - // find root/superblock - lfs_mdir_t root; - lfs_superblock_t superblock; - lfs_stag_t tag = lfs_dir_findmatch(lfs, - &root, (const lfs_block_t[2]){0, 1}, false, 0x7fc00000, - LFS_MKTAG(LFS_TYPE_ROOT, 0, 8), - lfs_dir_find_match, &(struct lfs_dir_find_match){ - lfs, "littlefs", 8}); - if (tag < 0) { - err = tag; - goto cleanup; - } + // scan directory blocks for superblock and any global updates + lfs_mdir_t dir = {.tail = {0, 1}}; + while (!lfs_pair_isnull(dir.tail)) { + // fetch next block in tail list + lfs_stag_t res = lfs_dir_fetchmatch(lfs, &dir, dir.tail, 0x7fc00000, + LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8), + lfs_dir_find_match, &(struct lfs_dir_find_match){ + lfs, "littlefs", 8}); + if (res < 0) { + err = res; + goto cleanup; + } - lfs_stag_t res = lfs_dir_get(lfs, &root, 0x7f800000, - LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)), - &superblock); - if (res < 0) { - err = res; - goto cleanup; - } - lfs_superblock_fromle32(&superblock); + // has superblock? + if (res) { + // update root + lfs->root[0] = dir.pair[0]; + lfs->root[1] = dir.pair[1]; + + // grab superblock + lfs_superblock_t superblock; + res = lfs_dir_get(lfs, &dir, 0x7f800000, + LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)), + &superblock); + if (res < 0) { + err = res; + goto cleanup; + } + lfs_superblock_fromle32(&superblock); - lfs->root[0] = root.pair[0]; - lfs->root[1] = root.pair[1]; + // check version + uint16_t major_version = (0xffff & (superblock.version >> 16)); + uint16_t minor_version = (0xffff & (superblock.version >> 0)); + if ((major_version != LFS_DISK_VERSION_MAJOR || + minor_version > LFS_DISK_VERSION_MINOR)) { + LFS_ERROR("Invalid version %"PRIu32".%"PRIu32, + major_version, minor_version); + err = LFS_ERR_INVAL; + goto cleanup; + } - // check version - uint16_t major_version = (0xffff & (superblock.version >> 16)); - uint16_t minor_version = (0xffff & (superblock.version >> 0)); - if ((major_version != LFS_DISK_VERSION_MAJOR || - minor_version > LFS_DISK_VERSION_MINOR)) { - LFS_ERROR("Invalid version %"PRIu32".%"PRIu32, - major_version, minor_version); - err = LFS_ERR_INVAL; - goto cleanup; - } + // check superblock configuration + if (superblock.attr_max) { + if (superblock.attr_max > lfs->attr_max) { + LFS_ERROR("Unsupported attr_max (%"PRIu32" > %"PRIu32")", + superblock.attr_max, lfs->attr_max); + err = LFS_ERR_INVAL; + goto cleanup; + } - // check superblock configuration - if (superblock.attr_max) { - if (superblock.attr_max > lfs->attr_max) { - LFS_ERROR("Unsupported attr_max (%"PRIu32" > %"PRIu32")", - superblock.attr_max, lfs->attr_max); - err = LFS_ERR_INVAL; - goto cleanup; - } + lfs->attr_max = superblock.attr_max; + } - lfs->attr_max = superblock.attr_max; - } + if (superblock.name_max) { + if (superblock.name_max > lfs->name_max) { + LFS_ERROR("Unsupported name_max (%"PRIu32" > %"PRIu32")", + superblock.name_max, lfs->name_max); + err = LFS_ERR_INVAL; + goto cleanup; + } - if (superblock.name_max) { - if (superblock.name_max > lfs->name_max) { - LFS_ERROR("Unsupported name_max (%"PRIu32" > %"PRIu32")", - superblock.name_max, lfs->name_max); - err = LFS_ERR_INVAL; - goto cleanup; - } + lfs->name_max = superblock.name_max; + } - lfs->name_max = superblock.name_max; - } + if (superblock.inline_max) { + if (superblock.inline_max > lfs->inline_max) { + LFS_ERROR("Unsupported inline_max (%"PRIu32" > %"PRIu32")", + superblock.inline_max, lfs->inline_max); + err = LFS_ERR_INVAL; + goto cleanup; + } - if (superblock.inline_max) { - if (superblock.inline_max > lfs->inline_max) { - LFS_ERROR("Unsupported inline_max (%"PRIu32" > %"PRIu32")", - superblock.inline_max, lfs->inline_max); - err = LFS_ERR_INVAL; - goto cleanup; + lfs->inline_max = superblock.inline_max; + } } - lfs->inline_max = superblock.inline_max; - } - - // scan for any global updates - lfs_mdir_t dir = {.tail = {0, 1}}; - while (!lfs_pair_isnull(dir.tail)) { - res = lfs_dir_fetchmatch(lfs, &dir, dir.tail, 0x7c000000, - LFS_MKTAG(LFS_TYPE_GLOBALS, 0, 10), NULL, NULL); - if (res < 0) { - err = LFS_ERR_INVAL; + // has globals? + lfs_global_t locals; + res = lfs_dir_get(lfs, &dir, 0x7c000000, + LFS_MKTAG(LFS_TYPE_GLOBALS, 0, 10), &locals); + if (res < 0 && res != LFS_ERR_NOENT) { + err = res; goto cleanup; } - if (res) { - lfs_global_t locals; - res = lfs_dir_get(lfs, &dir, 0x7c000000, - LFS_MKTAG(LFS_TYPE_GLOBALS, 0, 10), &locals); - if (res < 0) { - err = res; - goto cleanup; - } + if (res != LFS_ERR_NOENT) { locals.l.deorphaned = (lfs_tag_type(res) & 1); - - // xor together indirect deletes + // xor together to find resulting globals lfs_global_xor(&lfs->locals, &locals); } } @@ -94,27 +94,25 @@ enum lfs_type { // internally used types LFS_TYPE_USER = 0x100, - LFS_TYPE_SUPERBLOCK = 0x001, - LFS_TYPE_ROOT = 0x000, LFS_TYPE_NAME = 0x000, LFS_TYPE_DELETE = 0x020, LFS_TYPE_STRUCT = 0x040, - LFS_TYPE_GLOBALS = 0x0e0, LFS_TYPE_TAIL = 0x080, LFS_TYPE_SOFTTAIL = 0x080, LFS_TYPE_HARDTAIL = 0x081, LFS_TYPE_CRC = 0x0a0, + LFS_TYPE_SUPERBLOCK = 0x001, + LFS_TYPE_GLOBALS = 0x0e0, LFS_TYPE_DIRSTRUCT = 0x040, LFS_TYPE_INLINESTRUCT = 0x041, LFS_TYPE_CTZSTRUCT = 0x042, // internal chip sources - LFS_FROM_REGION = 0x000, + LFS_FROM_MEM = 0x000, LFS_FROM_DISK = 0x200, LFS_FROM_MOVE = 0x0c1, LFS_FROM_USERATTRS = 0x0c2, - LFS_FROM_SUPERBLOCK = 0x0c3, }; // File open flags diff --git a/tests/debug.py b/tests/debug.py index 3c975c8..2fcc05a 100755 --- a/tests/debug.py +++ b/tests/debug.py @@ -7,7 +7,6 @@ TYPES = { (0x1ff, 0x002): 'reg', (0x1ff, 0x003): 'dir', (0x1ff, 0x001): 'superblock', - (0x1ff, 0x000): 'root', (0x1ff, 0x020): 'delete', (0x1f0, 0x0e0): 'globals', (0x1ff, 0x080): 'tail soft', |