Merge pull request #959 from littlefs-project/fix-expanded-magic
Duplicate the superblock entry during superblock expansion, fix missing magic
This commit is contained in:
@@ -441,9 +441,10 @@ Superblock fields:
|
|||||||
|
|
||||||
7. **Attr max (32-bits)** - Maximum size of file attributes in bytes.
|
7. **Attr max (32-bits)** - Maximum size of file attributes in bytes.
|
||||||
|
|
||||||
The superblock must always be the first entry (id 0) in a metadata pair as well
|
The superblock must always be the first entry (id 0) in the metadata pair, and
|
||||||
as be the first entry written to the block. This means that the superblock
|
the name tag must always be the first tag in the metadata pair. This makes it
|
||||||
entry can be read from a device using offsets alone.
|
so that the magic string "littlefs" will always reside at offset=8 in a valid
|
||||||
|
littlefs superblock.
|
||||||
|
|
||||||
---
|
---
|
||||||
#### `0x2xx` LFS_TYPE_STRUCT
|
#### `0x2xx` LFS_TYPE_STRUCT
|
||||||
|
|||||||
@@ -2191,7 +2191,8 @@ static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,
|
|||||||
// we can do, we'll error later if we've become frozen
|
// we can do, we'll error later if we've become frozen
|
||||||
LFS_WARN("Unable to expand superblock");
|
LFS_WARN("Unable to expand superblock");
|
||||||
} else {
|
} else {
|
||||||
end = begin;
|
// duplicate the superblock entry into the new superblock
|
||||||
|
end = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2358,7 +2359,9 @@ fixmlist:;
|
|||||||
|
|
||||||
while (d->id >= d->m.count && d->m.split) {
|
while (d->id >= d->m.count && d->m.split) {
|
||||||
// we split and id is on tail now
|
// we split and id is on tail now
|
||||||
d->id -= d->m.count;
|
if (lfs_pair_cmp(d->m.tail, lfs->root) != 0) {
|
||||||
|
d->id -= d->m.count;
|
||||||
|
}
|
||||||
int err = lfs_dir_fetch(lfs, &d->m, d->m.tail);
|
int err = lfs_dir_fetch(lfs, &d->m, d->m.tail);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -4466,6 +4469,7 @@ static int lfs_mount_(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
// found older minor version? set an in-device only bit in the
|
// found older minor version? set an in-device only bit in the
|
||||||
// gstate so we know we need to rewrite the superblock before
|
// gstate so we know we need to rewrite the superblock before
|
||||||
// the first write
|
// the first write
|
||||||
|
bool needssuperblock = false;
|
||||||
if (minor_version < lfs_fs_disk_version_minor(lfs)) {
|
if (minor_version < lfs_fs_disk_version_minor(lfs)) {
|
||||||
LFS_DEBUG("Found older minor version "
|
LFS_DEBUG("Found older minor version "
|
||||||
"v%"PRIu16".%"PRIu16" < v%"PRIu16".%"PRIu16,
|
"v%"PRIu16".%"PRIu16" < v%"PRIu16".%"PRIu16,
|
||||||
@@ -4473,10 +4477,11 @@ static int lfs_mount_(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
minor_version,
|
minor_version,
|
||||||
lfs_fs_disk_version_major(lfs),
|
lfs_fs_disk_version_major(lfs),
|
||||||
lfs_fs_disk_version_minor(lfs));
|
lfs_fs_disk_version_minor(lfs));
|
||||||
// note this bit is reserved on disk, so fetching more gstate
|
needssuperblock = true;
|
||||||
// will not interfere here
|
|
||||||
lfs_fs_prepsuperblock(lfs, true);
|
|
||||||
}
|
}
|
||||||
|
// note this bit is reserved on disk, so fetching more gstate
|
||||||
|
// will not interfere here
|
||||||
|
lfs_fs_prepsuperblock(lfs, needssuperblock);
|
||||||
|
|
||||||
// check superblock configuration
|
// check superblock configuration
|
||||||
if (superblock.name_max) {
|
if (superblock.name_max) {
|
||||||
|
|||||||
@@ -14,6 +14,24 @@ code = '''
|
|||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# make sure the magic string "littlefs" is always at offset=8
|
||||||
|
[cases.test_superblocks_magic]
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfs_format(&lfs, cfg) => 0;
|
||||||
|
|
||||||
|
// check our magic string
|
||||||
|
//
|
||||||
|
// note if we lose power we may not have the magic string in both blocks!
|
||||||
|
// but we don't lose power in this test so we can assert the magic string
|
||||||
|
// is present in both
|
||||||
|
uint8_t magic[lfs_max(16, READ_SIZE)];
|
||||||
|
cfg->read(cfg, 0, 0, magic, lfs_max(16, READ_SIZE)) => 0;
|
||||||
|
assert(memcmp(&magic[8], "littlefs", 8) == 0);
|
||||||
|
cfg->read(cfg, 1, 0, magic, lfs_max(16, READ_SIZE)) => 0;
|
||||||
|
assert(memcmp(&magic[8], "littlefs", 8) == 0);
|
||||||
|
'''
|
||||||
|
|
||||||
# mount/unmount from interpretting a previous superblock block_count
|
# mount/unmount from interpretting a previous superblock block_count
|
||||||
[cases.test_superblocks_mount_unknown_block_count]
|
[cases.test_superblocks_mount_unknown_block_count]
|
||||||
code = '''
|
code = '''
|
||||||
@@ -28,7 +46,6 @@ code = '''
|
|||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
# reentrant format
|
# reentrant format
|
||||||
[cases.test_superblocks_reentrant_format]
|
[cases.test_superblocks_reentrant_format]
|
||||||
reentrant = true
|
reentrant = true
|
||||||
@@ -135,6 +152,39 @@ code = '''
|
|||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# make sure the magic string "littlefs" is always at offset=8
|
||||||
|
[cases.test_superblocks_magic_expand]
|
||||||
|
defines.BLOCK_CYCLES = [32, 33, 1]
|
||||||
|
defines.N = [10, 100, 1000]
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfs_format(&lfs, cfg) => 0;
|
||||||
|
lfs_mount(&lfs, cfg) => 0;
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
lfs_file_t file;
|
||||||
|
lfs_file_open(&lfs, &file, "dummy",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
lfs_file_close(&lfs, &file) => 0;
|
||||||
|
struct lfs_info info;
|
||||||
|
lfs_stat(&lfs, "dummy", &info) => 0;
|
||||||
|
assert(strcmp(info.name, "dummy") == 0);
|
||||||
|
assert(info.type == LFS_TYPE_REG);
|
||||||
|
lfs_remove(&lfs, "dummy") => 0;
|
||||||
|
}
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// check our magic string
|
||||||
|
//
|
||||||
|
// note if we lose power we may not have the magic string in both blocks!
|
||||||
|
// but we don't lose power in this test so we can assert the magic string
|
||||||
|
// is present in both
|
||||||
|
uint8_t magic[lfs_max(16, READ_SIZE)];
|
||||||
|
cfg->read(cfg, 0, 0, magic, lfs_max(16, READ_SIZE)) => 0;
|
||||||
|
assert(memcmp(&magic[8], "littlefs", 8) == 0);
|
||||||
|
cfg->read(cfg, 1, 0, magic, lfs_max(16, READ_SIZE)) => 0;
|
||||||
|
assert(memcmp(&magic[8], "littlefs", 8) == 0);
|
||||||
|
'''
|
||||||
|
|
||||||
# expanding superblock with power cycle
|
# expanding superblock with power cycle
|
||||||
[cases.test_superblocks_expand_power_cycle]
|
[cases.test_superblocks_expand_power_cycle]
|
||||||
defines.BLOCK_CYCLES = [32, 33, 1]
|
defines.BLOCK_CYCLES = [32, 33, 1]
|
||||||
@@ -221,6 +271,7 @@ code = '''
|
|||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
# mount with unknown block_count
|
# mount with unknown block_count
|
||||||
[cases.test_superblocks_unknown_blocks]
|
[cases.test_superblocks_unknown_blocks]
|
||||||
code = '''
|
code = '''
|
||||||
|
|||||||
Reference in New Issue
Block a user