mirror of
https://github.com/littlefs-project/littlefs.git
synced 2025-11-16 12:34:34 +00:00
Compare commits
9 Commits
v2.9.2
...
fix-trace-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac207586ba | ||
|
|
d01280e649 | ||
|
|
6e52140d51 | ||
|
|
0bbb8bc88b | ||
|
|
78082336e7 | ||
|
|
8336ecd203 | ||
|
|
11b036cc6c | ||
|
|
25ee90fdf1 | ||
|
|
a60a986c9c |
38
README.md
38
README.md
@@ -231,11 +231,25 @@ License Identifiers that are here available: http://spdx.org/licenses/
|
||||
to use littlefs in a Rust-friendly API, reaping the benefits of Rust's memory
|
||||
safety and other guarantees.
|
||||
|
||||
- [nim-littlefs] - A Nim wrapper and API for littlefs. Includes a fuse
|
||||
implementation based on [littlefs-fuse]
|
||||
|
||||
- [chamelon] - A pure-OCaml implementation of (most of) littlefs, designed for
|
||||
use with the MirageOS library operating system project. It is interoperable
|
||||
with the reference implementation, with some caveats.
|
||||
|
||||
- [littlefs-disk-img-viewer] - A memory-efficient web application for viewing
|
||||
littlefs disk images in your web browser.
|
||||
|
||||
- [mklfs] - A command line tool built by the [Lua RTOS] guys for making
|
||||
littlefs images from a host PC. Supports Windows, Mac OS, and Linux.
|
||||
- [mklfs] - A command line tool for creating littlefs images. Used in the Lua
|
||||
RTOS ecosystem.
|
||||
|
||||
- [mklittlefs] - A command line tool for creating littlefs images. Used in the
|
||||
ESP8266 and RP2040 ecosystem.
|
||||
|
||||
- [pico-littlefs-usb] - An interface for littlefs that emulates a FAT12
|
||||
filesystem over USB. Allows mounting littlefs on a host PC without additional
|
||||
drivers.
|
||||
|
||||
- [Mbed OS] - The easiest way to get started with littlefs is to jump into Mbed
|
||||
which already has block device drivers for most forms of embedded storage.
|
||||
@@ -254,27 +268,21 @@ License Identifiers that are here available: http://spdx.org/licenses/
|
||||
for microcontroller-scale devices. Due to limitations of FAT it can't provide
|
||||
power-loss resilience, but it does allow easy interop with PCs.
|
||||
|
||||
- [chamelon] - A pure-OCaml implementation of (most of) littlefs, designed for
|
||||
use with the MirageOS library operating system project. It is interoperable
|
||||
with the reference implementation, with some caveats.
|
||||
|
||||
- [nim-littlefs] - A Nim wrapper and API for littlefs. Includes a fuse
|
||||
implementation based on [littlefs-fuse]
|
||||
|
||||
[BSD-3-Clause]: https://spdx.org/licenses/BSD-3-Clause.html
|
||||
[littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer
|
||||
[littlefs-fuse]: https://github.com/geky/littlefs-fuse
|
||||
[FUSE]: https://github.com/libfuse/libfuse
|
||||
[littlefs-js]: https://github.com/geky/littlefs-js
|
||||
[littlefs-js-demo]:http://littlefs.geky.net/demo.html
|
||||
[littlefs-python]: https://pypi.org/project/littlefs-python/
|
||||
[littlefs2-rust]: https://crates.io/crates/littlefs2
|
||||
[nim-littlefs]: https://github.com/Graveflo/nim-littlefs
|
||||
[chamelon]: https://github.com/yomimono/chamelon
|
||||
[littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer
|
||||
[mklfs]: https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src
|
||||
[Lua RTOS]: https://github.com/whitecatboard/Lua-RTOS-ESP32
|
||||
[mklittlefs]: https://github.com/earlephilhower/mklittlefs
|
||||
[pico-littlefs-usb]: https://github.com/oyama/pico-littlefs-usb
|
||||
[Mbed OS]: https://github.com/armmbed/mbed-os
|
||||
[LittleFileSystem]: https://os.mbed.com/docs/mbed-os/latest/apis/littlefilesystem.html
|
||||
[SPIFFS]: https://github.com/pellepl/spiffs
|
||||
[Dhara]: https://github.com/dlbeer/dhara
|
||||
[ChaN's FatFs]: http://elm-chan.org/fsw/ff/00index_e.html
|
||||
[littlefs-python]: https://pypi.org/project/littlefs-python/
|
||||
[littlefs2-rust]: https://crates.io/crates/littlefs2
|
||||
[chamelon]: https://github.com/yomimono/chamelon
|
||||
[nim-littlefs]: https://github.com/Graveflo/nim-littlefs
|
||||
|
||||
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
|
||||
|
||||
25
lfs.c
25
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) {
|
||||
@@ -5885,7 +5890,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
|
||||
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
|
||||
".block_size=%"PRIu32", .block_count=%"PRIu32", "
|
||||
".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
|
||||
".block_cycles=%"PRId32", .cache_size=%"PRIu32", "
|
||||
".lookahead_size=%"PRIu32", .read_buffer=%p, "
|
||||
".prog_buffer=%p, .lookahead_buffer=%p, "
|
||||
".name_max=%"PRIu32", .file_max=%"PRIu32", "
|
||||
@@ -5915,7 +5920,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
|
||||
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
|
||||
".block_size=%"PRIu32", .block_count=%"PRIu32", "
|
||||
".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
|
||||
".block_cycles=%"PRId32", .cache_size=%"PRIu32", "
|
||||
".lookahead_size=%"PRIu32", .read_buffer=%p, "
|
||||
".prog_buffer=%p, .lookahead_buffer=%p, "
|
||||
".name_max=%"PRIu32", .file_max=%"PRIu32", "
|
||||
@@ -6052,7 +6057,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) {
|
||||
return err;
|
||||
}
|
||||
LFS_TRACE("lfs_file_open(%p, %p, \"%s\", %x)",
|
||||
(void*)lfs, (void*)file, path, flags);
|
||||
(void*)lfs, (void*)file, path, (unsigned)flags);
|
||||
LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
err = lfs_file_open_(lfs, file, path, flags);
|
||||
@@ -6072,7 +6077,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
|
||||
}
|
||||
LFS_TRACE("lfs_file_opencfg(%p, %p, \"%s\", %x, %p {"
|
||||
".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})",
|
||||
(void*)lfs, (void*)file, path, flags,
|
||||
(void*)lfs, (void*)file, path, (unsigned)flags,
|
||||
(void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);
|
||||
LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
@@ -6434,7 +6439,7 @@ int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
|
||||
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
|
||||
".block_size=%"PRIu32", .block_count=%"PRIu32", "
|
||||
".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
|
||||
".block_cycles=%"PRId32", .cache_size=%"PRIu32", "
|
||||
".lookahead_size=%"PRIu32", .read_buffer=%p, "
|
||||
".prog_buffer=%p, .lookahead_buffer=%p, "
|
||||
".name_max=%"PRIu32", .file_max=%"PRIu32", "
|
||||
|
||||
@@ -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