mirror of
https://github.com/littlefs-project/littlefs.git
synced 2025-11-16 12:34:34 +00: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
|
||||||
|
|||||||
271
SPEC.md
271
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,14 +90,14 @@ 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`.
|
||||||
|
|
||||||
Entries themselves are stored as a 32-bit tag followed by a variable length
|
Entries themselves are stored as a 32-bit tag followed by a variable length
|
||||||
blob of data. But exactly how these tags are stored is a little bit tricky.
|
blob of data. But exactly how these tags are stored is a little bit tricky.
|
||||||
@@ -159,7 +158,7 @@ Here's a more complete example of metadata block containing 4 entries:
|
|||||||
| | | || |
|
| | | || |
|
||||||
| |-------------------+-------------------| || |
|
| |-------------------+-------------------| || |
|
||||||
| | tag CxCRC | CRC | || /
|
| | tag CxCRC | CRC | || /
|
||||||
| |-------------------+-------------------| ||
|
| |-------------------+-------------------| ||
|
||||||
| | tag CRCxA' | data A' | || \
|
| | tag CRCxA' | data A' | || \
|
||||||
| |-------------------+ | || |
|
| |-------------------+ | || |
|
||||||
| | | || |
|
| | | || |
|
||||||
@@ -167,7 +166,7 @@ Here's a more complete example of metadata block containing 4 entries:
|
|||||||
| | | tag CRCxA' | | || |
|
| | | tag CRCxA' | | || |
|
||||||
| |--------------+-------------------+----| || |
|
| |--------------+-------------------+----| || |
|
||||||
| | CRC | padding | || /
|
| | CRC | padding | || /
|
||||||
| |--------------+----+-------------------| ||
|
| |--------------+----+-------------------| ||
|
||||||
| | tag CRCxA'' | data A'' | <---. \
|
| | tag CRCxA'' | data A'' | <---. \
|
||||||
| |-------------------+ | ||| |
|
| |-------------------+ | ||| |
|
||||||
| | | ||| |
|
| | | ||| |
|
||||||
@@ -179,12 +178,12 @@ Here's a more complete example of metadata block containing 4 entries:
|
|||||||
| | | tag Dx| |||| |
|
| | | tag Dx| |||| |
|
||||||
| |---------+-------------------+---------| |||| |
|
| |---------+-------------------+---------| |||| |
|
||||||
| |CRC | CRC | | |||| /
|
| |CRC | CRC | | |||| /
|
||||||
| |---------+-------------------+ | ||||
|
| |---------+-------------------+ | ||||
|
||||||
| | unwritten storage | |||| more commits
|
| | unwritten storage | |||| more commits
|
||||||
| | | |||| |
|
| | | |||| |
|
||||||
| | | |||| v
|
| | | |||| v
|
||||||
| | | ||||
|
| | | ||||
|
||||||
| | | ||||
|
| | | ||||
|
||||||
| '---------------------------------------' ||||
|
| '---------------------------------------' ||||
|
||||||
'---------------------------------------' |||'- most recent A
|
'---------------------------------------' |||'- most recent A
|
||||||
||'-- most recent B
|
||'-- most recent B
|
||||||
@@ -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,26 +227,26 @@ 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
|
||||||
|
|
||||||
@@ -274,7 +273,7 @@ array of files.
|
|||||||
---
|
---
|
||||||
#### `0x0xx` LFS_TYPE_NAME
|
#### `0x0xx` LFS_TYPE_NAME
|
||||||
|
|
||||||
Associates the id with a file name and file type.
|
Associates the id with a file name and file type.
|
||||||
|
|
||||||
The data contains the file name stored as an ASCII string (may be expanded to
|
The data contains the file name stored as an ASCII string (may be expanded to
|
||||||
UTF8 in the future).
|
UTF8 in the future).
|
||||||
@@ -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,14 +334,15 @@ 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
|
||||||
```
|
```
|
||||||
|
|
||||||
The filesystem starts with only the root directory. The superblock metadata
|
The filesystem starts with only the root directory. The superblock metadata
|
||||||
@@ -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.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -431,12 +424,13 @@ Directories in littlefs are stored on disk as a linked-list of metadata pairs,
|
|||||||
each pair containing any number of files in alphabetical order.
|
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,15 +454,15 @@ 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.
|
||||||
|
|
||||||
---
|
---
|
||||||
#### `0x201` LFS_TYPE_INLINESTRUCT
|
#### `0x201` LFS_TYPE_INLINESTRUCT
|
||||||
|
|
||||||
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,15 +531,15 @@ 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
|
||||||
|
|
||||||
Attaches a user attribute to an id.
|
Attaches a user attribute to an id.
|
||||||
|
|
||||||
littlefs has a concept of "user attributes". These are small user-provided
|
littlefs has a concept of "user attributes". These are small user-provided
|
||||||
attributes that can be used to store things like timestamps, hashes,
|
attributes that can be used to store things like timestamps, hashes,
|
||||||
@@ -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
|
||||||
@@ -586,21 +581,23 @@ which indicates if the following metadata pair is a part of the directory
|
|||||||
(hard-tail) or only used to traverse the filesystem (soft-tail).
|
(hard-tail) or only used to traverse the filesystem (soft-tail).
|
||||||
|
|
||||||
```
|
```
|
||||||
.--------.
|
.--------.
|
||||||
| 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,10 +608,10 @@ 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
|
||||||
errors before it can be used reliably. Note that the threaded linked-list can
|
errors before it can be used reliably. Note that the threaded linked-list can
|
||||||
@@ -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,17 +727,17 @@ 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.
|
||||||
|
|
||||||
---
|
---
|
||||||
#### `0x5xx` LFS_TYPE_CRC
|
#### `0x5xx` LFS_TYPE_CRC
|
||||||
@@ -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