119ea8026Sopenharmony_ci## littlefs technical specification
219ea8026Sopenharmony_ci
319ea8026Sopenharmony_ciThis is the technical specification of the little filesystem with on-disk
419ea8026Sopenharmony_civersion lfs2.1. This document covers the technical details of how the littlefs
519ea8026Sopenharmony_ciis stored on disk for introspection and tooling. This document assumes you are
619ea8026Sopenharmony_cifamiliar with the design of the littlefs, for more info on how littlefs works
719ea8026Sopenharmony_cicheck out [DESIGN.md](DESIGN.md).
819ea8026Sopenharmony_ci
919ea8026Sopenharmony_ci```
1019ea8026Sopenharmony_ci   | | |     .---._____
1119ea8026Sopenharmony_ci  .-----.   |          |
1219ea8026Sopenharmony_ci--|o    |---| littlefs |
1319ea8026Sopenharmony_ci--|     |---|          |
1419ea8026Sopenharmony_ci  '-----'   '----------'
1519ea8026Sopenharmony_ci   | | |
1619ea8026Sopenharmony_ci```
1719ea8026Sopenharmony_ci
1819ea8026Sopenharmony_ci## Some quick notes
1919ea8026Sopenharmony_ci
2019ea8026Sopenharmony_ci- littlefs is a block-based filesystem. The disk is divided into an array of
2119ea8026Sopenharmony_ci  evenly sized blocks that are used as the logical unit of storage.
2219ea8026Sopenharmony_ci
2319ea8026Sopenharmony_ci- Block pointers are stored in 32 bits, with the special value `0xffffffff`
2419ea8026Sopenharmony_ci  representing a null block address.
2519ea8026Sopenharmony_ci
2619ea8026Sopenharmony_ci- In addition to the logical block size (which usually matches the erase
2719ea8026Sopenharmony_ci  block size), littlefs also uses a program block size and read block size.
2819ea8026Sopenharmony_ci  These determine the alignment of block device operations, but don't need
2919ea8026Sopenharmony_ci  to be consistent for portability.
3019ea8026Sopenharmony_ci
3119ea8026Sopenharmony_ci- By default, all values in littlefs are stored in little-endian byte order.
3219ea8026Sopenharmony_ci
3319ea8026Sopenharmony_ci## Directories / Metadata pairs
3419ea8026Sopenharmony_ci
3519ea8026Sopenharmony_ciMetadata pairs form the backbone of littlefs and provide a system for
3619ea8026Sopenharmony_cidistributed atomic updates. Even the superblock is stored in a metadata pair.
3719ea8026Sopenharmony_ci
3819ea8026Sopenharmony_ciAs their name suggests, a metadata pair is stored in two blocks, with one block
3919ea8026Sopenharmony_ciproviding a backup during erase cycles in case power is lost. These two blocks
4019ea8026Sopenharmony_ciare not necessarily sequential and may be anywhere on disk, so a "pointer" to a
4119ea8026Sopenharmony_cimetadata pair is stored as two block pointers.
4219ea8026Sopenharmony_ci
4319ea8026Sopenharmony_ciOn top of this, each metadata block behaves as an appendable log, containing a
4419ea8026Sopenharmony_civariable number of commits. Commits can be appended to the metadata log in
4519ea8026Sopenharmony_ciorder to update the metadata without requiring an erase cycles. Note that
4619ea8026Sopenharmony_cisuccessive commits may supersede the metadata in previous commits. Only the
4719ea8026Sopenharmony_cimost recent metadata should be considered valid.
4819ea8026Sopenharmony_ci
4919ea8026Sopenharmony_ciThe high-level layout of a metadata block is fairly simple:
5019ea8026Sopenharmony_ci
5119ea8026Sopenharmony_ci```
5219ea8026Sopenharmony_ci  .---------------------------------------.
5319ea8026Sopenharmony_ci.-|  revision count   |      entries      |  \
5419ea8026Sopenharmony_ci| |-------------------+                   |  |
5519ea8026Sopenharmony_ci| |                                       |  |
5619ea8026Sopenharmony_ci| |                                       |  +-- 1st commit
5719ea8026Sopenharmony_ci| |                                       |  |
5819ea8026Sopenharmony_ci| |                   +-------------------|  |
5919ea8026Sopenharmony_ci| |                   |        CRC        |  /
6019ea8026Sopenharmony_ci| |-------------------+-------------------|
6119ea8026Sopenharmony_ci| |                entries                |  \
6219ea8026Sopenharmony_ci| |                                       |  |
6319ea8026Sopenharmony_ci| |                                       |  +-- 2nd commit
6419ea8026Sopenharmony_ci| |    +-------------------+--------------|  |
6519ea8026Sopenharmony_ci| |    |        CRC        |    padding   |  /
6619ea8026Sopenharmony_ci| |----+-------------------+--------------|
6719ea8026Sopenharmony_ci| |                entries                |  \
6819ea8026Sopenharmony_ci| |                                       |  |
6919ea8026Sopenharmony_ci| |                                       |  +-- 3rd commit
7019ea8026Sopenharmony_ci| |         +-------------------+---------|  |
7119ea8026Sopenharmony_ci| |         |        CRC        |         |  /
7219ea8026Sopenharmony_ci| |---------+-------------------+         |
7319ea8026Sopenharmony_ci| |           unwritten storage           |  more commits
7419ea8026Sopenharmony_ci| |                                       |       |
7519ea8026Sopenharmony_ci| |                                       |       v
7619ea8026Sopenharmony_ci| |                                       |
7719ea8026Sopenharmony_ci| |                                       |
7819ea8026Sopenharmony_ci| '---------------------------------------'
7919ea8026Sopenharmony_ci'---------------------------------------'
8019ea8026Sopenharmony_ci```
8119ea8026Sopenharmony_ci
8219ea8026Sopenharmony_ciEach metadata block contains a 32-bit revision count followed by a number of
8319ea8026Sopenharmony_cicommits. Each commit contains a variable number of metadata entries followed
8419ea8026Sopenharmony_ciby a 32-bit CRC.
8519ea8026Sopenharmony_ci
8619ea8026Sopenharmony_ciNote also that entries aren't necessarily word-aligned. This allows us to
8719ea8026Sopenharmony_cistore metadata more compactly, however we can only write to addresses that are
8819ea8026Sopenharmony_cialigned to our program block size. This means each commit may have padding for
8919ea8026Sopenharmony_cialignment.
9019ea8026Sopenharmony_ci
9119ea8026Sopenharmony_ciMetadata block fields:
9219ea8026Sopenharmony_ci
9319ea8026Sopenharmony_ci1. **Revision count (32-bits)** - Incremented every erase cycle. If both blocks
9419ea8026Sopenharmony_ci   contain valid commits, only the block with the most recent revision count
9519ea8026Sopenharmony_ci   should be used. Sequence comparison must be used to avoid issues with
9619ea8026Sopenharmony_ci   integer overflow.
9719ea8026Sopenharmony_ci
9819ea8026Sopenharmony_ci2. **CRC (32-bits)** - Detects corruption from power-loss or other write
9919ea8026Sopenharmony_ci   issues.  Uses a CRC-32 with a polynomial of `0x04c11db7` initialized
10019ea8026Sopenharmony_ci   with `0xffffffff`.
10119ea8026Sopenharmony_ci
10219ea8026Sopenharmony_ciEntries themselves are stored as a 32-bit tag followed by a variable length
10319ea8026Sopenharmony_ciblob of data. But exactly how these tags are stored is a little bit tricky.
10419ea8026Sopenharmony_ci
10519ea8026Sopenharmony_ciMetadata blocks support both forward and backward iteration. In order to do
10619ea8026Sopenharmony_cithis without duplicating the space for each tag, neighboring entries have their
10719ea8026Sopenharmony_citags XORed together, starting with `0xffffffff`.
10819ea8026Sopenharmony_ci
10919ea8026Sopenharmony_ci```
11019ea8026Sopenharmony_ci Forward iteration                        Backward iteration
11119ea8026Sopenharmony_ci
11219ea8026Sopenharmony_ci.-------------------.  0xffffffff        .-------------------.
11319ea8026Sopenharmony_ci|  revision count   |      |             |  revision count   |
11419ea8026Sopenharmony_ci|-------------------|      v             |-------------------|
11519ea8026Sopenharmony_ci|      tag ~A       |---> xor -> tag A   |      tag ~A       |---> xor -> 0xffffffff
11619ea8026Sopenharmony_ci|-------------------|      |             |-------------------|      ^
11719ea8026Sopenharmony_ci|       data A      |      |             |       data A      |      |
11819ea8026Sopenharmony_ci|                   |      |             |                   |      |
11919ea8026Sopenharmony_ci|                   |      |             |                   |      |
12019ea8026Sopenharmony_ci|-------------------|      v             |-------------------|      |
12119ea8026Sopenharmony_ci|      tag AxB      |---> xor -> tag B   |      tag AxB      |---> xor -> tag A
12219ea8026Sopenharmony_ci|-------------------|      |             |-------------------|      ^
12319ea8026Sopenharmony_ci|       data B      |      |             |       data B      |      |
12419ea8026Sopenharmony_ci|                   |      |             |                   |      |
12519ea8026Sopenharmony_ci|                   |      |             |                   |      |
12619ea8026Sopenharmony_ci|-------------------|      v             |-------------------|      |
12719ea8026Sopenharmony_ci|      tag BxC      |---> xor -> tag C   |      tag BxC      |---> xor -> tag B
12819ea8026Sopenharmony_ci|-------------------|                    |-------------------|      ^
12919ea8026Sopenharmony_ci|       data C      |                    |       data C      |      |
13019ea8026Sopenharmony_ci|                   |                    |                   |    tag C
13119ea8026Sopenharmony_ci|                   |                    |                   |
13219ea8026Sopenharmony_ci|                   |                    |                   |
13319ea8026Sopenharmony_ci'-------------------'                    '-------------------'
13419ea8026Sopenharmony_ci```
13519ea8026Sopenharmony_ci
13619ea8026Sopenharmony_ciHere's a more complete example of metadata block containing 4 entries:
13719ea8026Sopenharmony_ci
13819ea8026Sopenharmony_ci```
13919ea8026Sopenharmony_ci  .---------------------------------------.
14019ea8026Sopenharmony_ci.-|  revision count   |      tag ~A       |        \
14119ea8026Sopenharmony_ci| |-------------------+-------------------|        |
14219ea8026Sopenharmony_ci| |                 data A                |        |
14319ea8026Sopenharmony_ci| |                                       |        |
14419ea8026Sopenharmony_ci| |-------------------+-------------------|        |
14519ea8026Sopenharmony_ci| |      tag AxB      |       data B      | <--.   |
14619ea8026Sopenharmony_ci| |-------------------+                   |    |   |
14719ea8026Sopenharmony_ci| |                                       |    |   +-- 1st commit
14819ea8026Sopenharmony_ci| |         +-------------------+---------|    |   |
14919ea8026Sopenharmony_ci| |         |      tag BxC      |         | <-.|   |
15019ea8026Sopenharmony_ci| |---------+-------------------+         |   ||   |
15119ea8026Sopenharmony_ci| |                 data C                |   ||   |
15219ea8026Sopenharmony_ci| |                                       |   ||   |
15319ea8026Sopenharmony_ci| |-------------------+-------------------|   ||   |
15419ea8026Sopenharmony_ci| |     tag CxCRC     |        CRC        |   ||   /
15519ea8026Sopenharmony_ci| |-------------------+-------------------|   ||
15619ea8026Sopenharmony_ci| |     tag CRCxA'    |      data A'      |   ||   \
15719ea8026Sopenharmony_ci| |-------------------+                   |   ||   |
15819ea8026Sopenharmony_ci| |                                       |   ||   |
15919ea8026Sopenharmony_ci| |              +-------------------+----|   ||   +-- 2nd commit
16019ea8026Sopenharmony_ci| |              |     tag CRCxA'    |    |   ||   |
16119ea8026Sopenharmony_ci| |--------------+-------------------+----|   ||   |
16219ea8026Sopenharmony_ci| | CRC          |        padding         |   ||   /
16319ea8026Sopenharmony_ci| |--------------+----+-------------------|   ||
16419ea8026Sopenharmony_ci| |     tag CRCxA''   |      data A''     | <---.  \
16519ea8026Sopenharmony_ci| |-------------------+                   |   |||  |
16619ea8026Sopenharmony_ci| |                                       |   |||  |
16719ea8026Sopenharmony_ci| |         +-------------------+---------|   |||  |
16819ea8026Sopenharmony_ci| |         |     tag A''xD     |         | < |||  |
16919ea8026Sopenharmony_ci| |---------+-------------------+         |  ||||  +-- 3rd commit
17019ea8026Sopenharmony_ci| |                data D                 |  ||||  |
17119ea8026Sopenharmony_ci| |                             +---------|  ||||  |
17219ea8026Sopenharmony_ci| |                             |   tag Dx|  ||||  |
17319ea8026Sopenharmony_ci| |---------+-------------------+---------|  ||||  |
17419ea8026Sopenharmony_ci| |CRC      |        CRC        |         |  ||||  /
17519ea8026Sopenharmony_ci| |---------+-------------------+         |  ||||
17619ea8026Sopenharmony_ci| |           unwritten storage           |  ||||  more commits
17719ea8026Sopenharmony_ci| |                                       |  ||||       |
17819ea8026Sopenharmony_ci| |                                       |  ||||       v
17919ea8026Sopenharmony_ci| |                                       |  ||||
18019ea8026Sopenharmony_ci| |                                       |  ||||
18119ea8026Sopenharmony_ci| '---------------------------------------'  ||||
18219ea8026Sopenharmony_ci'---------------------------------------'    |||'- most recent A
18319ea8026Sopenharmony_ci                                             ||'-- most recent B
18419ea8026Sopenharmony_ci                                             |'--- most recent C
18519ea8026Sopenharmony_ci                                             '---- most recent D
18619ea8026Sopenharmony_ci```
18719ea8026Sopenharmony_ci
18819ea8026Sopenharmony_ciTwo things to note before we get into the details around tag encoding:
18919ea8026Sopenharmony_ci
19019ea8026Sopenharmony_ci1. Each tag contains a valid bit used to indicate if the tag and containing
19119ea8026Sopenharmony_ci   commit is valid. After XORing, this bit should always be zero.
19219ea8026Sopenharmony_ci
19319ea8026Sopenharmony_ci   At the end of each commit, the valid bit of the previous tag is XORed
19419ea8026Sopenharmony_ci   with the lowest bit in the type field of the CRC tag. This allows
19519ea8026Sopenharmony_ci   the CRC tag to force the next commit to fail the valid bit test if it
19619ea8026Sopenharmony_ci   has not yet been written to.
19719ea8026Sopenharmony_ci
19819ea8026Sopenharmony_ci2. The valid bit alone is not enough info to know if the next commit has been
19919ea8026Sopenharmony_ci   erased. We don't know the order bits will be programmed in a program block,
20019ea8026Sopenharmony_ci   so it's possible that the next commit had an attempted program that left the
20119ea8026Sopenharmony_ci   valid bit unchanged.
20219ea8026Sopenharmony_ci
20319ea8026Sopenharmony_ci   To ensure we only ever program erased bytes, each commit can contain an
20419ea8026Sopenharmony_ci   optional forward-CRC (FCRC). An FCRC contains a checksum of some amount of
20519ea8026Sopenharmony_ci   bytes in the next commit at the time it was erased.
20619ea8026Sopenharmony_ci
20719ea8026Sopenharmony_ci   ```
20819ea8026Sopenharmony_ci   .-------------------. \      \
20919ea8026Sopenharmony_ci   |  revision count   | |      |
21019ea8026Sopenharmony_ci   |-------------------| |      |
21119ea8026Sopenharmony_ci   |     metadata      | |      |
21219ea8026Sopenharmony_ci   |                   | +---.  +-- current commit
21319ea8026Sopenharmony_ci   |                   | |   |  |
21419ea8026Sopenharmony_ci   |-------------------| |   |  |
21519ea8026Sopenharmony_ci   |       FCRC       ---|-. |  |
21619ea8026Sopenharmony_ci   |-------------------| / | |  |
21719ea8026Sopenharmony_ci   |        CRC       -----|-'  /
21819ea8026Sopenharmony_ci   |-------------------|   |
21919ea8026Sopenharmony_ci   |      padding      |   |        padding (does't need CRC)
22019ea8026Sopenharmony_ci   |                   |   |
22119ea8026Sopenharmony_ci   |-------------------| \ |    \
22219ea8026Sopenharmony_ci   |      erased?      | +-'    |
22319ea8026Sopenharmony_ci   |         |         | |      +-- next commit
22419ea8026Sopenharmony_ci   |         v         | /      |
22519ea8026Sopenharmony_ci   |                   |        /
22619ea8026Sopenharmony_ci   |                   |
22719ea8026Sopenharmony_ci   '-------------------'
22819ea8026Sopenharmony_ci   ```
22919ea8026Sopenharmony_ci
23019ea8026Sopenharmony_ci   If the FCRC is missing or the checksum does not match, we must assume a
23119ea8026Sopenharmony_ci   commit was attempted but failed due to power-loss.
23219ea8026Sopenharmony_ci
23319ea8026Sopenharmony_ci   Note that end-of-block commits do not need an FCRC.
23419ea8026Sopenharmony_ci
23519ea8026Sopenharmony_ci## Metadata tags
23619ea8026Sopenharmony_ci
23719ea8026Sopenharmony_ciSo in littlefs, 32-bit tags describe every type of metadata. And this means
23819ea8026Sopenharmony_ci_every_ type of metadata, including file entries, directory fields, and
23919ea8026Sopenharmony_ciglobal state. Even the CRCs used to mark the end of commits get their own tag.
24019ea8026Sopenharmony_ci
24119ea8026Sopenharmony_ciBecause of this, the tag format contains some densely packed information. Note
24219ea8026Sopenharmony_cithat there are multiple levels of types which break down into more info:
24319ea8026Sopenharmony_ci
24419ea8026Sopenharmony_ci```
24519ea8026Sopenharmony_ci[----            32             ----]
24619ea8026Sopenharmony_ci[1|--  11   --|--  10  --|--  10  --]
24719ea8026Sopenharmony_ci ^.     ^     .     ^          ^- length
24819ea8026Sopenharmony_ci |.     |     .     '------------ id
24919ea8026Sopenharmony_ci |.     '-----.------------------ type (type3)
25019ea8026Sopenharmony_ci '.-----------.------------------ valid bit
25119ea8026Sopenharmony_ci  [-3-|-- 8 --]
25219ea8026Sopenharmony_ci    ^     ^- chunk
25319ea8026Sopenharmony_ci    '------- type (type1)
25419ea8026Sopenharmony_ci```
25519ea8026Sopenharmony_ci
25619ea8026Sopenharmony_ci
25719ea8026Sopenharmony_ciBefore we go further, there's one important thing to note. These tags are
25819ea8026Sopenharmony_ci**not** stored in little-endian. Tags stored in commits are actually stored
25919ea8026Sopenharmony_ciin big-endian (and is the only thing in littlefs stored in big-endian). This
26019ea8026Sopenharmony_cilittle bit of craziness comes from the fact that the valid bit must be the
26119ea8026Sopenharmony_cifirst bit in a commit, and when converted to little-endian, the valid bit finds
26219ea8026Sopenharmony_ciitself in byte 4. We could restructure the tag to store the valid bit lower,
26319ea8026Sopenharmony_cibut, because none of the fields are byte-aligned, this would be more
26419ea8026Sopenharmony_cicomplicated than just storing the tag in big-endian.
26519ea8026Sopenharmony_ci
26619ea8026Sopenharmony_ciAnother thing to note is that both the tags `0x00000000` and `0xffffffff` are
26719ea8026Sopenharmony_ciinvalid and can be used for null values.
26819ea8026Sopenharmony_ci
26919ea8026Sopenharmony_ciMetadata tag fields:
27019ea8026Sopenharmony_ci
27119ea8026Sopenharmony_ci1. **Valid bit (1-bit)** - Indicates if the tag is valid.
27219ea8026Sopenharmony_ci
27319ea8026Sopenharmony_ci2. **Type3 (11-bits)** - Type of the tag. This field is broken down further
27419ea8026Sopenharmony_ci   into a 3-bit abstract type and an 8-bit chunk field. Note that the value
27519ea8026Sopenharmony_ci   `0x000` is invalid and not assigned a type.
27619ea8026Sopenharmony_ci
27719ea8026Sopenharmony_ci    1. **Type1 (3-bits)** - Abstract type of the tag. Groups the tags into
27819ea8026Sopenharmony_ci       8 categories that facilitate bitmasked lookups.
27919ea8026Sopenharmony_ci
28019ea8026Sopenharmony_ci    2. **Chunk (8-bits)** - Chunk field used for various purposes by the different
28119ea8026Sopenharmony_ci       abstract types.  type1+chunk+id form a unique identifier for each tag in the
28219ea8026Sopenharmony_ci       metadata block.
28319ea8026Sopenharmony_ci
28419ea8026Sopenharmony_ci3. **Id (10-bits)** - File id associated with the tag. Each file in a metadata
28519ea8026Sopenharmony_ci   block gets a unique id which is used to associate tags with that file. The
28619ea8026Sopenharmony_ci   special value `0x3ff` is used for any tags that are not associated with a
28719ea8026Sopenharmony_ci   file, such as directory and global metadata.
28819ea8026Sopenharmony_ci
28919ea8026Sopenharmony_ci4. **Length (10-bits)** - Length of the data in bytes. The special value
29019ea8026Sopenharmony_ci   `0x3ff` indicates that this tag has been deleted.
29119ea8026Sopenharmony_ci
29219ea8026Sopenharmony_ci## Metadata types
29319ea8026Sopenharmony_ci
29419ea8026Sopenharmony_ciWhat follows is an exhaustive list of metadata in littlefs.
29519ea8026Sopenharmony_ci
29619ea8026Sopenharmony_ci---
29719ea8026Sopenharmony_ci#### `0x401` LFS_TYPE_CREATE
29819ea8026Sopenharmony_ci
29919ea8026Sopenharmony_ciCreates a new file with this id. Note that files in a metadata block
30019ea8026Sopenharmony_cidon't necessarily need a create tag. All a create does is move over any
30119ea8026Sopenharmony_cifiles using this id. In this sense a create is similar to insertion into
30219ea8026Sopenharmony_cian imaginary array of files.
30319ea8026Sopenharmony_ci
30419ea8026Sopenharmony_ciThe create and delete tags allow littlefs to keep files in a directory
30519ea8026Sopenharmony_ciordered alphabetically by filename.
30619ea8026Sopenharmony_ci
30719ea8026Sopenharmony_ci---
30819ea8026Sopenharmony_ci#### `0x4ff` LFS_TYPE_DELETE
30919ea8026Sopenharmony_ci
31019ea8026Sopenharmony_ciDeletes the file with this id. An inverse to create, this tag moves over
31119ea8026Sopenharmony_ciany files neighboring this id similar to a deletion from an imaginary
31219ea8026Sopenharmony_ciarray of files.
31319ea8026Sopenharmony_ci
31419ea8026Sopenharmony_ci---
31519ea8026Sopenharmony_ci#### `0x0xx` LFS_TYPE_NAME
31619ea8026Sopenharmony_ci
31719ea8026Sopenharmony_ciAssociates the id with a file name and file type.
31819ea8026Sopenharmony_ci
31919ea8026Sopenharmony_ciThe data contains the file name stored as an ASCII string (may be expanded to
32019ea8026Sopenharmony_ciUTF8 in the future).
32119ea8026Sopenharmony_ci
32219ea8026Sopenharmony_ciThe chunk field in this tag indicates an 8-bit file type which can be one of
32319ea8026Sopenharmony_cithe following.
32419ea8026Sopenharmony_ci
32519ea8026Sopenharmony_ciCurrently, the name tag must precede any other tags associated with the id and
32619ea8026Sopenharmony_cican not be reassigned without deleting the file.
32719ea8026Sopenharmony_ci
32819ea8026Sopenharmony_ciLayout of the name tag:
32919ea8026Sopenharmony_ci
33019ea8026Sopenharmony_ci```
33119ea8026Sopenharmony_ci        tag                          data
33219ea8026Sopenharmony_ci[--      32      --][---        variable length        ---]
33319ea8026Sopenharmony_ci[1| 3| 8 | 10 | 10 ][---          (size * 8)           ---]
33419ea8026Sopenharmony_ci ^  ^  ^    ^    ^- size                   ^- file name
33519ea8026Sopenharmony_ci |  |  |    '------ id
33619ea8026Sopenharmony_ci |  |  '----------- file type
33719ea8026Sopenharmony_ci |  '-------------- type1 (0x0)
33819ea8026Sopenharmony_ci '----------------- valid bit
33919ea8026Sopenharmony_ci```
34019ea8026Sopenharmony_ci
34119ea8026Sopenharmony_ciName fields:
34219ea8026Sopenharmony_ci
34319ea8026Sopenharmony_ci1. **file type (8-bits)** - Type of the file.
34419ea8026Sopenharmony_ci
34519ea8026Sopenharmony_ci2. **file name** - File name stored as an ASCII string.
34619ea8026Sopenharmony_ci
34719ea8026Sopenharmony_ci---
34819ea8026Sopenharmony_ci#### `0x001` LFS_TYPE_REG
34919ea8026Sopenharmony_ci
35019ea8026Sopenharmony_ciInitializes the id + name as a regular file.
35119ea8026Sopenharmony_ci
35219ea8026Sopenharmony_ciHow each file is stored depends on its struct tag, which is described below.
35319ea8026Sopenharmony_ci
35419ea8026Sopenharmony_ci---
35519ea8026Sopenharmony_ci#### `0x002` LFS_TYPE_DIR
35619ea8026Sopenharmony_ci
35719ea8026Sopenharmony_ciInitializes the id + name as a directory.
35819ea8026Sopenharmony_ci
35919ea8026Sopenharmony_ciDirectories in littlefs are stored on disk as a linked-list of metadata pairs,
36019ea8026Sopenharmony_cieach pair containing any number of files in alphabetical order. A pointer to
36119ea8026Sopenharmony_cithe directory is stored in the struct tag, which is described below.
36219ea8026Sopenharmony_ci
36319ea8026Sopenharmony_ci---
36419ea8026Sopenharmony_ci#### `0x0ff` LFS_TYPE_SUPERBLOCK
36519ea8026Sopenharmony_ci
36619ea8026Sopenharmony_ciInitializes the id as a superblock entry.
36719ea8026Sopenharmony_ci
36819ea8026Sopenharmony_ciThe superblock entry is a special entry used to store format-time configuration
36919ea8026Sopenharmony_ciand identify the filesystem.
37019ea8026Sopenharmony_ci
37119ea8026Sopenharmony_ciThe name is a bit of a misnomer. While the superblock entry serves the same
37219ea8026Sopenharmony_cipurpose as a superblock found in other filesystems, in littlefs the superblock
37319ea8026Sopenharmony_cidoes not get a dedicated block. Instead, the superblock entry is duplicated
37419ea8026Sopenharmony_ciacross a linked-list of metadata pairs rooted on the blocks 0 and 1. The last
37519ea8026Sopenharmony_cimetadata pair doubles as the root directory of the filesystem.
37619ea8026Sopenharmony_ci
37719ea8026Sopenharmony_ci```
37819ea8026Sopenharmony_ci .--------.  .--------.  .--------.  .--------.  .--------.
37919ea8026Sopenharmony_ci.| super  |->| super  |->| super  |->| super  |->| file B |
38019ea8026Sopenharmony_ci|| block  | || block  | || block  | || block  | || file C |
38119ea8026Sopenharmony_ci||        | ||        | ||        | || file A | || file D |
38219ea8026Sopenharmony_ci|'--------' |'--------' |'--------' |'--------' |'--------'
38319ea8026Sopenharmony_ci'--------'  '--------'  '--------'  '--------'  '--------'
38419ea8026Sopenharmony_ci
38519ea8026Sopenharmony_ci\----------------+----------------/ \----------+----------/
38619ea8026Sopenharmony_ci          superblock pairs               root directory
38719ea8026Sopenharmony_ci```
38819ea8026Sopenharmony_ci
38919ea8026Sopenharmony_ciThe filesystem starts with only the root directory. The superblock metadata
39019ea8026Sopenharmony_cipairs grow every time the root pair is compacted in order to prolong the
39119ea8026Sopenharmony_cilife of the device exponentially.
39219ea8026Sopenharmony_ci
39319ea8026Sopenharmony_ciThe contents of the superblock entry are stored in a name tag with the
39419ea8026Sopenharmony_cisuperblock type and an inline-struct tag. The name tag contains the magic
39519ea8026Sopenharmony_cistring "littlefs", while the inline-struct tag contains version and
39619ea8026Sopenharmony_ciconfiguration information.
39719ea8026Sopenharmony_ci
39819ea8026Sopenharmony_ciLayout of the superblock name tag and inline-struct tag:
39919ea8026Sopenharmony_ci
40019ea8026Sopenharmony_ci```
40119ea8026Sopenharmony_ci        tag                          data
40219ea8026Sopenharmony_ci[--      32      --][--      32      --|--      32      --]
40319ea8026Sopenharmony_ci[1|- 11 -| 10 | 10 ][---              64               ---]
40419ea8026Sopenharmony_ci ^    ^     ^    ^- size (8)           ^- magic string ("littlefs")
40519ea8026Sopenharmony_ci |    |     '------ id (0)
40619ea8026Sopenharmony_ci |    '------------ type (0x0ff)
40719ea8026Sopenharmony_ci '----------------- valid bit
40819ea8026Sopenharmony_ci
40919ea8026Sopenharmony_ci        tag                          data
41019ea8026Sopenharmony_ci[--      32      --][--      32      --|--      32      --|--      32      --]
41119ea8026Sopenharmony_ci[1|- 11 -| 10 | 10 ][--      32      --|--      32      --|--      32      --]
41219ea8026Sopenharmony_ci ^    ^     ^    ^            ^- version         ^- block size      ^- block count
41319ea8026Sopenharmony_ci |    |     |    |  [--      32      --|--      32      --|--      32      --]
41419ea8026Sopenharmony_ci |    |     |    |  [--      32      --|--      32      --|--      32      --]
41519ea8026Sopenharmony_ci |    |     |    |            ^- name max        ^- file max        ^- attr max
41619ea8026Sopenharmony_ci |    |     |    '- size (24)
41719ea8026Sopenharmony_ci |    |     '------ id (0)
41819ea8026Sopenharmony_ci |    '------------ type (0x201)
41919ea8026Sopenharmony_ci '----------------- valid bit
42019ea8026Sopenharmony_ci```
42119ea8026Sopenharmony_ci
42219ea8026Sopenharmony_ciSuperblock fields:
42319ea8026Sopenharmony_ci
42419ea8026Sopenharmony_ci1. **Magic string (8-bytes)** - Magic string indicating the presence of
42519ea8026Sopenharmony_ci   littlefs on the device. Must be the string "littlefs".
42619ea8026Sopenharmony_ci
42719ea8026Sopenharmony_ci2. **Version (32-bits)** - The version of littlefs at format time. The version
42819ea8026Sopenharmony_ci   is encoded in a 32-bit value with the upper 16-bits containing the major
42919ea8026Sopenharmony_ci   version, and the lower 16-bits containing the minor version.
43019ea8026Sopenharmony_ci
43119ea8026Sopenharmony_ci   This specification describes version 2.0 (`0x00020000`).
43219ea8026Sopenharmony_ci
43319ea8026Sopenharmony_ci3. **Block size (32-bits)** - Size of the logical block size used by the
43419ea8026Sopenharmony_ci   filesystem in bytes.
43519ea8026Sopenharmony_ci
43619ea8026Sopenharmony_ci4. **Block count (32-bits)** - Number of blocks in the filesystem.
43719ea8026Sopenharmony_ci
43819ea8026Sopenharmony_ci5. **Name max (32-bits)** - Maximum size of file names in bytes.
43919ea8026Sopenharmony_ci
44019ea8026Sopenharmony_ci6. **File max (32-bits)** - Maximum size of files in bytes.
44119ea8026Sopenharmony_ci
44219ea8026Sopenharmony_ci7. **Attr max (32-bits)** - Maximum size of file attributes in bytes.
44319ea8026Sopenharmony_ci
44419ea8026Sopenharmony_ciThe superblock must always be the first entry (id 0) in a metadata pair as well
44519ea8026Sopenharmony_cias be the first entry written to the block. This means that the superblock
44619ea8026Sopenharmony_cientry can be read from a device using offsets alone.
44719ea8026Sopenharmony_ci
44819ea8026Sopenharmony_ci---
44919ea8026Sopenharmony_ci#### `0x2xx` LFS_TYPE_STRUCT
45019ea8026Sopenharmony_ci
45119ea8026Sopenharmony_ciAssociates the id with an on-disk data structure.
45219ea8026Sopenharmony_ci
45319ea8026Sopenharmony_ciThe exact layout of the data depends on the data structure type stored in the
45419ea8026Sopenharmony_cichunk field and can be one of the following.
45519ea8026Sopenharmony_ci
45619ea8026Sopenharmony_ciAny type of struct supersedes all other structs associated with the id. For
45719ea8026Sopenharmony_ciexample, appending a ctz-struct replaces an inline-struct on the same file.
45819ea8026Sopenharmony_ci
45919ea8026Sopenharmony_ci---
46019ea8026Sopenharmony_ci#### `0x200` LFS_TYPE_DIRSTRUCT
46119ea8026Sopenharmony_ci
46219ea8026Sopenharmony_ciGives the id a directory data structure.
46319ea8026Sopenharmony_ci
46419ea8026Sopenharmony_ciDirectories in littlefs are stored on disk as a linked-list of metadata pairs,
46519ea8026Sopenharmony_cieach pair containing any number of files in alphabetical order.
46619ea8026Sopenharmony_ci
46719ea8026Sopenharmony_ci```
46819ea8026Sopenharmony_ci     |
46919ea8026Sopenharmony_ci     v
47019ea8026Sopenharmony_ci .--------.  .--------.  .--------.  .--------.  .--------.  .--------.
47119ea8026Sopenharmony_ci.| file A |->| file D |->| file G |->| file I |->| file J |->| file M |
47219ea8026Sopenharmony_ci|| file B | || file E | || file H | ||        | || file K | || file N |
47319ea8026Sopenharmony_ci|| file C | || file F | ||        | ||        | || file L | ||        |
47419ea8026Sopenharmony_ci|'--------' |'--------' |'--------' |'--------' |'--------' |'--------'
47519ea8026Sopenharmony_ci'--------'  '--------'  '--------'  '--------'  '--------'  '--------'
47619ea8026Sopenharmony_ci```
47719ea8026Sopenharmony_ci
47819ea8026Sopenharmony_ciThe dir-struct tag contains only the pointer to the first metadata-pair in the
47919ea8026Sopenharmony_cidirectory. The directory size is not known without traversing the directory.
48019ea8026Sopenharmony_ci
48119ea8026Sopenharmony_ciThe pointer to the next metadata-pair in the directory is stored in a tail tag,
48219ea8026Sopenharmony_ciwhich is described below.
48319ea8026Sopenharmony_ci
48419ea8026Sopenharmony_ciLayout of the dir-struct tag:
48519ea8026Sopenharmony_ci
48619ea8026Sopenharmony_ci```
48719ea8026Sopenharmony_ci        tag                          data
48819ea8026Sopenharmony_ci[--      32      --][--      32      --|--      32      --]
48919ea8026Sopenharmony_ci[1|- 11 -| 10 | 10 ][---              64               ---]
49019ea8026Sopenharmony_ci ^    ^     ^    ^- size (8)           ^- metadata pair
49119ea8026Sopenharmony_ci |    |     '------ id
49219ea8026Sopenharmony_ci |    '------------ type (0x200)
49319ea8026Sopenharmony_ci '----------------- valid bit
49419ea8026Sopenharmony_ci```
49519ea8026Sopenharmony_ci
49619ea8026Sopenharmony_ciDir-struct fields:
49719ea8026Sopenharmony_ci
49819ea8026Sopenharmony_ci1. **Metadata pair (8-bytes)** - Pointer to the first metadata-pair
49919ea8026Sopenharmony_ci   in the directory.
50019ea8026Sopenharmony_ci
50119ea8026Sopenharmony_ci---
50219ea8026Sopenharmony_ci#### `0x201` LFS_TYPE_INLINESTRUCT
50319ea8026Sopenharmony_ci
50419ea8026Sopenharmony_ciGives the id an inline data structure.
50519ea8026Sopenharmony_ci
50619ea8026Sopenharmony_ciInline structs store small files that can fit in the metadata pair. In this
50719ea8026Sopenharmony_cicase, the file data is stored directly in the tag's data area.
50819ea8026Sopenharmony_ci
50919ea8026Sopenharmony_ciLayout of the inline-struct tag:
51019ea8026Sopenharmony_ci
51119ea8026Sopenharmony_ci```
51219ea8026Sopenharmony_ci        tag                          data
51319ea8026Sopenharmony_ci[--      32      --][---        variable length        ---]
51419ea8026Sopenharmony_ci[1|- 11 -| 10 | 10 ][---           (size * 8)          ---]
51519ea8026Sopenharmony_ci ^    ^     ^    ^- size                    ^- inline data
51619ea8026Sopenharmony_ci |    |     '------ id
51719ea8026Sopenharmony_ci |    '------------ type (0x201)
51819ea8026Sopenharmony_ci '----------------- valid bit
51919ea8026Sopenharmony_ci```
52019ea8026Sopenharmony_ci
52119ea8026Sopenharmony_ciInline-struct fields:
52219ea8026Sopenharmony_ci
52319ea8026Sopenharmony_ci1. **Inline data** - File data stored directly in the metadata-pair.
52419ea8026Sopenharmony_ci
52519ea8026Sopenharmony_ci---
52619ea8026Sopenharmony_ci#### `0x202` LFS_TYPE_CTZSTRUCT
52719ea8026Sopenharmony_ci
52819ea8026Sopenharmony_ciGives the id a CTZ skip-list data structure.
52919ea8026Sopenharmony_ci
53019ea8026Sopenharmony_ciCTZ skip-lists store files that can not fit in the metadata pair. These files
53119ea8026Sopenharmony_ciare stored in a skip-list in reverse, with a pointer to the head of the
53219ea8026Sopenharmony_ciskip-list. Note that the head of the skip-list and the file size is enough
53319ea8026Sopenharmony_ciinformation to read the file.
53419ea8026Sopenharmony_ci
53519ea8026Sopenharmony_ciHow exactly CTZ skip-lists work is a bit complicated. A full explanation can be
53619ea8026Sopenharmony_cifound in the [DESIGN.md](DESIGN.md#ctz-skip-lists).
53719ea8026Sopenharmony_ci
53819ea8026Sopenharmony_ciA quick summary: For every _n_&zwj;th block where _n_ is divisible by
53919ea8026Sopenharmony_ci2&zwj;_&#739;_, that block contains a pointer to block _n_-2&zwj;_&#739;_.
54019ea8026Sopenharmony_ciThese pointers are stored in increasing order of _x_ in each block of the file
54119ea8026Sopenharmony_cibefore the actual data.
54219ea8026Sopenharmony_ci
54319ea8026Sopenharmony_ci```
54419ea8026Sopenharmony_ci                                                               |
54519ea8026Sopenharmony_ci                                                               v
54619ea8026Sopenharmony_ci.--------.  .--------.  .--------.  .--------.  .--------.  .--------.
54719ea8026Sopenharmony_ci| A      |<-| D      |<-| G      |<-| J      |<-| M      |<-| P      |
54819ea8026Sopenharmony_ci| B      |<-| E      |--| H      |<-| K      |--| N      |  | Q      |
54919ea8026Sopenharmony_ci| C      |<-| F      |--| I      |--| L      |--| O      |  |        |
55019ea8026Sopenharmony_ci'--------'  '--------'  '--------'  '--------'  '--------'  '--------'
55119ea8026Sopenharmony_ci  block 0     block 1     block 2     block 3     block 4     block 5
55219ea8026Sopenharmony_ci              1 skip      2 skips     1 skip      3 skips     1 skip
55319ea8026Sopenharmony_ci```
55419ea8026Sopenharmony_ci
55519ea8026Sopenharmony_ciNote that the maximum number of pointers in a block is bounded by the maximum
55619ea8026Sopenharmony_cifile size divided by the block size. With 32 bits for file size, this results
55719ea8026Sopenharmony_ciin a minimum block size of 104 bytes.
55819ea8026Sopenharmony_ci
55919ea8026Sopenharmony_ciLayout of the CTZ-struct tag:
56019ea8026Sopenharmony_ci
56119ea8026Sopenharmony_ci```
56219ea8026Sopenharmony_ci        tag                          data
56319ea8026Sopenharmony_ci[--      32      --][--      32      --|--      32      --]
56419ea8026Sopenharmony_ci[1|- 11 -| 10 | 10 ][--      32      --|--      32      --]
56519ea8026Sopenharmony_ci ^    ^     ^    ^            ^                  ^- file size
56619ea8026Sopenharmony_ci |    |     |    |            '-------------------- file head
56719ea8026Sopenharmony_ci |    |     |    '- size (8)
56819ea8026Sopenharmony_ci |    |     '------ id
56919ea8026Sopenharmony_ci |    '------------ type (0x202)
57019ea8026Sopenharmony_ci '----------------- valid bit
57119ea8026Sopenharmony_ci```
57219ea8026Sopenharmony_ci
57319ea8026Sopenharmony_ciCTZ-struct fields:
57419ea8026Sopenharmony_ci
57519ea8026Sopenharmony_ci1. **File head (32-bits)** - Pointer to the block that is the head of the
57619ea8026Sopenharmony_ci   file's CTZ skip-list.
57719ea8026Sopenharmony_ci
57819ea8026Sopenharmony_ci2. **File size (32-bits)** - Size of the file in bytes.
57919ea8026Sopenharmony_ci
58019ea8026Sopenharmony_ci---
58119ea8026Sopenharmony_ci#### `0x3xx` LFS_TYPE_USERATTR
58219ea8026Sopenharmony_ci
58319ea8026Sopenharmony_ciAttaches a user attribute to an id.
58419ea8026Sopenharmony_ci
58519ea8026Sopenharmony_cilittlefs has a concept of "user attributes". These are small user-provided
58619ea8026Sopenharmony_ciattributes that can be used to store things like timestamps, hashes,
58719ea8026Sopenharmony_cipermissions, etc.
58819ea8026Sopenharmony_ci
58919ea8026Sopenharmony_ciEach user attribute is uniquely identified by an 8-bit type which is stored in
59019ea8026Sopenharmony_cithe chunk field, and the user attribute itself can be found in the tag's data.
59119ea8026Sopenharmony_ci
59219ea8026Sopenharmony_ciThere are currently no standard user attributes and a portable littlefs
59319ea8026Sopenharmony_ciimplementation should work with any user attributes missing.
59419ea8026Sopenharmony_ci
59519ea8026Sopenharmony_ciLayout of the user-attr tag:
59619ea8026Sopenharmony_ci
59719ea8026Sopenharmony_ci```
59819ea8026Sopenharmony_ci        tag                          data
59919ea8026Sopenharmony_ci[--      32      --][---        variable length        ---]
60019ea8026Sopenharmony_ci[1| 3| 8 | 10 | 10 ][---           (size * 8)          ---]
60119ea8026Sopenharmony_ci ^  ^  ^    ^    ^- size                    ^- attr data
60219ea8026Sopenharmony_ci |  |  |    '------ id
60319ea8026Sopenharmony_ci |  |  '----------- attr type
60419ea8026Sopenharmony_ci |  '-------------- type1 (0x3)
60519ea8026Sopenharmony_ci '----------------- valid bit
60619ea8026Sopenharmony_ci```
60719ea8026Sopenharmony_ci
60819ea8026Sopenharmony_ciUser-attr fields:
60919ea8026Sopenharmony_ci
61019ea8026Sopenharmony_ci1. **Attr type (8-bits)** - Type of the user attributes.
61119ea8026Sopenharmony_ci
61219ea8026Sopenharmony_ci2. **Attr data** - The data associated with the user attribute.
61319ea8026Sopenharmony_ci
61419ea8026Sopenharmony_ci---
61519ea8026Sopenharmony_ci#### `0x6xx` LFS_TYPE_TAIL
61619ea8026Sopenharmony_ci
61719ea8026Sopenharmony_ciProvides the tail pointer for the metadata pair itself.
61819ea8026Sopenharmony_ci
61919ea8026Sopenharmony_ciThe metadata pair's tail pointer is used in littlefs for a linked-list
62019ea8026Sopenharmony_cicontaining all metadata pairs. The chunk field contains the type of the tail,
62119ea8026Sopenharmony_ciwhich indicates if the following metadata pair is a part of the directory
62219ea8026Sopenharmony_ci(hard-tail) or only used to traverse the filesystem (soft-tail).
62319ea8026Sopenharmony_ci
62419ea8026Sopenharmony_ci```
62519ea8026Sopenharmony_ci         .--------.
62619ea8026Sopenharmony_ci        .| dir A  |-.
62719ea8026Sopenharmony_ci        ||softtail| |
62819ea8026Sopenharmony_ci.--------|        |-'
62919ea8026Sopenharmony_ci|       |'--------'
63019ea8026Sopenharmony_ci|       '---|--|-'
63119ea8026Sopenharmony_ci|        .-'    '-------------.
63219ea8026Sopenharmony_ci|       v                      v
63319ea8026Sopenharmony_ci|  .--------.  .--------.  .--------.
63419ea8026Sopenharmony_ci'->| dir B  |->| dir B  |->| dir C  |
63519ea8026Sopenharmony_ci  ||hardtail| ||softtail| ||        |
63619ea8026Sopenharmony_ci  ||        | ||        | ||        |
63719ea8026Sopenharmony_ci  |'--------' |'--------' |'--------'
63819ea8026Sopenharmony_ci  '--------'  '--------'  '--------'
63919ea8026Sopenharmony_ci```
64019ea8026Sopenharmony_ci
64119ea8026Sopenharmony_ciCurrently any type supersedes any other preceding tails in the metadata pair,
64219ea8026Sopenharmony_cibut this may change if additional metadata pair state is added.
64319ea8026Sopenharmony_ci
64419ea8026Sopenharmony_ciA note about the metadata pair linked-list: Normally, this linked-list contains
64519ea8026Sopenharmony_cievery metadata pair in the filesystem. However, there are some operations that
64619ea8026Sopenharmony_cican cause this linked-list to become out of sync if a power-loss were to occur.
64719ea8026Sopenharmony_ciWhen this happens, littlefs sets the "sync" flag in the global state. How
64819ea8026Sopenharmony_ciexactly this flag is stored is described below.
64919ea8026Sopenharmony_ci
65019ea8026Sopenharmony_ciWhen the sync flag is set:
65119ea8026Sopenharmony_ci
65219ea8026Sopenharmony_ci1. The linked-list may contain an orphaned directory that has been removed in
65319ea8026Sopenharmony_ci   the filesystem.
65419ea8026Sopenharmony_ci2. The linked-list may contain a metadata pair with a bad block that has been
65519ea8026Sopenharmony_ci   replaced in the filesystem.
65619ea8026Sopenharmony_ci
65719ea8026Sopenharmony_ciIf the sync flag is set, the threaded linked-list must be checked for these
65819ea8026Sopenharmony_cierrors before it can be used reliably. Note that the threaded linked-list can
65919ea8026Sopenharmony_cibe ignored if littlefs is mounted read-only.
66019ea8026Sopenharmony_ci
66119ea8026Sopenharmony_ciLayout of the tail tag:
66219ea8026Sopenharmony_ci
66319ea8026Sopenharmony_ci```
66419ea8026Sopenharmony_ci        tag                          data
66519ea8026Sopenharmony_ci[--      32      --][--      32      --|--      32      --]
66619ea8026Sopenharmony_ci[1| 3| 8 | 10 | 10 ][---              64               ---]
66719ea8026Sopenharmony_ci ^  ^  ^   ^    ^- size (8)            ^- metadata pair
66819ea8026Sopenharmony_ci |  |  |   '------ id
66919ea8026Sopenharmony_ci |  |  '---------- tail type
67019ea8026Sopenharmony_ci |  '------------- type1 (0x6)
67119ea8026Sopenharmony_ci '---------------- valid bit
67219ea8026Sopenharmony_ci```
67319ea8026Sopenharmony_ci
67419ea8026Sopenharmony_ciTail fields:
67519ea8026Sopenharmony_ci
67619ea8026Sopenharmony_ci1. **Tail type (8-bits)** - Type of the tail pointer.
67719ea8026Sopenharmony_ci
67819ea8026Sopenharmony_ci2. **Metadata pair (8-bytes)** - Pointer to the next metadata-pair.
67919ea8026Sopenharmony_ci
68019ea8026Sopenharmony_ci---
68119ea8026Sopenharmony_ci#### `0x600` LFS_TYPE_SOFTTAIL
68219ea8026Sopenharmony_ci
68319ea8026Sopenharmony_ciProvides a tail pointer that points to the next metadata pair in the
68419ea8026Sopenharmony_cifilesystem.
68519ea8026Sopenharmony_ci
68619ea8026Sopenharmony_ciIn this case, the next metadata pair is not a part of our current directory
68719ea8026Sopenharmony_ciand should only be followed when traversing the entire filesystem.
68819ea8026Sopenharmony_ci
68919ea8026Sopenharmony_ci---
69019ea8026Sopenharmony_ci#### `0x601` LFS_TYPE_HARDTAIL
69119ea8026Sopenharmony_ci
69219ea8026Sopenharmony_ciProvides a tail pointer that points to the next metadata pair in the
69319ea8026Sopenharmony_cidirectory.
69419ea8026Sopenharmony_ci
69519ea8026Sopenharmony_ciIn this case, the next metadata pair belongs to the current directory. Note
69619ea8026Sopenharmony_cithat because directories in littlefs are sorted alphabetically, the next
69719ea8026Sopenharmony_cimetadata pair should only contain filenames greater than any filename in the
69819ea8026Sopenharmony_cicurrent pair.
69919ea8026Sopenharmony_ci
70019ea8026Sopenharmony_ci---
70119ea8026Sopenharmony_ci#### `0x7xx` LFS_TYPE_GSTATE
70219ea8026Sopenharmony_ci
70319ea8026Sopenharmony_ciProvides delta bits for global state entries.
70419ea8026Sopenharmony_ci
70519ea8026Sopenharmony_cilittlefs has a concept of "global state". This is a small set of state that
70619ea8026Sopenharmony_cican be updated by a commit to _any_ metadata pair in the filesystem.
70719ea8026Sopenharmony_ci
70819ea8026Sopenharmony_ciThe way this works is that the global state is stored as a set of deltas
70919ea8026Sopenharmony_cidistributed across the filesystem such that the global state can be found by
71019ea8026Sopenharmony_cithe xor-sum of these deltas.
71119ea8026Sopenharmony_ci
71219ea8026Sopenharmony_ci```
71319ea8026Sopenharmony_ci .--------.  .--------.  .--------.  .--------.  .--------.
71419ea8026Sopenharmony_ci.|        |->| gdelta |->|        |->| gdelta |->| gdelta |
71519ea8026Sopenharmony_ci||        | || 0x23   | ||        | || 0xff   | || 0xce   |
71619ea8026Sopenharmony_ci||        | ||        | ||        | ||        | ||        |
71719ea8026Sopenharmony_ci|'--------' |'--------' |'--------' |'--------' |'--------'
71819ea8026Sopenharmony_ci'--------'  '----|---'  '--------'  '----|---'  '----|---'
71919ea8026Sopenharmony_ci                 v                       v           v
72019ea8026Sopenharmony_ci       0x00 --> xor ------------------> xor ------> xor --> gstate = 0x12
72119ea8026Sopenharmony_ci```
72219ea8026Sopenharmony_ci
72319ea8026Sopenharmony_ciNote that storing globals this way is very expensive in terms of storage usage,
72419ea8026Sopenharmony_ciso any global state should be kept very small.
72519ea8026Sopenharmony_ci
72619ea8026Sopenharmony_ciThe size and format of each piece of global state depends on the type, which
72719ea8026Sopenharmony_ciis stored in the chunk field. Currently, the only global state is move state,
72819ea8026Sopenharmony_ciwhich is outlined below.
72919ea8026Sopenharmony_ci
73019ea8026Sopenharmony_ci---
73119ea8026Sopenharmony_ci#### `0x7ff` LFS_TYPE_MOVESTATE
73219ea8026Sopenharmony_ci
73319ea8026Sopenharmony_ciProvides delta bits for the global move state.
73419ea8026Sopenharmony_ci
73519ea8026Sopenharmony_ciThe move state in littlefs is used to store info about operations that could
73619ea8026Sopenharmony_cicause to filesystem to go out of sync if the power is lost. The operations
73719ea8026Sopenharmony_ciwhere this could occur is moves of files between metadata pairs and any
73819ea8026Sopenharmony_cioperation that changes metadata pairs on the threaded linked-list.
73919ea8026Sopenharmony_ci
74019ea8026Sopenharmony_ciIn the case of moves, the move state contains a tag + metadata pair describing
74119ea8026Sopenharmony_cithe source of the ongoing move. If this tag is non-zero, that means that power
74219ea8026Sopenharmony_ciwas lost during a move, and the file exists in two different locations. If this
74319ea8026Sopenharmony_cihappens, the source of the move should be considered deleted, and the move
74419ea8026Sopenharmony_cishould be completed (the source should be deleted) before any other write
74519ea8026Sopenharmony_cioperations to the filesystem.
74619ea8026Sopenharmony_ci
74719ea8026Sopenharmony_ciIn the case of operations to the threaded linked-list, a single "sync" bit is
74819ea8026Sopenharmony_ciused to indicate that a modification is ongoing. If this sync flag is set, the
74919ea8026Sopenharmony_cithreaded linked-list will need to be checked for errors before it can be used
75019ea8026Sopenharmony_cireliably. The exact cases to check for are described above in the tail tag.
75119ea8026Sopenharmony_ci
75219ea8026Sopenharmony_ciLayout of the move state:
75319ea8026Sopenharmony_ci
75419ea8026Sopenharmony_ci```
75519ea8026Sopenharmony_ci        tag                                    data
75619ea8026Sopenharmony_ci[--      32      --][--      32      --|--      32      --|--      32      --]
75719ea8026Sopenharmony_ci[1|- 11 -| 10 | 10 ][1|- 11 -| 10 | 10 |---              64               ---]
75819ea8026Sopenharmony_ci ^    ^     ^    ^   ^    ^     ^    ^- padding (0)       ^- metadata pair
75919ea8026Sopenharmony_ci |    |     |    |   |    |     '------ move id
76019ea8026Sopenharmony_ci |    |     |    |   |    '------------ move type
76119ea8026Sopenharmony_ci |    |     |    |   '----------------- sync bit
76219ea8026Sopenharmony_ci |    |     |    |
76319ea8026Sopenharmony_ci |    |     |    '- size (12)
76419ea8026Sopenharmony_ci |    |     '------ id (0x3ff)
76519ea8026Sopenharmony_ci |    '------------ type (0x7ff)
76619ea8026Sopenharmony_ci '----------------- valid bit
76719ea8026Sopenharmony_ci```
76819ea8026Sopenharmony_ci
76919ea8026Sopenharmony_ciMove state fields:
77019ea8026Sopenharmony_ci
77119ea8026Sopenharmony_ci1. **Sync bit (1-bit)** - Indicates if the metadata pair threaded linked-list
77219ea8026Sopenharmony_ci   is in-sync. If set, the threaded linked-list should be checked for errors.
77319ea8026Sopenharmony_ci
77419ea8026Sopenharmony_ci2. **Move type (11-bits)** - Type of move being performed. Must be either
77519ea8026Sopenharmony_ci   `0x000`, indicating no move, or `0x4ff` indicating the source file should
77619ea8026Sopenharmony_ci   be deleted.
77719ea8026Sopenharmony_ci
77819ea8026Sopenharmony_ci3. **Move id (10-bits)** - The file id being moved.
77919ea8026Sopenharmony_ci
78019ea8026Sopenharmony_ci4. **Metadata pair (8-bytes)** - Pointer to the metadata-pair containing
78119ea8026Sopenharmony_ci   the move.
78219ea8026Sopenharmony_ci
78319ea8026Sopenharmony_ci---
78419ea8026Sopenharmony_ci#### `0x5xx` LFS_TYPE_CRC
78519ea8026Sopenharmony_ci
78619ea8026Sopenharmony_ciLast but not least, the CRC tag marks the end of a commit and provides a
78719ea8026Sopenharmony_cichecksum for any commits to the metadata block.
78819ea8026Sopenharmony_ci
78919ea8026Sopenharmony_ciThe first 32-bits of the data contain a CRC-32 with a polynomial of
79019ea8026Sopenharmony_ci`0x04c11db7` initialized with `0xffffffff`. This CRC provides a checksum for
79119ea8026Sopenharmony_ciall metadata since the previous CRC tag, including the CRC tag itself. For
79219ea8026Sopenharmony_cithe first commit, this includes the revision count for the metadata block.
79319ea8026Sopenharmony_ci
79419ea8026Sopenharmony_ciHowever, the size of the data is not limited to 32-bits. The data field may
79519ea8026Sopenharmony_cilarger to pad the commit to the next program-aligned boundary.
79619ea8026Sopenharmony_ci
79719ea8026Sopenharmony_ciIn addition, the CRC tag's chunk field contains a set of flags which can
79819ea8026Sopenharmony_cichange the behaviour of commits. Currently the only flag in use is the lowest
79919ea8026Sopenharmony_cibit, which determines the expected state of the valid bit for any following
80019ea8026Sopenharmony_citags. This is used to guarantee that unwritten storage in a metadata block
80119ea8026Sopenharmony_ciwill be detected as invalid.
80219ea8026Sopenharmony_ci
80319ea8026Sopenharmony_ciLayout of the CRC tag:
80419ea8026Sopenharmony_ci
80519ea8026Sopenharmony_ci```
80619ea8026Sopenharmony_ci        tag                                    data
80719ea8026Sopenharmony_ci[--      32      --][--      32      --|---        variable length        ---]
80819ea8026Sopenharmony_ci[1| 3| 8 | 10 | 10 ][--      32      --|---        (size * 8 - 32)        ---]
80919ea8026Sopenharmony_ci ^  ^  ^    ^    ^            ^- crc                             ^- padding
81019ea8026Sopenharmony_ci |  |  |    |    '- size
81119ea8026Sopenharmony_ci |  |  |    '------ id (0x3ff)
81219ea8026Sopenharmony_ci |  |  '----------- valid state
81319ea8026Sopenharmony_ci |  '-------------- type1 (0x5)
81419ea8026Sopenharmony_ci '----------------- valid bit
81519ea8026Sopenharmony_ci```
81619ea8026Sopenharmony_ci
81719ea8026Sopenharmony_ciCRC fields:
81819ea8026Sopenharmony_ci
81919ea8026Sopenharmony_ci1. **Valid state (1-bit)** - Indicates the expected value of the valid bit for
82019ea8026Sopenharmony_ci   any tags in the next commit.
82119ea8026Sopenharmony_ci
82219ea8026Sopenharmony_ci2. **CRC (32-bits)** - CRC-32 with a polynomial of `0x04c11db7` initialized
82319ea8026Sopenharmony_ci   with `0xffffffff`.
82419ea8026Sopenharmony_ci
82519ea8026Sopenharmony_ci3. **Padding** - Padding to the next program-aligned boundary. No guarantees
82619ea8026Sopenharmony_ci   are made about the contents.
82719ea8026Sopenharmony_ci
82819ea8026Sopenharmony_ci---
82919ea8026Sopenharmony_ci#### `0x5ff` LFS_TYPE_FCRC
83019ea8026Sopenharmony_ci
83119ea8026Sopenharmony_ciAdded in lfs2.1, the optional FCRC tag contains a checksum of some amount of
83219ea8026Sopenharmony_cibytes in the next commit at the time it was erased. This allows us to ensure
83319ea8026Sopenharmony_cithat we only ever program erased bytes, even if a previous commit failed due
83419ea8026Sopenharmony_cito power-loss.
83519ea8026Sopenharmony_ci
83619ea8026Sopenharmony_ciWhen programming a commit, the FCRC size must be at least as large as the
83719ea8026Sopenharmony_ciprogram block size. However, the program block is not saved on disk, and can
83819ea8026Sopenharmony_cichange between mounts, so the FCRC size on disk may be different than the
83919ea8026Sopenharmony_cicurrent program block size.
84019ea8026Sopenharmony_ci
84119ea8026Sopenharmony_ciIf the FCRC is missing or the checksum does not match, we must assume a
84219ea8026Sopenharmony_cicommit was attempted but failed due to power-loss.
84319ea8026Sopenharmony_ci
84419ea8026Sopenharmony_ciLayout of the FCRC tag:
84519ea8026Sopenharmony_ci
84619ea8026Sopenharmony_ci```
84719ea8026Sopenharmony_ci        tag                          data
84819ea8026Sopenharmony_ci[--      32      --][--      32      --|--      32      --]
84919ea8026Sopenharmony_ci[1|- 11 -| 10 | 10 ][--      32      --|--      32      --]
85019ea8026Sopenharmony_ci ^    ^     ^    ^            ^- fcrc size       ^- fcrc
85119ea8026Sopenharmony_ci |    |     |    '- size (8)
85219ea8026Sopenharmony_ci |    |     '------ id (0x3ff)
85319ea8026Sopenharmony_ci |    '------------ type (0x5ff)
85419ea8026Sopenharmony_ci '----------------- valid bit
85519ea8026Sopenharmony_ci```
85619ea8026Sopenharmony_ci
85719ea8026Sopenharmony_ciFCRC fields:
85819ea8026Sopenharmony_ci
85919ea8026Sopenharmony_ci1. **FCRC size (32-bits)** - Number of bytes after this commit's CRC tag's
86019ea8026Sopenharmony_ci   padding to include in the FCRC.
86119ea8026Sopenharmony_ci
86219ea8026Sopenharmony_ci2. **FCRC (32-bits)** - CRC of the bytes after this commit's CRC tag's padding
86319ea8026Sopenharmony_ci   when erased. Like the CRC tag, this uses a CRC-32 with a polynomial of
86419ea8026Sopenharmony_ci   `0x04c11db7` initialized with `0xffffffff`.
86519ea8026Sopenharmony_ci
86619ea8026Sopenharmony_ci---
867