Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/littlefs-project/littlefs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Haster <chaster@utexas.edu>2018-09-12 09:50:21 +0300
committerChristopher Haster <chaster@utexas.edu>2018-10-18 18:00:49 +0300
commitcf87ba537598d13b0884751bee8d4ad71e782450 (patch)
tree755b9ea3d11d78761bd5e9344ccfa834c6cfe9ca
parent7bacf9b1e01b9bf56fec9fc481e2078c4424c2d7 (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.c153
-rw-r--r--lfs.h8
-rwxr-xr-xtests/debug.py1
3 files changed, 78 insertions, 84 deletions
diff --git a/lfs.c b/lfs.c
index 45c52fd..592f980 100644
--- a/lfs.c
+++ b/lfs.c
@@ -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);
}
}
diff --git a/lfs.h b/lfs.h
index 090041c..5acb484 100644
--- a/lfs.h
+++ b/lfs.h
@@ -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',