mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Updated DESIGN.md to reflect v2 changes
Now with graphs! Images are stored on the branch gh-images in an effort to avoid binary bloat in the git history. Also spruced up SPEC.md and README.md and ran a spellechecker over the documentation. Favorite typo so far was dependendent, which is, in fact, not a word.
This commit is contained in:
		
							
								
								
									
										163
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										163
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| ## The little filesystem | ## littlefs | ||||||
|  |  | ||||||
| A little fail-safe filesystem designed for embedded systems. | A little fail-safe filesystem designed for microcontrollers. | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
|    | | |     .---._____ |    | | |     .---._____ | ||||||
| @@ -11,17 +11,19 @@ A little fail-safe filesystem designed for embedded systems. | |||||||
|    | | | |    | | | | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| **Bounded RAM/ROM** - The littlefs is designed to work with a limited amount | **Power-loss resilience** - littlefs is designed to handle random power | ||||||
| of memory. Recursion is avoided and dynamic memory is limited to configurable | failures. All file operations have strong copy-on-write guarantees and if | ||||||
| buffers that can be provided statically. | power is lost the filesystem will fall back to the last known good state. | ||||||
|  |  | ||||||
| **Power-loss resilient** - The littlefs is designed for systems that may have | **Dynamic wear leveling** - littlefs is designed with flash in mind, and | ||||||
| random power failures. The littlefs has strong copy-on-write guarantees and | provides wear leveling over dynamic blocks. Additionally, littlefs can | ||||||
| storage on disk is always kept in a valid state. | detect bad blocks and work around them. | ||||||
|  |  | ||||||
| **Wear leveling** - Since the most common form of embedded storage is erodible | **Bounded RAM/ROM** - littlefs is designed to work with a small amount of | ||||||
| flash memories, littlefs provides a form of dynamic wear leveling for systems | memory. RAM usage is strictly bounded, which means RAM consumption does not | ||||||
| that can not fit a full flash translation layer. | change as the filesystem grows. The filesystem contains no unbounded | ||||||
|  | recursion and dynamic memory is limited to configurable buffers that can be | ||||||
|  | provided statically. | ||||||
|  |  | ||||||
| ## Example | ## Example | ||||||
|  |  | ||||||
| @@ -91,11 +93,11 @@ int main(void) { | |||||||
| Detailed documentation (or at least as much detail as is currently available) | Detailed documentation (or at least as much detail as is currently available) | ||||||
| can be found in the comments in [lfs.h](lfs.h). | can be found in the comments in [lfs.h](lfs.h). | ||||||
|  |  | ||||||
| As you may have noticed, littlefs takes in a configuration structure that | littlefs takes in a configuration structure that defines how the filesystem | ||||||
| defines how the filesystem operates. The configuration struct provides the | operates. The configuration struct provides the filesystem with the block | ||||||
| filesystem with the block device operations and dimensions, tweakable | device operations and dimensions, tweakable parameters that tradeoff memory | ||||||
| parameters that tradeoff memory usage for performance, and optional | usage for performance, and optional static buffers if the user wants to avoid | ||||||
| static buffers if the user wants to avoid dynamic memory. | dynamic memory. | ||||||
|  |  | ||||||
| The state of the littlefs is stored in the `lfs_t` type which is left up | The state of the littlefs is stored in the `lfs_t` type which is left up | ||||||
| to the user to allocate, allowing multiple filesystems to be in use | to the user to allocate, allowing multiple filesystems to be in use | ||||||
| @@ -107,14 +109,14 @@ directory functions, with the deviation that the allocation of filesystem | |||||||
| structures must be provided by the user. | structures must be provided by the user. | ||||||
|  |  | ||||||
| All POSIX operations, such as remove and rename, are atomic, even in event | All POSIX operations, such as remove and rename, are atomic, even in event | ||||||
| of power-loss. Additionally, no file updates are actually committed to the | of power-loss. Additionally, no file updates are not actually committed to | ||||||
| filesystem until sync or close is called on the file. | the filesystem until sync or close is called on the file. | ||||||
|  |  | ||||||
| ## Other notes | ## Other notes | ||||||
|  |  | ||||||
| All littlefs have the potential to return a negative error code. The errors | All littlefs functions have the potential to return a negative error code. The | ||||||
| can be either one of those found in the `enum lfs_error` in [lfs.h](lfs.h), | errors can be either one of those found in the `enum lfs_error` in | ||||||
| or an error returned by the user's block device operations. | [lfs.h](lfs.h), or an error returned by the user's block device operations. | ||||||
|  |  | ||||||
| In the configuration struct, the `prog` and `erase` function provided by the | In the configuration struct, the `prog` and `erase` function provided by the | ||||||
| user may return a `LFS_ERR_CORRUPT` error if the implementation already can | user may return a `LFS_ERR_CORRUPT` error if the implementation already can | ||||||
| @@ -128,14 +130,60 @@ from memory, otherwise data integrity can not be guaranteed. If the `write` | |||||||
| function does not perform caching, and therefore each `read` or `write` call | function does not perform caching, and therefore each `read` or `write` call | ||||||
| hits the memory, the `sync` function can simply return 0. | hits the memory, the `sync` function can simply return 0. | ||||||
|  |  | ||||||
| ## Reference material | ## Design | ||||||
|  |  | ||||||
| [DESIGN.md](DESIGN.md) - DESIGN.md contains a fully detailed dive into how | At a high level, littlefs is a block based filesystem that uses small logs to | ||||||
| littlefs actually works. I would encourage you to read it since the | store metadata and larger copy-on-write (COW) structures to store file data. | ||||||
| solutions and tradeoffs at work here are quite interesting. |  | ||||||
|  |  | ||||||
| [SPEC.md](SPEC.md) - SPEC.md contains the on-disk specification of littlefs | In littlefs, these ingredients form a sort of two-layered cake, with the small | ||||||
| with all the nitty-gritty details. Can be useful for developing tooling. | logs (called metadata pairs) providing fast updates to metadata anywhere on | ||||||
|  | storage, while the COW structures store file data compactly and without any | ||||||
|  | wear amplification cost. | ||||||
|  |  | ||||||
|  | Both of these data structures are built out of blocks, which are fed by a | ||||||
|  | common block allocator. By limiting the number of erases allowed on a block | ||||||
|  | per allocation, the allocator provides dynamic wear leveling over the entire | ||||||
|  | filesystem. | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  |                     root | ||||||
|  |                    .--------.--------. | ||||||
|  |                    | A'| B'|         | | ||||||
|  |                    |   |   |->       | | ||||||
|  |                    |   |   |         | | ||||||
|  |                    '--------'--------' | ||||||
|  |                 .----'   '--------------. | ||||||
|  |        A       v                 B       v | ||||||
|  |       .--------.--------.       .--------.--------. | ||||||
|  |       | C'| D'|         |       | E'|new|         | | ||||||
|  |       |   |   |->       |       |   | E'|->       | | ||||||
|  |       |   |   |         |       |   |   |         | | ||||||
|  |       '--------'--------'       '--------'--------' | ||||||
|  |       .-'   '--.                  |   '------------------. | ||||||
|  |      v          v              .-'                        v | ||||||
|  | .--------.  .--------.        v                       .--------. | ||||||
|  | |   C    |  |   D    |   .--------.       write       | new E  | | ||||||
|  | |        |  |        |   |   E    |        ==>        |        | | ||||||
|  | |        |  |        |   |        |                   |        | | ||||||
|  | '--------'  '--------'   |        |                   '--------' | ||||||
|  |                          '--------'                   .-'    | | ||||||
|  |                          .-'    '-.    .-------------|------' | ||||||
|  |                         v          v  v              v | ||||||
|  |                    .--------.  .--------.       .--------. | ||||||
|  |                    |   F    |  |   G    |       | new F  | | ||||||
|  |                    |        |  |        |       |        | | ||||||
|  |                    |        |  |        |       |        | | ||||||
|  |                    '--------'  '--------'       '--------' | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | More details on how littlefs works can be found in [DESIGN.md](DESIGN.md) and | ||||||
|  | [SPEC.md](SPEC.md). | ||||||
|  |  | ||||||
|  | - [DESIGN.md](DESIGN.md) - A fully detailed dive into how littlefs works. | ||||||
|  |   I would suggest reading it as the tradeoffs at work are quite interesting. | ||||||
|  |  | ||||||
|  | - [SPEC.md](SPEC.md) - The on-disk specification of littlefs with all the | ||||||
|  |   nitty-gritty details. May be useful for tooling development. | ||||||
|  |  | ||||||
| ## Testing | ## Testing | ||||||
|  |  | ||||||
| @@ -149,9 +197,9 @@ make test | |||||||
|  |  | ||||||
| ## License | ## License | ||||||
|  |  | ||||||
| The littlefs is provided under the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html) | The littlefs is provided under the [BSD-3-Clause] license. See | ||||||
| license. See [LICENSE.md](LICENSE.md) for more information. Contributions to | [LICENSE.md](LICENSE.md) for more information. Contributions to this project | ||||||
| this project are accepted under the same license. | are accepted under the same license. | ||||||
|  |  | ||||||
| Individual files contain the following tag instead of the full license text. | Individual files contain the following tag instead of the full license text. | ||||||
|  |  | ||||||
| @@ -162,32 +210,39 @@ License Identifiers that are here available: http://spdx.org/licenses/ | |||||||
|  |  | ||||||
| ## Related projects | ## Related projects | ||||||
|  |  | ||||||
| [Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) - | - [littlefs-fuse] - A [FUSE] wrapper for littlefs. The project allows you to | ||||||
| The easiest way to get started with littlefs is to jump into [Mbed](https://os.mbed.com/), |   mount littlefs directly on a Linux machine. Can be useful for debugging | ||||||
| which already has block device drivers for most forms of embedded storage. The |   littlefs if you have an SD card handy. | ||||||
| littlefs is available in Mbed OS as the [LittleFileSystem](https://os.mbed.com/docs/latest/reference/littlefilesystem.html) |  | ||||||
| class. |  | ||||||
|  |  | ||||||
| [littlefs-fuse](https://github.com/geky/littlefs-fuse) - A [FUSE](https://github.com/libfuse/libfuse) | - [littlefs-js] - A javascript wrapper for littlefs. I'm not sure why you would | ||||||
| wrapper for littlefs. The project allows you to mount littlefs directly on a |   want this, but it is handy for demos.  You can see it in action | ||||||
| Linux machine. Can be useful for debugging littlefs if you have an SD card |   [here][littlefs-js-demo]. | ||||||
| handy. |  | ||||||
|  |  | ||||||
| [littlefs-js](https://github.com/geky/littlefs-js) - A javascript wrapper for | - [mklfs] - A command line tool built by the [Lua RTOS] guys for making | ||||||
| littlefs. I'm not sure why you would want this, but it is handy for demos. |   littlefs images from a host PC. Supports Windows, Mac OS, and Linux. | ||||||
| You can see it in action [here](http://littlefs.geky.net/demo.html). |  | ||||||
|  |  | ||||||
| [mklfs](https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src) - | - [Mbed OS] - The easiest way to get started with littlefs is to jump into Mbed | ||||||
| A command line tool built by the [Lua RTOS](https://github.com/whitecatboard/Lua-RTOS-ESP32) |   which already has block device drivers for most forms of embedded storage. | ||||||
| guys for making littlefs images from a host PC. Supports Windows, Mac OS, |   littlefs is available in Mbed OS as the [LittleFileSystem] class. | ||||||
| and Linux. |  | ||||||
|  |  | ||||||
| [SPIFFS](https://github.com/pellepl/spiffs) - Another excellent embedded | - [SPIFFS] - Another excellent embedded filesystem for NOR flash. As a more | ||||||
| filesystem for NOR flash. As a more traditional logging filesystem with full |   traditional logging filesystem with full static wear-leveling, SPIFFS will | ||||||
| static wear-leveling, SPIFFS will likely outperform littlefs on small |   likely outperform littlefs on small memories such as the internal flash on | ||||||
| memories such as the internal flash on microcontrollers. |   microcontrollers. | ||||||
|  |  | ||||||
| [Dhara](https://github.com/dlbeer/dhara) - An interesting NAND flash | - [Dhara] - An interesting NAND flash translation layer designed for small | ||||||
| translation layer designed for small MCUs. It offers static wear-leveling and |   MCUs. It offers static wear-leveling and power-resilience with only a fixed | ||||||
| power-resilience with only a fixed O(|address|) pointer structure stored on |   _O(|address|)_ pointer structure stored on each block and in RAM. | ||||||
| each block and in RAM. |  | ||||||
|  |  | ||||||
|  | [BSD-3-Clause]: https://spdx.org/licenses/BSD-3-Clause.html | ||||||
|  | [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 | ||||||
|  | [mklfs]: https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src | ||||||
|  | [Lua RTOS]: https://github.com/whitecatboard/Lua-RTOS-ESP32 | ||||||
|  | [Mbed OS]: https://github.com/armmbed/mbed-os | ||||||
|  | [LittleFileSystem]: https://os.mbed.com/docs/mbed-os/v5.12/apis/littlefilesystem.html | ||||||
|  | [SPIFFS]: https://github.com/pellepl/spiffs | ||||||
|  | [Dhara]: https://github.com/dlbeer/dhara | ||||||
|   | |||||||
							
								
								
									
										191
									
								
								SPEC.md
									
									
									
									
									
								
							
							
						
						
									
										191
									
								
								SPEC.md
									
									
									
									
									
								
							| @@ -1,9 +1,9 @@ | |||||||
| ## The little filesystem technical specification | ## littlefs technical specification | ||||||
|  |  | ||||||
| This is the technical specification of the little filesystem. This document | This is the technical specification of the little filesystem. This document | ||||||
| covers the technical details of how the littlefs is stored on disk for | covers the technical details of how the littlefs is stored on disk for | ||||||
| introspection and tool development. This document assumes you are familiar | introspection and tooling. This document assumes you are familiar with the | ||||||
| with the design of the littlefs, for more info on how littlefs works check | design of the littlefs, for more info on how littlefs works check | ||||||
| out [DESIGN.md](DESIGN.md). | out [DESIGN.md](DESIGN.md). | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
| @@ -18,22 +18,21 @@ out [DESIGN.md](DESIGN.md). | |||||||
| ## Some quick notes | ## Some quick notes | ||||||
|  |  | ||||||
| - littlefs is a block-based filesystem. The disk is divided into an array of | - littlefs is a block-based filesystem. The disk is divided into an array of | ||||||
|   evenly sized blocks that are used as the logical unit of storage. Block |   evenly sized blocks that are used as the logical unit of storage. | ||||||
|   pointers are stored in 32 bits. |  | ||||||
|  | - Block pointers are stored in 32 bits, with the special value `0xffffffff` | ||||||
|  |   representing a null block address. | ||||||
|  |  | ||||||
| - In addition to the logical block size (which usually matches the erase | - In addition to the logical block size (which usually matches the erase | ||||||
|   block size), littlefs also uses a program block size and read block size. |   block size), littlefs also uses a program block size and read block size. | ||||||
|   These determine the alignment of block device operations, but aren't needed |   These determine the alignment of block device operations, but don't need | ||||||
|   for portability. |   to be consistent for portability. | ||||||
|  |  | ||||||
| - By default, any values in littlefs are stored in little-endian byte order. | - By default, all values in littlefs are stored in little-endian byte order. | ||||||
|  |  | ||||||
| - The littlefs uses the value of `0xffffffff` to represent a null |  | ||||||
|   block address. |  | ||||||
|  |  | ||||||
| ## Directories / Metadata pairs | ## Directories / Metadata pairs | ||||||
|  |  | ||||||
| Metadata pairs form the backbone of the littlefs and provide a system for | Metadata pairs form the backbone of littlefs and provide a system for | ||||||
| distributed atomic updates. Even the superblock is stored in a metadata pair. | distributed atomic updates. Even the superblock is stored in a metadata pair. | ||||||
|  |  | ||||||
| As their name suggests, a metadata pair is stored in two blocks, with one block | As their name suggests, a metadata pair is stored in two blocks, with one block | ||||||
| @@ -91,12 +90,12 @@ alignment. | |||||||
|  |  | ||||||
| Metadata block fields: | Metadata block fields: | ||||||
|  |  | ||||||
| - **Revision count (32-bits)** - Incremented every erase cycle. If both blocks | 1. **Revision count (32-bits)** - Incremented every erase cycle. If both blocks | ||||||
|    contain valid commits, only the block with the most recent revision count |    contain valid commits, only the block with the most recent revision count | ||||||
|    should be used. Sequence comparison must be used to avoid issues with |    should be used. Sequence comparison must be used to avoid issues with | ||||||
|    integer overflow. |    integer overflow. | ||||||
|  |  | ||||||
| - **CRC (32-bits)** - Detects corruption from power-loss or other write | 2. **CRC (32-bits)** - Detects corruption from power-loss or other write | ||||||
|    issues.  Uses a CRC-32 with a polynomial of `0x04c11db7` initialized |    issues.  Uses a CRC-32 with a polynomial of `0x04c11db7` initialized | ||||||
|    with `0xffffffff`. |    with `0xffffffff`. | ||||||
|  |  | ||||||
| @@ -198,7 +197,7 @@ So in littlefs, 32-bit tags describe every type of metadata. And this means | |||||||
| _every_ type of metadata, including file entries, directory fields, and | _every_ type of metadata, including file entries, directory fields, and | ||||||
| global state. Even the CRCs used to mark the end of commits get their own tag. | global state. Even the CRCs used to mark the end of commits get their own tag. | ||||||
|  |  | ||||||
| Because of this, the tag format contains some densely packed informtaion. Note | Because of this, the tag format contains some densely packed information. Note | ||||||
| that there are multiple levels of types which break down into more info: | that there are multiple levels of types which break down into more info: | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
| @@ -214,9 +213,9 @@ that there are multiple levels of types which break down into more info: | |||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
| Before we go further, there's one VERY important thing to note. These tags are | Before we go further, there's one important thing to note. These tags are | ||||||
| NOT stored in little-endian. Tags stored in commits are actually stored in | **not** stored in little-endian. Tags stored in commits are actually stored | ||||||
| big-endian (and is the only thing in littlefs stored in big-endian). This | in big-endian (and is the only thing in littlefs stored in big-endian). This | ||||||
| little bit of craziness comes from the fact that the valid bit must be the | little bit of craziness comes from the fact that the valid bit must be the | ||||||
| first bit in a commit, and when converted to little-endian, the valid bit finds | first bit in a commit, and when converted to little-endian, the valid bit finds | ||||||
| itself in byte 4. We could restructure the tag to store the valid bit lower, | itself in byte 4. We could restructure the tag to store the valid bit lower, | ||||||
| @@ -228,25 +227,25 @@ invalid and can be used for null values. | |||||||
|  |  | ||||||
| Metadata tag fields: | Metadata tag fields: | ||||||
|  |  | ||||||
| - **Valid bit (1-bit)** - Indicates if the tag is valid. | 1. **Valid bit (1-bit)** - Indicates if the tag is valid. | ||||||
|  |  | ||||||
| - **Type3 (11-bits)** - Type of the tag. This field is broken down further | 2. **Type3 (11-bits)** - Type of the tag. This field is broken down further | ||||||
|    into a 3-bit abstract type and an 8-bit chunk field. Note that the value |    into a 3-bit abstract type and an 8-bit chunk field. Note that the value | ||||||
|    `0x000` is invalid and not assigned a type. |    `0x000` is invalid and not assigned a type. | ||||||
|  |  | ||||||
| - **Type1 (3-bits)** - Abstract type of the tag. Groups the tags into | 3. **Type1 (3-bits)** - Abstract type of the tag. Groups the tags into | ||||||
|    8 categories that facilitate bitmasked lookups. |    8 categories that facilitate bitmasked lookups. | ||||||
|  |  | ||||||
| - **Chunk (8-bits)** - Chunk field used for various purposes by the different | 4. **Chunk (8-bits)** - Chunk field used for various purposes by the different | ||||||
|    abstract types.  type1+chunk+id form a unique identifier for each tag in the |    abstract types.  type1+chunk+id form a unique identifier for each tag in the | ||||||
|    metadata block. |    metadata block. | ||||||
|  |  | ||||||
| - **Id (10-bits)** - File id associated with the tag. Each file in a metadata | 5. **Id (10-bits)** - File id associated with the tag. Each file in a metadata | ||||||
|    block gets a unique id which is used to associate tags with that file. The |    block gets a unique id which is used to associate tags with that file. The | ||||||
|    special value `0x3ff` is used for any tags that are not associated with a |    special value `0x3ff` is used for any tags that are not associated with a | ||||||
|    file, such as directory and global metadata. |    file, such as directory and global metadata. | ||||||
|  |  | ||||||
| - **Length (10-bits)** - Length of the data in bytes. The special value | 6. **Length (10-bits)** - Length of the data in bytes. The special value | ||||||
|    `0x3ff` indicates that this tag has been deleted. |    `0x3ff` indicates that this tag has been deleted. | ||||||
|  |  | ||||||
| ## Metadata types | ## Metadata types | ||||||
| @@ -300,9 +299,9 @@ Layout of the name tag: | |||||||
|  |  | ||||||
| Name fields: | Name fields: | ||||||
|  |  | ||||||
| - **file type (8-bits)** - Type of the file. | 1. **file type (8-bits)** - Type of the file. | ||||||
|  |  | ||||||
| - **file name** - File name stored as an ASCII string. | 2. **file name** - File name stored as an ASCII string. | ||||||
|  |  | ||||||
| --- | --- | ||||||
| #### `0x001` LFS_TYPE_REG | #### `0x001` LFS_TYPE_REG | ||||||
| @@ -335,13 +334,14 @@ across a linked-list of metadata pairs rooted on the blocks 0 and 1. The last | |||||||
| metadata pair doubles as the root directory of the filesystem. | metadata pair doubles as the root directory of the filesystem. | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
| .--------.  .--------.  .--------.  .--------.  .--------. |  .--------.  .--------.  .--------.  .--------.  .--------. | ||||||
| | super  |->| super  |->| super  |->| super  |->| file B | | .| super  |->| super  |->| super  |->| super  |->| file B | | ||||||
| | block  |  | block  |  | block  |  | block  |  | file C | | || block  | || block  | || block  | || block  | || file C | | ||||||
| |        |  |        |  |        |  | file A |  | file D | | ||        | ||        | ||        | || file A | || file D | | ||||||
|  | |'--------' |'--------' |'--------' |'--------' |'--------' | ||||||
| '--------'  '--------'  '--------'  '--------'  '--------' | '--------'  '--------'  '--------'  '--------'  '--------' | ||||||
|  |  | ||||||
| \---------------+----------------/  \---------+---------/ | \----------------+----------------/ \----------+----------/ | ||||||
|           superblock pairs               root directory |           superblock pairs               root directory | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| @@ -366,48 +366,41 @@ Layout of the superblock name tag and inline-struct tag: | |||||||
|  '----------------- valid bit |  '----------------- valid bit | ||||||
|  |  | ||||||
|         tag                          data |         tag                          data | ||||||
| [--      32      --][--      32      --|--      32      --| | [--      32      --][--      32      --|--      32      --|--      32      --] | ||||||
| [1|- 11 -| 10 | 10 ][--      32      --|--      32      --| | [1|- 11 -| 10 | 10 ][--      32      --|--      32      --|--      32      --] | ||||||
|  ^    ^     ^    ^            ^- version         ^- block size |  ^    ^     ^    ^            ^- version         ^- block size      ^- block count | ||||||
|  |  |    |     |    |  [--      32      --|--      32      --|--      32      --] | ||||||
|  |  |    |     |    |  [--      32      --|--      32      --|--      32      --] | ||||||
|  |  |    |     |    |            ^- name max        ^- file max        ^- attr max | ||||||
|  |    |     |    '- size (24) |  |    |     |    '- size (24) | ||||||
|  |    |     '------ id (0) |  |    |     '------ id (0) | ||||||
|  |    '------------ type (0x201) |  |    '------------ type (0x201) | ||||||
|  '----------------- valid bit |  '----------------- valid bit | ||||||
|  |  | ||||||
|                         data (cont) |  | ||||||
| |--      32      --|--      32      --|--      32      --| |  | ||||||
| |--      32      --|--      32      --|--      32      --| |  | ||||||
|           ^- block count     ^- name max        ^- file max |  | ||||||
|  |  | ||||||
|      data (cont) |  | ||||||
| |--      32      --] |  | ||||||
| |--      32      --] |  | ||||||
|           ^- attr max |  | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Superblock fields: | Superblock fields: | ||||||
|  |  | ||||||
| - **Magic string (8-bytes)** - Magic string indicating the presence of littlefs | 1. **Magic string (8-bytes)** - Magic string indicating the presence of | ||||||
|   on the device. Must be the string "littlefs". |    littlefs on the device. Must be the string "littlefs". | ||||||
|  |  | ||||||
| - **Version (32-bits)** - The version of littlefs at format time. The version | 2. **Version (32-bits)** - The version of littlefs at format time. The version | ||||||
|    is encoded in a 32-bit value with the upper 16-bits containing the major |    is encoded in a 32-bit value with the upper 16-bits containing the major | ||||||
|    version, and the lower 16-bits containing the minor version. |    version, and the lower 16-bits containing the minor version. | ||||||
|  |  | ||||||
|    This specification describes version 2.0 (`0x00020000`). |    This specification describes version 2.0 (`0x00020000`). | ||||||
|  |  | ||||||
| - **Block size (32-bits)** - Size of the logical block size used by the | 3. **Block size (32-bits)** - Size of the logical block size used by the | ||||||
|    filesystem in bytes. |    filesystem in bytes. | ||||||
|  |  | ||||||
| - **Block count (32-bits)** - Number of blocks in the filesystem. | 4. **Block count (32-bits)** - Number of blocks in the filesystem. | ||||||
|  |  | ||||||
| - **Name max (32-bits)** - Maximum size of file names in bytes. | 5. **Name max (32-bits)** - Maximum size of file names in bytes. | ||||||
|  |  | ||||||
| - **File max (32-bits)** - Maximum size of files in bytes. | 6. **File max (32-bits)** - Maximum size of files in bytes. | ||||||
|  |  | ||||||
| - **Attr max (32-bits)** - Maximum size of file attributes in bytes. | 7. **Attr max (32-bits)** - Maximum size of file attributes in bytes. | ||||||
|  |  | ||||||
| The superblock must always be the first entry (id 0) in a metdata pair as well | 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 | as be the first entry written to the block. This means that the superblock | ||||||
| entry can be read from a device using offsets alone. | entry can be read from a device using offsets alone. | ||||||
|  |  | ||||||
| @@ -419,7 +412,7 @@ Associates the id with an on-disk data structure. | |||||||
| The exact layout of the data depends on the data structure type stored in the | The exact layout of the data depends on the data structure type stored in the | ||||||
| chunk field and can be one of the following. | chunk field and can be one of the following. | ||||||
|  |  | ||||||
| Any type of struct supercedes all other structs associated with the id. For | Any type of struct supersedes all other structs associated with the id. For | ||||||
| example, appending a ctz-struct replaces an inline-struct on the same file. | example, appending a ctz-struct replaces an inline-struct on the same file. | ||||||
|  |  | ||||||
| --- | --- | ||||||
| @@ -433,10 +426,11 @@ each pair containing any number of files in alphabetical order. | |||||||
| ``` | ``` | ||||||
|      | |      | | ||||||
|      v |      v | ||||||
| .--------.  .--------.  .--------.  .--------.  .--------.  .--------. |  .--------.  .--------.  .--------.  .--------.  .--------.  .--------. | ||||||
| | file A |->| file D |->| file G |->| file I |->| file J |->| file M | | .| file A |->| file D |->| file G |->| file I |->| file J |->| file M | | ||||||
| | file B |  | file E |  | file H |  |        |  | file K |  | file N | | || file B | || file E | || file H | ||        | || file K | || file N | | ||||||
| | file C |  | file F |  |        |  |        |  | file L |  |        | | || file C | || file F | ||        | ||        | || file L | ||        | | ||||||
|  | |'--------' |'--------' |'--------' |'--------' |'--------' |'--------' | ||||||
| '--------'  '--------'  '--------'  '--------'  '--------'  '--------' | '--------'  '--------'  '--------'  '--------'  '--------'  '--------' | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| @@ -460,7 +454,7 @@ Layout of the dir-struct tag: | |||||||
|  |  | ||||||
| Dir-struct fields: | Dir-struct fields: | ||||||
|  |  | ||||||
| - **Metadata pair (8-bytes)** - Pointer to the first metadata-pair | 1. **Metadata pair (8-bytes)** - Pointer to the first metadata-pair | ||||||
|    in the directory. |    in the directory. | ||||||
|  |  | ||||||
| --- | --- | ||||||
| @@ -468,7 +462,7 @@ Dir-struct fields: | |||||||
|  |  | ||||||
| Gives the id an inline data structure. | Gives the id an inline data structure. | ||||||
|  |  | ||||||
| Inline structs store small files that can fit in the metdata pair. In this | Inline structs store small files that can fit in the metadata pair. In this | ||||||
| case, the file data is stored directly in the tag's data area. | case, the file data is stored directly in the tag's data area. | ||||||
|  |  | ||||||
| Layout of the inline-struct tag: | Layout of the inline-struct tag: | ||||||
| @@ -485,7 +479,7 @@ Layout of the inline-struct tag: | |||||||
|  |  | ||||||
| Inline-struct fields: | Inline-struct fields: | ||||||
|  |  | ||||||
| - **Inline data** - File data stored directly in the metadata-pair. | 1. **Inline data** - File data stored directly in the metadata-pair. | ||||||
|  |  | ||||||
| --- | --- | ||||||
| #### `0x202` LFS_TYPE_CTZSTRUCT | #### `0x202` LFS_TYPE_CTZSTRUCT | ||||||
| @@ -497,12 +491,13 @@ are stored in a skip-list in reverse, with a pointer to the head of the | |||||||
| skip-list. Note that the head of the skip-list and the file size is enough | skip-list. Note that the head of the skip-list and the file size is enough | ||||||
| information to read the file. | information to read the file. | ||||||
|  |  | ||||||
| How exactly CTZ skip-lists work is a bit complicted. A full explanation can be | How exactly CTZ skip-lists work is a bit complicated. A full explanation can be | ||||||
| found in the [DESIGN.md](DESIGN.md#ctz-skip-lists). | found in the [DESIGN.md](DESIGN.md#ctz-skip-lists). | ||||||
|  |  | ||||||
| A quick summary: For every nth block where n is divisible by 2^x, the block | A quick summary: For every _n_‍th block where _n_ is divisible by | ||||||
| contains a pointer to block n-2^x. These pointers are stored in increasing | 2‍_ˣ_, that block contains a pointer to block _n_-2‍_ˣ_. | ||||||
| order of x in each block of the file before the actual data. | These pointers are stored in increasing order of _x_ in each block of the file | ||||||
|  | before the actual data. | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
|                                                                | |                                                                | | ||||||
| @@ -536,10 +531,10 @@ Layout of the CTZ-struct tag: | |||||||
|  |  | ||||||
| CTZ-struct fields: | CTZ-struct fields: | ||||||
|  |  | ||||||
| - **File head (32-bits)** - Pointer to the block that is the head of the | 1. **File head (32-bits)** - Pointer to the block that is the head of the | ||||||
|    file's CTZ skip-list. |    file's CTZ skip-list. | ||||||
|  |  | ||||||
| - **File size (32-bits)** - Size of the file in bytes. | 2. **File size (32-bits)** - Size of the file in bytes. | ||||||
|  |  | ||||||
| --- | --- | ||||||
| #### `0x3xx` LFS_TYPE_USERATTR | #### `0x3xx` LFS_TYPE_USERATTR | ||||||
| @@ -571,9 +566,9 @@ Layout of the user-attr tag: | |||||||
|  |  | ||||||
| User-attr fields: | User-attr fields: | ||||||
|  |  | ||||||
| - **Attr type (8-bits)** - Type of the user attributes. | 1. **Attr type (8-bits)** - Type of the user attributes. | ||||||
|  |  | ||||||
| - **Attr data** - The data associated with the user attribute. | 2. **Attr data** - The data associated with the user attribute. | ||||||
|  |  | ||||||
| --- | --- | ||||||
| #### `0x6xx` LFS_TYPE_TAIL | #### `0x6xx` LFS_TYPE_TAIL | ||||||
| @@ -587,20 +582,22 @@ which indicates if the following metadata pair is a part of the directory | |||||||
|  |  | ||||||
| ``` | ``` | ||||||
|          .--------. |          .--------. | ||||||
|          | dir A  |-. |         .| dir A  |-. | ||||||
|          |softtail| | |         ||softtail| | | ||||||
| .--------|        |-' | .--------|        |-' | ||||||
| |        '--------'   | |       |'--------' | ||||||
|  | |       '---|--|-' | ||||||
| |        .-'    '-------------. | |        .-'    '-------------. | ||||||
| |       v                      v | |       v                      v | ||||||
| |  .--------.  .--------.  .--------. | |  .--------.  .--------.  .--------. | ||||||
| '->| dir B  |->| dir B  |->| dir C  | | '->| dir B  |->| dir B  |->| dir C  | | ||||||
|    |hardtail|  |softtail|  |        | |   ||hardtail| ||softtail| ||        | | ||||||
|    |        |  |        |  |        | |   ||        | ||        | ||        | | ||||||
|  |   |'--------' |'--------' |'--------' | ||||||
|   '--------'  '--------'  '--------' |   '--------'  '--------'  '--------' | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Currently any type supercedes any other preceding tails in the metadata pair, | Currently any type supersedes any other preceding tails in the metadata pair, | ||||||
| but this may change if additional metadata pair state is added. | but this may change if additional metadata pair state is added. | ||||||
|  |  | ||||||
| A note about the metadata pair linked-list: Normally, this linked-list contains | A note about the metadata pair linked-list: Normally, this linked-list contains | ||||||
| @@ -611,9 +608,9 @@ exactly this flag is stored is described below. | |||||||
|  |  | ||||||
| When the sync flag is set: | When the sync flag is set: | ||||||
|  |  | ||||||
| - The linked-list may contain an orphaned directory that has been removed in | 1. The linked-list may contain an orphaned directory that has been removed in | ||||||
|    the filesystem. |    the filesystem. | ||||||
| - The linked-list may contain a metadata pair with a bad block that has been | 2. The linked-list may contain a metadata pair with a bad block that has been | ||||||
|    replaced in the filesystem. |    replaced in the filesystem. | ||||||
|  |  | ||||||
| If the sync flag is set, the threaded linked-list must be checked for these | If the sync flag is set, the threaded linked-list must be checked for these | ||||||
| @@ -635,9 +632,9 @@ Layout of the tail tag: | |||||||
|  |  | ||||||
| Tail fields: | Tail fields: | ||||||
|  |  | ||||||
| - **Tail type (8-bits)** - Type of the tail pointer. | 1. **Tail type (8-bits)** - Type of the tail pointer. | ||||||
|  |  | ||||||
| - **Metadata pair (8-bytes)** - Pointer to the next metadata-pair. | 2. **Metadata pair (8-bytes)** - Pointer to the next metadata-pair. | ||||||
|  |  | ||||||
| --- | --- | ||||||
| #### `0x600` LFS_TYPE_SOFTTAIL | #### `0x600` LFS_TYPE_SOFTTAIL | ||||||
| @@ -668,18 +665,18 @@ littlefs has a concept of "global state". This is a small set of state that | |||||||
| can be updated by a commit to _any_ metadata pair in the filesystem. | can be updated by a commit to _any_ metadata pair in the filesystem. | ||||||
|  |  | ||||||
| The way this works is that the global state is stored as a set of deltas | The way this works is that the global state is stored as a set of deltas | ||||||
| distributed across the filesystem such that the global state can by found by | distributed across the filesystem such that the global state can be found by | ||||||
| the xor-sum of these deltas. | the xor-sum of these deltas. | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
| .--------.  .--------.  .--------.  .--------.  .--------. |  .--------.  .--------.  .--------.  .--------.  .--------. | ||||||
| |        |->| gstate |->|        |->| gstate |->| gstate | | .|        |->| gdelta |->|        |->| gdelta |->| gdelta | | ||||||
| |        |  | 0x23   |  |        |  | 0xff   |  | 0xce   | | ||        | || 0x23   | ||        | || 0xff   | || 0xce   | | ||||||
| |        |  |        |  |        |  |        |  |        | | ||        | ||        | ||        | ||        | ||        | | ||||||
| '--------'  '--------'  '--------'  '--------'  '--------' | |'--------' |'--------' |'--------' |'--------' |'--------' | ||||||
|                 |                       |           | | '--------'  '----|---'  '--------'  '----|---'  '----|---' | ||||||
|                  v                       v           v |                  v                       v           v | ||||||
|       0x00 --> xor ------------------> xor ------> xor --> gstate 0x12 |        0x00 --> xor ------------------> xor ------> xor --> gstate = 0x12 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Note that storing globals this way is very expensive in terms of storage usage, | Note that storing globals this way is very expensive in terms of storage usage, | ||||||
| @@ -730,16 +727,16 @@ Layout of the move state: | |||||||
|  |  | ||||||
| Move state fields: | Move state fields: | ||||||
|  |  | ||||||
| - **Sync bit (1-bit)** - Indicates if the metadata pair threaded linked-list is | 1. **Sync bit (1-bit)** - Indicates if the metadata pair threaded linked-list | ||||||
|   in-sync. If set, the threaded linked-list should be checked for errors. |    is in-sync. If set, the threaded linked-list should be checked for errors. | ||||||
|  |  | ||||||
| - **Move type (11-bits)** - Type of move being performed. Must be either | 2. **Move type (11-bits)** - Type of move being performed. Must be either | ||||||
|    `0x000`, indicating no move, or `0x4ff` indicating the source file should |    `0x000`, indicating no move, or `0x4ff` indicating the source file should | ||||||
|    be deleted. |    be deleted. | ||||||
|  |  | ||||||
| - **Move id (10-bits)** - The file id being moved. | 3. **Move id (10-bits)** - The file id being moved. | ||||||
|  |  | ||||||
| - **Metadata pair (8-bytes)** - Pointer to the metadata-pair containing | 4. **Metadata pair (8-bytes)** - Pointer to the metadata-pair containing | ||||||
|    the move. |    the move. | ||||||
|  |  | ||||||
| --- | --- | ||||||
| @@ -778,13 +775,13 @@ Layout of the CRC tag: | |||||||
|  |  | ||||||
| CRC fields: | CRC fields: | ||||||
|  |  | ||||||
| - **Valid state (1-bit)** - Indicates the expected value of the valid bit for | 1. **Valid state (1-bit)** - Indicates the expected value of the valid bit for | ||||||
|    any tags in the next commit. |    any tags in the next commit. | ||||||
|  |  | ||||||
| - **CRC (32-bits)** - CRC-32 with a polynomial of `0x04c11db7` initialized with | 2. **CRC (32-bits)** - CRC-32 with a polynomial of `0x04c11db7` initialized | ||||||
|   `0xffffffff`. |    with `0xffffffff`. | ||||||
|  |  | ||||||
| - **Padding** - Padding to the next program-aligned boundary. No guarantees are | 3. **Padding** - Padding to the next program-aligned boundary. No guarantees | ||||||
|   made about the contents. |    are made about the contents. | ||||||
|  |  | ||||||
| --- | --- | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user