1## littlefs 2 3A little fail-safe filesystem designed for microcontrollers. 4 5``` 6 | | | .---._____ 7 .-----. | | 8--|o |---| littlefs | 9--| |---| | 10 '-----' '----------' 11 | | | 12``` 13 14**Power-loss resilience** - littlefs is designed to handle random power 15failures. All file operations have strong copy-on-write guarantees and if 16power is lost the filesystem will fall back to the last known good state. 17 18**Dynamic wear leveling** - littlefs is designed with flash in mind, and 19provides wear leveling over dynamic blocks. Additionally, littlefs can 20detect bad blocks and work around them. 21 22**Bounded RAM/ROM** - littlefs is designed to work with a small amount of 23memory. RAM usage is strictly bounded, which means RAM consumption does not 24change as the filesystem grows. The filesystem contains no unbounded 25recursion and dynamic memory is limited to configurable buffers that can be 26provided statically. 27 28## Example 29 30Here's a simple example that updates a file named `boot_count` every time 31main runs. The program can be interrupted at any time without losing track 32of how many times it has been booted and without corrupting the filesystem: 33 34``` c 35#include "lfs.h" 36 37// variables used by the filesystem 38lfs_t lfs; 39lfs_file_t file; 40 41// configuration of the filesystem is provided by this struct 42const struct lfs_config cfg = { 43 // block device operations 44 .read = user_provided_block_device_read, 45 .prog = user_provided_block_device_prog, 46 .erase = user_provided_block_device_erase, 47 .sync = user_provided_block_device_sync, 48 49 // block device configuration 50 .read_size = 16, 51 .prog_size = 16, 52 .block_size = 4096, 53 .block_count = 128, 54 .cache_size = 16, 55 .lookahead_size = 16, 56 .block_cycles = 500, 57}; 58 59// entry point 60int main(void) { 61 // mount the filesystem 62 int err = lfs_mount(&lfs, &cfg); 63 64 // reformat if we can't mount the filesystem 65 // this should only happen on the first boot 66 if (err) { 67 lfs_format(&lfs, &cfg); 68 lfs_mount(&lfs, &cfg); 69 } 70 71 // read current count 72 uint32_t boot_count = 0; 73 lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT); 74 lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count)); 75 76 // update boot count 77 boot_count += 1; 78 lfs_file_rewind(&lfs, &file); 79 lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count)); 80 81 // remember the storage is not updated until the file is closed successfully 82 lfs_file_close(&lfs, &file); 83 84 // release any resources we were using 85 lfs_unmount(&lfs); 86 87 // print the boot count 88 printf("boot_count: %d\n", boot_count); 89} 90``` 91 92## Usage 93 94Detailed documentation (or at least as much detail as is currently available) 95can be found in the comments in [lfs.h](lfs.h). 96 97littlefs takes in a configuration structure that defines how the filesystem 98operates. The configuration struct provides the filesystem with the block 99device operations and dimensions, tweakable parameters that tradeoff memory 100usage for performance, and optional static buffers if the user wants to avoid 101dynamic memory. 102 103The state of the littlefs is stored in the `lfs_t` type which is left up 104to the user to allocate, allowing multiple filesystems to be in use 105simultaneously. With the `lfs_t` and configuration struct, a user can 106format a block device or mount the filesystem. 107 108Once mounted, the littlefs provides a full set of POSIX-like file and 109directory functions, with the deviation that the allocation of filesystem 110structures must be provided by the user. 111 112All POSIX operations, such as remove and rename, are atomic, even in event 113of power-loss. Additionally, file updates are not actually committed to 114the filesystem until sync or close is called on the file. 115 116## Other notes 117 118Littlefs is written in C, and specifically should compile with any compiler 119that conforms to the `C99` standard. 120 121All littlefs calls have the potential to return a negative error code. The 122errors can be either one of those found in the `enum lfs_error` in 123[lfs.h](lfs.h), or an error returned by the user's block device operations. 124 125In the configuration struct, the `prog` and `erase` function provided by the 126user may return a `LFS_ERR_CORRUPT` error if the implementation already can 127detect corrupt blocks. However, the wear leveling does not depend on the return 128code of these functions, instead all data is read back and checked for 129integrity. 130 131If your storage caches writes, make sure that the provided `sync` function 132flushes all the data to memory and ensures that the next read fetches the data 133from memory, otherwise data integrity can not be guaranteed. If the `write` 134function does not perform caching, and therefore each `read` or `write` call 135hits the memory, the `sync` function can simply return 0. 136 137## Design 138 139At a high level, littlefs is a block based filesystem that uses small logs to 140store metadata and larger copy-on-write (COW) structures to store file data. 141 142In littlefs, these ingredients form a sort of two-layered cake, with the small 143logs (called metadata pairs) providing fast updates to metadata anywhere on 144storage, while the COW structures store file data compactly and without any 145wear amplification cost. 146 147Both of these data structures are built out of blocks, which are fed by a 148common block allocator. By limiting the number of erases allowed on a block 149per allocation, the allocator provides dynamic wear leveling over the entire 150filesystem. 151 152``` 153 root 154 .--------.--------. 155 | A'| B'| | 156 | | |-> | 157 | | | | 158 '--------'--------' 159 .----' '--------------. 160 A v B v 161 .--------.--------. .--------.--------. 162 | C'| D'| | | E'|new| | 163 | | |-> | | | E'|-> | 164 | | | | | | | | 165 '--------'--------' '--------'--------' 166 .-' '--. | '------------------. 167 v v .-' v 168.--------. .--------. v .--------. 169| C | | D | .--------. write | new E | 170| | | | | E | ==> | | 171| | | | | | | | 172'--------' '--------' | | '--------' 173 '--------' .-' | 174 .-' '-. .-------------|------' 175 v v v v 176 .--------. .--------. .--------. 177 | F | | G | | new F | 178 | | | | | | 179 | | | | | | 180 '--------' '--------' '--------' 181``` 182 183More details on how littlefs works can be found in [DESIGN.md](DESIGN.md) and 184[SPEC.md](SPEC.md). 185 186- [DESIGN.md](DESIGN.md) - A fully detailed dive into how littlefs works. 187 I would suggest reading it as the tradeoffs at work are quite interesting. 188 189- [SPEC.md](SPEC.md) - The on-disk specification of littlefs with all the 190 nitty-gritty details. May be useful for tooling development. 191 192## Testing 193 194The littlefs comes with a test suite designed to run on a PC using the 195[emulated block device](emubd/lfs_emubd.h) found in the emubd directory. 196The tests assume a Linux environment and can be started with make: 197 198``` bash 199make test 200``` 201 202## License 203 204The littlefs is provided under the [BSD-3-Clause] license. See 205[LICENSE.md](LICENSE.md) for more information. Contributions to this project 206are accepted under the same license. 207 208Individual files contain the following tag instead of the full license text. 209 210 SPDX-License-Identifier: BSD-3-Clause 211 212This enables machine processing of license information based on the SPDX 213License Identifiers that are here available: http://spdx.org/licenses/ 214 215## Related projects 216 217- [littlefs-fuse] - A [FUSE] wrapper for littlefs. The project allows you to 218 mount littlefs directly on a Linux machine. Can be useful for debugging 219 littlefs if you have an SD card handy. 220 221- [littlefs-js] - A javascript wrapper for littlefs. I'm not sure why you would 222 want this, but it is handy for demos. You can see it in action 223 [here][littlefs-js-demo]. 224 225- [littlefs-python] - A Python wrapper for littlefs. The project allows you 226 to create images of the filesystem on your PC. Check if littlefs will fit 227 your needs, create images for a later download to the target memory or 228 inspect the content of a binary image of the target memory. 229 230- [mklfs] - A command line tool built by the [Lua RTOS] guys for making 231 littlefs images from a host PC. Supports Windows, Mac OS, and Linux. 232 233- [Mbed OS] - The easiest way to get started with littlefs is to jump into Mbed 234 which already has block device drivers for most forms of embedded storage. 235 littlefs is available in Mbed OS as the [LittleFileSystem] class. 236 237- [SPIFFS] - Another excellent embedded filesystem for NOR flash. As a more 238 traditional logging filesystem with full static wear-leveling, SPIFFS will 239 likely outperform littlefs on small memories such as the internal flash on 240 microcontrollers. 241 242- [Dhara] - An interesting NAND flash translation layer designed for small 243 MCUs. It offers static wear-leveling and power-resilience with only a fixed 244 _O(|address|)_ pointer structure stored on each block and in RAM. 245 246 247[BSD-3-Clause]: https://spdx.org/licenses/BSD-3-Clause.html 248[littlefs-fuse]: https://github.com/geky/littlefs-fuse 249[FUSE]: https://github.com/libfuse/libfuse 250[littlefs-js]: https://github.com/geky/littlefs-js 251[littlefs-js-demo]:http://littlefs.geky.net/demo.html 252[mklfs]: https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src 253[Lua RTOS]: https://github.com/whitecatboard/Lua-RTOS-ESP32 254[Mbed OS]: https://github.com/armmbed/mbed-os 255[LittleFileSystem]: https://os.mbed.com/docs/mbed-os/v5.12/apis/littlefilesystem.html 256[SPIFFS]: https://github.com/pellepl/spiffs 257[Dhara]: https://github.com/dlbeer/dhara 258[littlefs-python]: https://pypi.org/project/littlefs-python/ 259