|
| 1 | +## The little filesystem |
| 2 | + |
| 3 | +A little fail-safe filesystem designed for embedded systems. |
| 4 | + |
| 5 | +``` |
| 6 | + | | | .---._____ |
| 7 | + .-----. | | |
| 8 | +--|o |---| littlefs | |
| 9 | +--| |---| | |
| 10 | + '-----' '----------' |
| 11 | + | | | |
| 12 | +``` |
| 13 | + |
| 14 | +**Bounded RAM/ROM** - The littlefs is designed to work with a limited amount |
| 15 | +of memory. Recursion is avoided and dynamic memory is limited to configurable |
| 16 | +buffers that can be provided statically. |
| 17 | + |
| 18 | +**Power-loss resilient** - The littlefs is designed for systems that may have |
| 19 | +random power failures. The littlefs has strong copy-on-write guarantees and |
| 20 | +storage on disk is always kept in a valid state. |
| 21 | + |
| 22 | +**Wear leveling** - Since the most common form of embedded storage is erodible |
| 23 | +flash memories, littlefs provides a form of dynamic wear leveling for systems |
| 24 | +that can not fit a full flash translation layer. |
| 25 | + |
| 26 | +## Example |
| 27 | + |
| 28 | +Here's a simple example that updates a file named `boot_count` every time |
| 29 | +main runs. The program can be interrupted at any time without losing track |
| 30 | +of how many times it has been booted and without corrupting the filesystem: |
| 31 | + |
| 32 | +``` c |
| 33 | +#include "lfs.h" |
| 34 | + |
| 35 | +// variables used by the filesystem |
| 36 | +lfs_t lfs; |
| 37 | +lfs_file_t file; |
| 38 | + |
| 39 | +// configuration of the filesystem is provided by this struct |
| 40 | +const struct lfs_config cfg = { |
| 41 | + // block device operations |
| 42 | + .read = user_provided_block_device_read, |
| 43 | + .prog = user_provided_block_device_prog, |
| 44 | + .erase = user_provided_block_device_erase, |
| 45 | + .sync = user_provided_block_device_sync, |
| 46 | + |
| 47 | + // block device configuration |
| 48 | + .read_size = 16, |
| 49 | + .prog_size = 16, |
| 50 | + .block_size = 4096, |
| 51 | + .block_count = 128, |
| 52 | + .lookahead = 128, |
| 53 | +}; |
| 54 | + |
| 55 | +// entry point |
| 56 | +int main(void) { |
| 57 | + // mount the filesystem |
| 58 | + int err = lfs_mount(&lfs, &cfg); |
| 59 | + |
| 60 | + // reformat if we can't mount the filesystem |
| 61 | + // this should only happen on the first boot |
| 62 | + if (err) { |
| 63 | + lfs_format(&lfs, &cfg); |
| 64 | + lfs_mount(&lfs, &cfg); |
| 65 | + } |
| 66 | + |
| 67 | + // read current count |
| 68 | + uint32_t boot_count = 0; |
| 69 | + lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT); |
| 70 | + lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count)); |
| 71 | + |
| 72 | + // update boot count |
| 73 | + boot_count += 1; |
| 74 | + lfs_file_rewind(&lfs, &file); |
| 75 | + lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count)); |
| 76 | + |
| 77 | + // remember the storage is not updated until the file is closed successfully |
| 78 | + lfs_file_close(&lfs, &file); |
| 79 | + |
| 80 | + // release any resources we were using |
| 81 | + lfs_unmount(&lfs); |
| 82 | + |
| 83 | + // print the boot count |
| 84 | + printf("boot_count: %d\n", boot_count); |
| 85 | +} |
| 86 | +``` |
| 87 | +
|
| 88 | +## Usage |
| 89 | +
|
| 90 | +Detailed documentation (or at least as much detail as is currently available) |
| 91 | +can be found in the comments in [lfs.h](lfs.h). |
| 92 | +
|
| 93 | +As you may have noticed, littlefs takes in a configuration structure that |
| 94 | +defines how the filesystem operates. The configuration struct provides the |
| 95 | +filesystem with the block device operations and dimensions, tweakable |
| 96 | +parameters that tradeoff memory usage for performance, and optional |
| 97 | +static buffers if the user wants to avoid dynamic memory. |
| 98 | +
|
| 99 | +The state of the littlefs is stored in the `lfs_t` type which is left up |
| 100 | +to the user to allocate, allowing multiple filesystems to be in use |
| 101 | +simultaneously. With the `lfs_t` and configuration struct, a user can |
| 102 | +format a block device or mount the filesystem. |
| 103 | +
|
| 104 | +Once mounted, the littlefs provides a full set of POSIX-like file and |
| 105 | +directory functions, with the deviation that the allocation of filesystem |
| 106 | +structures must be provided by the user. |
| 107 | +
|
| 108 | +All POSIX operations, such as remove and rename, are atomic, even in event |
| 109 | +of power-loss. Additionally, no file updates are actually committed to the |
| 110 | +filesystem until sync or close is called on the file. |
| 111 | +
|
| 112 | +## Other notes |
| 113 | +
|
| 114 | +All littlefs have the potential to return a negative error code. The errors |
| 115 | +can be either one of those found in the `enum lfs_error` in [lfs.h](lfs.h), |
| 116 | +or an error returned by the user's block device operations. |
| 117 | +
|
| 118 | +In the configuration struct, the `prog` and `erase` function provided by the |
| 119 | +user may return a `LFS_ERR_CORRUPT` error if the implementation already can |
| 120 | +detect corrupt blocks. However, the wear leveling does not depend on the return |
| 121 | +code of these functions, instead all data is read back and checked for |
| 122 | +integrity. |
| 123 | +
|
| 124 | +If your storage caches writes, make sure that the provided `sync` function |
| 125 | +flushes all the data to memory and ensures that the next read fetches the data |
| 126 | +from memory, otherwise data integrity can not be guaranteed. If the `write` |
| 127 | +function does not perform caching, and therefore each `read` or `write` call |
| 128 | +hits the memory, the `sync` function can simply return 0. |
| 129 | +
|
| 130 | +## Reference material |
| 131 | +
|
| 132 | +[DESIGN.md](DESIGN.md) - DESIGN.md contains a fully detailed dive into how |
| 133 | +littlefs actually works. I would encourage you to read it since the |
| 134 | +solutions and tradeoffs at work here are quite interesting. |
| 135 | +
|
| 136 | +[SPEC.md](SPEC.md) - SPEC.md contains the on-disk specification of littlefs |
| 137 | +with all the nitty-gritty details. Can be useful for developing tooling. |
| 138 | +
|
| 139 | +## Testing |
| 140 | +
|
| 141 | +The littlefs comes with a test suite designed to run on a PC using the |
| 142 | +[emulated block device](emubd/lfs_emubd.h) found in the emubd directory. |
| 143 | +The tests assume a Linux environment and can be started with make: |
| 144 | +
|
| 145 | +``` bash |
| 146 | +make test |
| 147 | +``` |
| 148 | + |
| 149 | +## License |
| 150 | + |
| 151 | +The littlefs is provided under the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html) |
| 152 | +license. See [LICENSE.md](LICENSE.md) for more information. Contributions to |
| 153 | +this project are accepted under the same license. |
| 154 | + |
| 155 | +Individual files contain the following tag instead of the full license text. |
| 156 | + |
| 157 | + SPDX-License-Identifier: BSD-3-Clause |
| 158 | + |
| 159 | +This enables machine processing of license information based on the SPDX |
| 160 | +License Identifiers that are here available: http://spdx.org/licenses/ |
| 161 | + |
| 162 | +## Related projects |
| 163 | + |
| 164 | +[Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) - |
| 165 | +The easiest way to get started with littlefs is to jump into [Mbed](https://os.mbed.com/), |
| 166 | +which already has block device drivers for most forms of embedded storage. The |
| 167 | +littlefs is available in Mbed OS as the [LittleFileSystem](https://os.mbed.com/docs/latest/reference/littlefilesystem.html) |
| 168 | +class. |
| 169 | + |
| 170 | +[littlefs-fuse](https://github.com/geky/littlefs-fuse) - A [FUSE](https://github.com/libfuse/libfuse) |
| 171 | +wrapper for littlefs. The project allows you to mount littlefs directly on a |
| 172 | +Linux machine. Can be useful for debugging littlefs if you have an SD card |
| 173 | +handy. |
| 174 | + |
| 175 | +[littlefs-js](https://github.com/geky/littlefs-js) - A javascript wrapper for |
| 176 | +littlefs. I'm not sure why you would want this, but it is handy for demos. |
| 177 | +You can see it in action [here](http://littlefs.geky.net/demo.html). |
0 commit comments