Rather than tracking all in-flight blocks blocks during a lookahead, littlefs uses an ack scheme to mark the first allocated block that hasn't reached the disk yet. littlefs assumes all blocks since the last ack are bad or in-flight, and uses this to know when it's out of storage. However, these unacked allocations were still being populated in the lookahead buffer. If the whole block device fits in the lookahead buffer, _and_ littlefs managed to scan around the whole storage while an unacked block was still in-flight, it would assume the block was free and misallocate it. The fix is to only fill the lookahead buffer up to the last ack. The internal free structure was restructured to simplify the runtime calculation of lookahead size. |
||
---|---|---|
.. | ||
TESTS | ||
littlefs | ||
.mbedignore | ||
.travis.yml | ||
LICENSE.md | ||
LittleFileSystem.cpp | ||
LittleFileSystem.h | ||
README.md | ||
mbed_lib.json |
README.md
Mbed OS API for the little filesystem
This is the Mbed OS API for littlefs, a little fail-safe filesystem designed for embedded systems.
| | | .---._____
.-----. | |
--|o |---| littlefs |
--| |---| |
'-----' '----------'
| | |
Bounded RAM/ROM - The littlefs is designed to work with a limited amount of memory. Recursion is avoided, and dynamic memory is limited to configurable buffers that can be provided statically.
Power-loss resilient - The littlefs is designed for systems that may have random power failures. The littlefs has strong copy-on-write guarantees, and storage on disk is always kept in a valid state.
Wear leveling - Because the most common form of embedded storage is erodible flash memories, littlefs provides a form of dynamic wear leveling for systems that cannot fit a full flash translation layer.
Usage
If you are already using a filesystem in Mbed, adopting the littlefs should just require a name change to use the LittleFileSystem class.
Here is a simple example that updates a file named "boot_count" every time the application runs:
#include "LittleFileSystem.h"
#include "SPIFBlockDevice.h"
// Physical block device, can be any device that supports the BlockDevice API
SPIFBlockDevice bd(PTE2, PTE4, PTE1, PTE5);
// Storage for the littlefs
LittleFileSystem fs("fs");
// Entry point
int main() {
// Mount the filesystem
int err = fs.mount(&bd);
if (err) {
// Reformat if we can't mount the filesystem,
// this should only happen on the first boot
LittleFileSystem::format(&bd);
fs.mount(&bd);
}
// Read the boot count
uint32_t boot_count = 0;
FILE *f = fopen("/fs/boot_count", "r+");
if (!f) {
// Create the file if it doesn't exist
f = fopen("/fs/boot_count", "w+");
}
fread(&boot_count, sizeof(boot_count), 1, f);
// Update the boot count
boot_count += 1;
rewind(f);
fwrite(&boot_count, sizeof(boot_count), 1, f);
// Remember that storage may not be updated until the file
// is closed successfully
fclose(f);
// Release any resources we were using
fs.unmount();
// Print the boot count
printf("boot_count: %ld\n", boot_count);
}
Reference material
DESIGN.md - DESIGN.md contains a fully detailed dive into how littlefs actually works. We encourage you to read it because the solutions and tradeoffs at work here are quite interesting.
SPEC.md - SPEC.md contains the on-disk specification of littlefs with all the nitty-gritty details. This can be useful for developing tooling.
Related projects
littlefs - Where the core of littlefs currently lives.
littlefs-fuse - A FUSE wrapper for littlefs. The project allows you to mount littlefs directly in a Linux machine. This can be useful for debugging littlefs if you have an SD card handy.
littlefs-js - A JavaScript wrapper for littlefs. I'm not sure why you would want this, but it is handy for demos. You can see it in action here.