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_‍th block where _n_ is divisible by 53919ea8026Sopenharmony_ci2‍_ˣ_, that block contains a pointer to block _n_-2‍_ˣ_. 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