forked from Imagelibrary/littlefs
Compare commits
3 Commits
link-pico-
...
fix-expand
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11b036cc6c | ||
|
|
25ee90fdf1 | ||
|
|
a60a986c9c |
7
SPEC.md
7
SPEC.md
@@ -441,9 +441,10 @@ Superblock fields:
|
||||
|
||||
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
|
||||
as be the first entry written to the block. This means that the superblock
|
||||
entry can be read from a device using offsets alone.
|
||||
The superblock must always be the first entry (id 0) in the metadata pair, and
|
||||
the name tag must always be the first tag in the metadata pair. This makes it
|
||||
so that the magic string "littlefs" will always reside at offset=8 in a valid
|
||||
littlefs superblock.
|
||||
|
||||
---
|
||||
#### `0x2xx` LFS_TYPE_STRUCT
|
||||
|
||||
15
lfs.c
15
lfs.c
@@ -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
|
||||
LFS_WARN("Unable to expand superblock");
|
||||
} 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) {
|
||||
// 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);
|
||||
if (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
|
||||
// gstate so we know we need to rewrite the superblock before
|
||||
// the first write
|
||||
bool needssuperblock = false;
|
||||
if (minor_version < lfs_fs_disk_version_minor(lfs)) {
|
||||
LFS_DEBUG("Found older minor version "
|
||||
"v%"PRIu16".%"PRIu16" < v%"PRIu16".%"PRIu16,
|
||||
@@ -4473,10 +4477,11 @@ static int lfs_mount_(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
minor_version,
|
||||
lfs_fs_disk_version_major(lfs),
|
||||
lfs_fs_disk_version_minor(lfs));
|
||||
// note this bit is reserved on disk, so fetching more gstate
|
||||
// will not interfere here
|
||||
lfs_fs_prepsuperblock(lfs, true);
|
||||
needssuperblock = true;
|
||||
}
|
||||
// note this bit is reserved on disk, so fetching more gstate
|
||||
// will not interfere here
|
||||
lfs_fs_prepsuperblock(lfs, needssuperblock);
|
||||
|
||||
// check superblock configuration
|
||||
if (superblock.name_max) {
|
||||
|
||||
@@ -14,6 +14,24 @@ code = '''
|
||||
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
|
||||
[cases.test_superblocks_mount_unknown_block_count]
|
||||
code = '''
|
||||
@@ -28,7 +46,6 @@ code = '''
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
|
||||
# reentrant format
|
||||
[cases.test_superblocks_reentrant_format]
|
||||
reentrant = true
|
||||
@@ -135,6 +152,39 @@ code = '''
|
||||
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
|
||||
[cases.test_superblocks_expand_power_cycle]
|
||||
defines.BLOCK_CYCLES = [32, 33, 1]
|
||||
@@ -221,6 +271,7 @@ code = '''
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
|
||||
# mount with unknown block_count
|
||||
[cases.test_superblocks_unknown_blocks]
|
||||
code = '''
|
||||
|
||||
Reference in New Issue
Block a user