Skip to content

Commit 74006f3

Browse files
committed
Squashed 'littlefs/' changes from 68d28b5..d01280e
d01280e Merge pull request #968 from littlefs-project/link-pico-littlefs-usb 6e52140 Merge pull request #959 from littlefs-project/fix-expanded-magic 0bbb8bc Reorganized external project links a bit 7808233 Added a link to mklittlefs 8336ecd Added a link to pico-littlefs-usb (FAT12 emulation) 11b036c Prevented unnecessary superblock rewrites if old version in superblock chain 25ee90f Clarified what is accessible at specific superblock offsets in SPEC.md a60a986 Duplicate the superblock entry during superblock expansion git-subtree-dir: littlefs git-subtree-split: d01280e64934a09ba16cac60cf9d3a37e228bb66
1 parent 38112db commit 74006f3

File tree

4 files changed

+89
-24
lines changed

4 files changed

+89
-24
lines changed

README.md

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,25 @@ License Identifiers that are here available: http://spdx.org/licenses/
231231
to use littlefs in a Rust-friendly API, reaping the benefits of Rust's memory
232232
safety and other guarantees.
233233

234+
- [nim-littlefs] - A Nim wrapper and API for littlefs. Includes a fuse
235+
implementation based on [littlefs-fuse]
236+
237+
- [chamelon] - A pure-OCaml implementation of (most of) littlefs, designed for
238+
use with the MirageOS library operating system project. It is interoperable
239+
with the reference implementation, with some caveats.
240+
234241
- [littlefs-disk-img-viewer] - A memory-efficient web application for viewing
235242
littlefs disk images in your web browser.
236243

237-
- [mklfs] - A command line tool built by the [Lua RTOS] guys for making
238-
littlefs images from a host PC. Supports Windows, Mac OS, and Linux.
244+
- [mklfs] - A command line tool for creating littlefs images. Used in the Lua
245+
RTOS ecosystem.
246+
247+
- [mklittlefs] - A command line tool for creating littlefs images. Used in the
248+
ESP8266 and RP2040 ecosystem.
249+
250+
- [pico-littlefs-usb] - An interface for littlefs that emulates a FAT12
251+
filesystem over USB. Allows mounting littlefs on a host PC without additional
252+
drivers.
239253

240254
- [Mbed OS] - The easiest way to get started with littlefs is to jump into Mbed
241255
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/
254268
for microcontroller-scale devices. Due to limitations of FAT it can't provide
255269
power-loss resilience, but it does allow easy interop with PCs.
256270

257-
- [chamelon] - A pure-OCaml implementation of (most of) littlefs, designed for
258-
use with the MirageOS library operating system project. It is interoperable
259-
with the reference implementation, with some caveats.
260-
261-
- [nim-littlefs] - A Nim wrapper and API for littlefs. Includes a fuse
262-
implementation based on [littlefs-fuse]
263-
264271
[BSD-3-Clause]: https://spdx.org/licenses/BSD-3-Clause.html
265-
[littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer
266272
[littlefs-fuse]: https://github.com/geky/littlefs-fuse
267273
[FUSE]: https://github.com/libfuse/libfuse
268274
[littlefs-js]: https://github.com/geky/littlefs-js
269275
[littlefs-js-demo]:http://littlefs.geky.net/demo.html
276+
[littlefs-python]: https://pypi.org/project/littlefs-python/
277+
[littlefs2-rust]: https://crates.io/crates/littlefs2
278+
[nim-littlefs]: https://github.com/Graveflo/nim-littlefs
279+
[chamelon]: https://github.com/yomimono/chamelon
280+
[littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer
270281
[mklfs]: https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src
271-
[Lua RTOS]: https://github.com/whitecatboard/Lua-RTOS-ESP32
282+
[mklittlefs]: https://github.com/earlephilhower/mklittlefs
283+
[pico-littlefs-usb]: https://github.com/oyama/pico-littlefs-usb
272284
[Mbed OS]: https://github.com/armmbed/mbed-os
273285
[LittleFileSystem]: https://os.mbed.com/docs/mbed-os/latest/apis/littlefilesystem.html
274286
[SPIFFS]: https://github.com/pellepl/spiffs
275287
[Dhara]: https://github.com/dlbeer/dhara
276288
[ChaN's FatFs]: http://elm-chan.org/fsw/ff/00index_e.html
277-
[littlefs-python]: https://pypi.org/project/littlefs-python/
278-
[littlefs2-rust]: https://crates.io/crates/littlefs2
279-
[chamelon]: https://github.com/yomimono/chamelon
280-
[nim-littlefs]: https://github.com/Graveflo/nim-littlefs

SPEC.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,10 @@ Superblock fields:
441441

442442
7. **Attr max (32-bits)** - Maximum size of file attributes in bytes.
443443

444-
The superblock must always be the first entry (id 0) in a metadata pair as well
445-
as be the first entry written to the block. This means that the superblock
446-
entry can be read from a device using offsets alone.
444+
The superblock must always be the first entry (id 0) in the metadata pair, and
445+
the name tag must always be the first tag in the metadata pair. This makes it
446+
so that the magic string "littlefs" will always reside at offset=8 in a valid
447+
littlefs superblock.
447448

448449
---
449450
#### `0x2xx` LFS_TYPE_STRUCT

lfs.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,7 +2191,8 @@ static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,
21912191
// we can do, we'll error later if we've become frozen
21922192
LFS_WARN("Unable to expand superblock");
21932193
} else {
2194-
end = begin;
2194+
// duplicate the superblock entry into the new superblock
2195+
end = 1;
21952196
}
21962197
}
21972198
}
@@ -2358,7 +2359,9 @@ fixmlist:;
23582359

23592360
while (d->id >= d->m.count && d->m.split) {
23602361
// we split and id is on tail now
2361-
d->id -= d->m.count;
2362+
if (lfs_pair_cmp(d->m.tail, lfs->root) != 0) {
2363+
d->id -= d->m.count;
2364+
}
23622365
int err = lfs_dir_fetch(lfs, &d->m, d->m.tail);
23632366
if (err) {
23642367
return err;
@@ -4466,17 +4469,19 @@ static int lfs_mount_(lfs_t *lfs, const struct lfs_config *cfg) {
44664469
// found older minor version? set an in-device only bit in the
44674470
// gstate so we know we need to rewrite the superblock before
44684471
// the first write
4472+
bool needssuperblock = false;
44694473
if (minor_version < lfs_fs_disk_version_minor(lfs)) {
44704474
LFS_DEBUG("Found older minor version "
44714475
"v%"PRIu16".%"PRIu16" < v%"PRIu16".%"PRIu16,
44724476
major_version,
44734477
minor_version,
44744478
lfs_fs_disk_version_major(lfs),
44754479
lfs_fs_disk_version_minor(lfs));
4476-
// note this bit is reserved on disk, so fetching more gstate
4477-
// will not interfere here
4478-
lfs_fs_prepsuperblock(lfs, true);
4480+
needssuperblock = true;
44794481
}
4482+
// note this bit is reserved on disk, so fetching more gstate
4483+
// will not interfere here
4484+
lfs_fs_prepsuperblock(lfs, needssuperblock);
44804485

44814486
// check superblock configuration
44824487
if (superblock.name_max) {

tests/test_superblocks.toml

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,24 @@ code = '''
1414
lfs_unmount(&lfs) => 0;
1515
'''
1616

17+
# make sure the magic string "littlefs" is always at offset=8
18+
[cases.test_superblocks_magic]
19+
code = '''
20+
lfs_t lfs;
21+
lfs_format(&lfs, cfg) => 0;
22+
23+
// check our magic string
24+
//
25+
// note if we lose power we may not have the magic string in both blocks!
26+
// but we don't lose power in this test so we can assert the magic string
27+
// is present in both
28+
uint8_t magic[lfs_max(16, READ_SIZE)];
29+
cfg->read(cfg, 0, 0, magic, lfs_max(16, READ_SIZE)) => 0;
30+
assert(memcmp(&magic[8], "littlefs", 8) == 0);
31+
cfg->read(cfg, 1, 0, magic, lfs_max(16, READ_SIZE)) => 0;
32+
assert(memcmp(&magic[8], "littlefs", 8) == 0);
33+
'''
34+
1735
# mount/unmount from interpretting a previous superblock block_count
1836
[cases.test_superblocks_mount_unknown_block_count]
1937
code = '''
@@ -28,7 +46,6 @@ code = '''
2846
lfs_unmount(&lfs) => 0;
2947
'''
3048

31-
3249
# reentrant format
3350
[cases.test_superblocks_reentrant_format]
3451
reentrant = true
@@ -135,6 +152,39 @@ code = '''
135152
lfs_unmount(&lfs) => 0;
136153
'''
137154

155+
# make sure the magic string "littlefs" is always at offset=8
156+
[cases.test_superblocks_magic_expand]
157+
defines.BLOCK_CYCLES = [32, 33, 1]
158+
defines.N = [10, 100, 1000]
159+
code = '''
160+
lfs_t lfs;
161+
lfs_format(&lfs, cfg) => 0;
162+
lfs_mount(&lfs, cfg) => 0;
163+
for (int i = 0; i < N; i++) {
164+
lfs_file_t file;
165+
lfs_file_open(&lfs, &file, "dummy",
166+
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
167+
lfs_file_close(&lfs, &file) => 0;
168+
struct lfs_info info;
169+
lfs_stat(&lfs, "dummy", &info) => 0;
170+
assert(strcmp(info.name, "dummy") == 0);
171+
assert(info.type == LFS_TYPE_REG);
172+
lfs_remove(&lfs, "dummy") => 0;
173+
}
174+
lfs_unmount(&lfs) => 0;
175+
176+
// check our magic string
177+
//
178+
// note if we lose power we may not have the magic string in both blocks!
179+
// but we don't lose power in this test so we can assert the magic string
180+
// is present in both
181+
uint8_t magic[lfs_max(16, READ_SIZE)];
182+
cfg->read(cfg, 0, 0, magic, lfs_max(16, READ_SIZE)) => 0;
183+
assert(memcmp(&magic[8], "littlefs", 8) == 0);
184+
cfg->read(cfg, 1, 0, magic, lfs_max(16, READ_SIZE)) => 0;
185+
assert(memcmp(&magic[8], "littlefs", 8) == 0);
186+
'''
187+
138188
# expanding superblock with power cycle
139189
[cases.test_superblocks_expand_power_cycle]
140190
defines.BLOCK_CYCLES = [32, 33, 1]
@@ -221,6 +271,7 @@ code = '''
221271
lfs_unmount(&lfs) => 0;
222272
'''
223273

274+
224275
# mount with unknown block_count
225276
[cases.test_superblocks_unknown_blocks]
226277
code = '''

0 commit comments

Comments
 (0)