Это техническая спецификация файловой системы LittleFS с версией на диске lfs2.1. Этот документ описывает технические детали того, как LittleFS хранится на диске для интроспекции и инструментовки. Предполагается, что вы знакомы с дизайном LittleFS, для получения дополнительной информации о том, как работает LittleFS, обратитесь к DESIGN.md.
| | | .---._____
.-----. | |
--|o |---| littlefs |
--| |---| |
'-----' '----------'
| | |
LittleFS — это блочная файловая система. Диск разделён на массив блоков одинакового размера, которые используются в качестве логической единицы хранения.
Указатели блоков хранятся в 32 битах, специальное значение 0xffffffff
представляет нулевой адрес блока.
Помимо логического размера блока (который обычно соответствует размеру стираемого блока), LittleFS также использует размер программного блока и размер читаемого блока. Они определяют выравнивание операций блочного устройства, но не обязательно должны быть согласованы для обеспечения переносимости.
По умолчанию все значения в LittleFS хранятся в порядке байтов с прямым порядком.
Пары метаданных образуют основу LittleFS и обеспечивают систему распределённых атомарных обновлений. Даже суперблок хранится в паре метаданных.
Как следует из названия, пара метаданных хранится в двух блоках, один из которых обеспечивает резервную копию во время циклов стирания на случай потери питания. Эти два блока не обязательно последовательны и могут находиться где угодно на диске, поэтому «указатель» на пару метаданных сохраняется в виде двух указателей блоков.
Кроме того, каждый блок метаданных ведёт себя как добавляемый журнал, содержащий переменное количество фиксаций. Фиксации можно добавлять в журнал метаданных, чтобы обновлять метаданные без необходимости циклов стирания. Обратите внимание, что последующие фиксации могут заменять метаданные в предыдущих фиксациях. Только самые последние метаданные следует считать действительными.
Высокоуровневая структура блока метаданных довольно проста:
.---------------------------------------.
.-| revision count | entries | \
| |-------------------+ | |
| | | |
| | | +-- 1st commit
| | | |
| | +-------------------| |
| | | CRC | /
| |-------------------+-------------------|
| | entries | \
| | | |
| | | +-- 2nd commit
| | +-------------------+--------------| |
| | | CRC | padding | /
| |----+-------------------+--------------|
| | entries | \
| | | |
| | | +-- 3rd commit
| | +-------------------+---------| |
| | | CRC | | /
| |---------+-------------------+ |
| | unwritten storage | more commits
| | | |
| '---------------------------------------'
'---------------------------------------'
Каждый блок метаданных содержит 32-битный счётчик ревизий, за которым следует несколько фиксаций. Каждая фиксация содержит переменное число записей метаданных, за которыми следует 32-битная контрольная сумма циклическим избыточным кодом (CRC).
Также обратите внимание, что записи не обязательно выровнены по словам. Это позволяет нам хранить метаданные более компактно, однако мы можем записывать только по адресам, выровненным по нашему размеру программного блока. Это означает, что каждая фиксация может иметь заполнение для выравнивания.
Поля блока метаданных:
Счётчик ревизий (32 бита) — увеличивается при каждом цикле стирания. Если оба блока содержат действительные фиксации, следует использовать только блок с самым последним счётчиком ревизий. Для избежания проблем с целочисленным переполнением необходимо использовать сравнение последовательностей.
Контрольная сумма CRC В 3-битный абстрактный тип и 8-битное поле чанка. Обратите внимание, что значение 0x000
является недопустимым и не присваивается типу.
Тип 1 (3 бита) — абстрактный тип тега. Группирует теги в 8 категорий, которые облегчают поиск с использованием битовых масок.
Чанк (8 бит) — поле чанка используется для различных целей различными абстрактными типами. Тип 1 + чанк + идентификатор образуют уникальный идентификатор каждого тега в блоке метаданных.
Идентификатор (10 бит) — идентификатор файла, связанный с тегом. Каждый файл в блоке метаданных получает уникальный идентификатор, который используется для связывания тегов с этим файлом. Специальное значение 0x3ff
используется для любых тегов, которые не связаны с файлом, таких как каталог и глобальные метаданные.
Длина (10 бит) — длина данных в байтах. Специальное значение 0x3ff
указывает на то, что этот тег был удалён.
Далее следует исчерпывающий список метаданных в littlefs.
0x401
LFS_TYPE_CREATEСоздаёт новый файл с этим идентификатором. Обратите внимание, что файлы в блоке метаданных необязательно должны иметь тег создания. Всё, что делает создание, это перемещает любые файлы, использующие этот идентификатор. В этом смысле создание похоже на вставку в воображаемый массив файлов.
Теги создания и удаления позволяют littlefs хранить файлы в каталоге, упорядоченные по алфавиту по имени файла.
0x4ff
LFS_TYPE_DELETEУдаляет файл с этим идентификатором. Обратное созданию, этот тег перемещает любые соседние файлы этого идентификатора, подобно удалению из воображаемого массива файлов.
0x0xx
LFS_TYPE_NAMEСвязывает идентификатор с именем файла и типом файла.
Данные содержат имя файла, хранящееся в виде строки ASCII (в будущем может быть расширено до UTF8).
Поле чанка в этом теге указывает 8-битовый тип файла, который может быть одним из следующих.
В настоящее время тег имени должен предшествовать любым другим тегам, связанным с идентификатором, и не может быть переназначен без удаления файла.
Расположение тега имени:
tag data
[-- 32 --][--- variable length ---]
[1| 3| 8 | 10 | 10 ][--- (size * 8) ---]
^ ^ ^ ^ ^- размер ^- имя файла
| | | '------ идентификатор
| | '----------- тип файла
| '-------------- тип 1 (0x0)
'----------------- действительный бит
Поля имени:
тип файла (8 бит) — тип файла;
имя файла — имя файла хранится в виде строки ASCII.
0x001
LFS_TYPE_REGИнициализирует идентификатор + имя как обычный файл.
Способ хранения каждого файла зависит от его структурного тега, который описан ниже.
0x002
LFS_TYPE_DIRИнициализирует идентификатор + имя как каталог.
Каталоги в littlefs хранятся на диске в виде связанного списка пар метаданных, каждая пара содержит любое количество файлов в алфавитном порядке. Указатель на каталог хранится в структурном теге, который описан ниже.
0x0ff
LFS_TYPE_SUPERBLOCKИнициализирует идентификатор как запись суперблока.
Запись суперблока — это специальная запись, используемая для хранения конфигурации времени форматирования и идентификации файловой системы.
Название немного вводит в заблуждение. Хотя запись суперблока служит той же цели, что и суперблок, найденный в других файловых системах, в littlefs суперблоку не выделяется специальный блок. Вместо этого запись суперблока дублируется через связанный список пар метаданных, корни которых находятся на блоках 0 и 1. Последняя пара метаданных также служит корневым каталогом файловой системы.
.--------. .--------. .--------. .--------. .--------.
.| супер |->| супер |->| супер |->| супер |->| файл B |
|| блок | || блок | || блок | || блок | || файл C |
|| | || | || | || файл A | || файл D |
|'--------' |'--------' |'--------' |'--------' |'--------'
'--------' '--------' '--------' '--------' '--------'
\----------------+----------------/ \----------+----------/
суперблок пары root directory
Файловая система начинается только с корневого каталога. Пары метаданных суперблока растут каждый раз, когда корневая пара сжимается, чтобы экспоненциально продлить срок службы устройства. Содержимое записи суперблока хранится в теге имени с типом суперблока и тегом встроенной структуры. Тег имени содержит магическую строку «littlefs», а тег встроенной структуры — информацию о версии и конфигурации.
Расположение тегов имени и встроенной структуры:
тег | данные |
---|---|
[– 32 –] [– 32 – | – 32 –] |
^ ^ ^ - размер (8) | ^ - магическая строка («littlefs») |
‘------------ тип (0x0ff) | |
‘----------------- действительный бит |
тег | данные |
---|---|
[– 32 –][– 32 – | – 32 – |
[1 | - 11 - |
^ ^ ^ ^ версия | |
^ блок-размер | |
^ блок-счётчик | |
^ - имя макс. | |
^ файл макс. | |
^ атрибут макс. | |
- размер (24) | |
‘------ id (0) | |
‘------------ тип (0x201) | |
‘----------------- действительный бит |
Поля суперблока:
0x00020000
).LFS_TYPE_STRUCT 0x2xx
Связывает идентификатор со структурой данных на диске. Точное расположение данных зависит от типа структуры данных, хранящегося в поле chunk, и может быть одним из следующих. Любой тип структуры заменяет все другие структуры, связанные с идентификатором. Например, добавление ctz-структуры заменяет встроенную структуру в том же файле.
LFS_TYPE_DIRSTRUCT 0x200
Придаёт идентификатору структуру данных каталога. Каталоги в littlefs хранятся на диске в виде связанного списка пар метаданных, каждая пара содержит любое количество файлов в алфавитном порядке.
Указатель на следующую пару метаданных в каталоге хранится в хвостовом теге, который описан ниже.
Расположение тега dir-struct:
тег | данные |
---|---|
[– 32 –][– 32 – | – 32 –] |
[1 | - 11 - |
^- размер (8) | |
^- пара метаданных | |
^ - идентификатор | |
‘------------ тип (0x200) | |
‘----------------- действительный бит |
Dir-struct поля:
LFS_TYPE_INLINESTRUCT 0x201
Даёт идентификатору встроенные данные. Часть каталога (хвостовик жёсткий) или используется только для обхода файловой системы (хвостовик мягкий).
.--------.
.| dir A |-.
||softtail| |
.--------| |-'
| |'--------'
| '---|--|-'
| .-' '-------------.
| v v
| .--------. .--------. .--------.
'->| dir B |->| dir B |->| dir C |
||hardtail| ||softtail| || |
|| | || | || |
|'--------' |'--------' |'--------'
'--------' '--------' '--------'
В настоящее время любой тип заменяет все предыдущие хвостовики в паре метаданных, но это может измениться, если будет добавлено дополнительное состояние пары метаданных.
Примечание о связанном списке пар метаданных: обычно этот связанный список содержит каждую пару метаданных в файловой системе. Однако есть некоторые операции, которые могут привести к рассинхронизации связанного списка в случае потери питания. В этом случае littlefs устанавливает флаг «sync» в глобальном состоянии. Как именно хранится этот флаг, описано ниже.
Когда установлен флаг синхронизации:
Если установлен флаг синхронизации, связанный список с резьбой должен быть проверен на наличие этих ошибок, прежде чем его можно будет использовать надёжно. Обратите внимание, что связанным списком с резьбой можно пренебречь, если littlefs смонтирован только для чтения.
Расположение тега хвостовика:
tag data
[-- 32 --][-- 32 --|-- 32 --]
[1| 3| 8 | 10 | 10 ][--- 64 ---]
^ ^ ^ ^ ^- размер (8) ^- пара метаданных
| | | '------ идентификатор
| | '---------- тип хвостовика
| '------------- тип1 (0x6)
'---------------- действительный бит
Поля хвостовика:
Тип хвостовика (8-бит) — тип указателя хвостовика.
Пара метаданных (8 байт) — указатель на следующую пару метаданных.
0x600
LFS_TYPE_SOFTTAILПредоставляет указатель хвостовика, который указывает на следующую пару метаданных в файловой системе.
В этом случае следующая пара метаданных не является частью нашего текущего каталога и должна использоваться только при обходе всей файловой системы.
0x601
LFS_TYPE_HARDTAILПредоставляет указатель хвостовика, который указывает на следующую пару метаданных в каталоге.
В этом случае следующая пара метаданных принадлежит текущему каталогу. Обратите внимание: поскольку каталоги в littlefs отсортированы в алфавитном порядке, следующая пара метаданных должна содержать только имена файлов, превышающие любое имя файла в текущей паре.
0x7xx
LFS_TYPE_GSTATEПредоставляет биты дельты для записей глобального состояния.
littlefs имеет концепцию «глобального состояния». Это небольшой набор состояний, которые можно обновить путём фиксации в любой паре метаданных в файловой системе.
Принцип работы заключается в том, что глобальное состояние хранится в виде набора дельт, распределённых по файловой системе таким образом, чтобы глобальное состояние можно было найти по сумме XOR этих дельт.
.--------. .--------. .--------. .--------. .--------.
.| |->| gdelta |->| |->| gdelta |->| gdelta |
|| | || 0x23 | || | || 0xff | || 0xce |
|| | || | || | || | || |
|'--------' |'--------' |'--------' |'--------' |'--------'
'--------' '----|---' '--------' '----|---' '----|---'
v v v
0x00 --> xor ------------------> xor ------> xor --> gstate = 0x12
Обратите внимание, что хранение глобальных данных таким способом очень затратно с точки зрения использования памяти, поэтому любое глобальное состояние должно быть очень небольшим.
Размер и формат каждого фрагмента глобального состояния зависит от типа, который хранится в поле фрагмента. В настоящее время единственным глобальным состоянием является состояние перемещения, которое описано ниже.
0x7ff
LFS_TYPE_MOVESTATEПредоставляет биты дельты для глобального состояния перемещения.
Состояние перемещения в littlefs используется для хранения информации об операциях, которые могли бы привести к рассинхронизации файловой системы в случае потери питания. Операции, при которых это могло произойти, — это перемещение файлов между парами метаданных и любые
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )