Файловая система APFS: структура файловой системы и алгоритм восстановления данных
В этой статье мы рассмотрим алгоритм восстановления данных APFS и структуру файловой системы. Узнаем, как работает этот алгоритм и как устроена файловая система APFS. Это полезное руководство поможет вам понять основные принципы и принципы работы данной технологии. Подписывайтесь на наш блог, чтобы узнавать больше о технических аспектах IT!
- Контейнеры и Тома
- Block Header (Заголовок блока)
- Container Superblock
- Volume Superblock (Суперблок тома)
- Checkpoint (Чекпоинт)
- Checkpoint Superblock Descriptor (Дескриптор Чекпоинта Суперблока)
- Bitmap Structures (Битовая карта или карта тома)
- Таблицы (Tables)
- Сводка таблиц
- Моментальные снимки (Snapshots)
- Nodes (узлы)
- Менеджер пространства (Space Manager)
- Allocation info file (Информационный файл распределения)
- Файл и папка B-дерева
- Extents (Экстенты B-дерева)
- 64-bit inodes (index descriptors) - индексные дескрипторы
- Вопросы и ответы
- Комментарии
Контейнеры и Тома
Структура файловой системы APFS имеет вид b-дерева, где корневой каталог с данными — это листья этого дерева. Все ветви хранят лишь ссылки на следующий узел пока не дойдут до листьев. Файловая система использует контейнеры в качестве ячеек хранения. Эти контейнера могут содержать несколько томов. Также он является основным объектом для хранения данных. Для одного тома размер контейнера должен быть более 512 МБ, для двух томов – более 1024Мб и т.д.
На рисунке ниже представлена структура файловой системы «ApFS».
Каждый элемент этой структуры (кроме файла распределения) начинается с 32-байтового заголовка блока, который содержит некоторую общую информацию о блоке. Далее следует тело файловой системы. Оно состоит из следующих элементов:
- 0x01: Суперблок контейнера (Container Superblock)
- 0x02: Узел (Node)
- 0x05: Менеджер пространства (Space manager)
- 0x07: Файл размещения (Allocation Info File)
- 0x0C: Контрольная точка (Checkpoint)
- 0x0D: Суперблок тома (Volume Superblock)
Контейнеры обычно точно такие же, как записи в таблице разделов GUID (GPT). У них есть собственная защита от сбоев и схема распределения дискового пространства. Каждый контейнер содержит один или несколько томов, каждый из которых имеет собственное пространство имен, набор файлов и каталогов.
Файловая система «ApFS» не поддерживает напрямую программный «RAID», но его можно использовать с томами Apple RAID для поддержки чередования (RAID 0), зеркалирования (RAID 1) и склейки (JBOD).
С 64-битным индексом тома «ApFS» поддерживают до 9 квинтиллионов (1018) файлов.
Новая файловая система от Apple использует наносекунды для установки меток времени. В HFS + метки времени были установлены с точностью до секунды. Это уменьшит количество сбоев при передаче данных и других файловых операциях.
«ApFS» имеет встроенную систему шифрования и использует системы AES-XTS или AES-CBC, в зависимости от устройства. Пользователь может использовать несколько ключей шифрования для обеспечения безопасности данных даже в случае «физического взлома» носителя.
Это далеко не полный список нововведений, которыми обладает «ApFS».
Разделы, отформатированные в «ApFS», не распознаются OS X 10.11 Yosemite и более ранними версиями операционной системы.
Block Header (Заголовок блока)
Каждая структура файловой системы в «ApFS» начинается с заголовка блока. А сам заголовок начинается с контрольной суммы. Другая информация в заголовке включает в себя версию блока с копией при записи, идентификатор блока и его тип.
Смещение | Размер | Тип | ID |
---|---|---|---|
0 | 8 | uint64 | Контрольная сумма (checksum) |
8 | 8 | uint64 | Идентификатор (block_id) |
16 | 8 | uint64 | Версия (version) |
24 | 2 | uint16 | Тип блока (block_type) |
26 | 2 | uint16 | Флаги (flags) |
28 | 4 | uint32 | Отступ (padding) |
Из таблицы мы видим, что 1uint = 1 бит, 8 бит = 1 байту, из этого uint64 = 8, uint32 = 4, и uint16 = 2 байтам.
Container Superblock
Суперблок контейнера (Container Superblock) – это входная точка в файловую систему. Из-за структуры файловой системы с контейнерами и гибкими томами, распределение необходимо обрабатывать на уровне контейнера. Суперблок контейнера содержит информацию о размере блока, их количестве и указателях в менеджере пространства для этой задачи. Кроме того, в суперблоке хранятся идентификаторы (ID) блоков всех томов. Для сопоставления идентификаторов блоков блокам смещения, сохраняется указатель на карту блоков B-дерева. Это дерево содержит записи для каждого тома с его идентификатором и смещением. Суперблок контейнера – это самый высокий уровень файловой системы.
Он имеет следующий вид:
Смещение (HEX) | Тип | Id | Описание |
---|---|---|---|
0 | tApFS_COH | Header | Заголовок объекта-контейнера (Container Object Header) |
20 | uint32 | MagicNumber (NXSB) | Значение для проверки чтения Суперблока контейнера. |
24 | uint32 | BlockSize | Размер блока контейнера (в байтах) |
28 | uint64 | BlocksCount | Количество контейнерных блоков |
30 | uint64 | Features | Карта (bitmap) основных функций контейнера |
38 | uint64 | ReadOnlyFeatures | Карта (bitmap) базовых функций контейнера (только для чтения) |
40 | uint64 | IncompatibleFeatures | Карта (bitmap) основных несовместимых функций контейнера |
48 | tApFS_Uuid | Uuid | UUID контейнера |
58 | tApFS_Ident | NextIdent | Следующий идентификатор для нового логического или виртуального объекта |
60 | tApFS_Transaction | NextTransaction | Номер следующей транзакции |
68 | uint32 | DescriptorBlocks | Количество блоков, используемых дескриптором |
6C | uint32 | DataBlocks | Количество блоков, используемых данными |
70 | tApFS_Address | DescriptorBase | Базовый адрес дескриптора или идентификатор физического объекта с деревом адресо |
78 | int32 | DataBase | Адрес базы данных или идентификатор физического объекта с адресным деревом |
80 | uint32 | DescriptorNext | Индекс следующего дескриптора |
84 | uint32 | DataNext | Следующий индекс данных |
88 | uint32 | DescriptorIndex | Индекс первого действительного элемента в сегменте дескриптора |
8C | uint32 | DescriptorLength | Количество блоков в сегменте дескриптора, используемого суперблоком |
90 | uint32 | DataIndex | Индекс первого действительного элемента в сегменте данных |
94 | uint32 | DataLength | Количество блоков в сегменте данных, используемом суперблоком |
98 | tApFS_Ident | SpaceManagerIdent | Идентификатор логического объекта Space Manager |
A0 | tApFS_Ident | ObjectsMapIdent | Идентификатор физического объекта карты объекта контейнера |
A8 | tApFS_Ident | ReaperIdent | Идентификатор логического объекта |
B0 | uint32 | ReservedForTesting | |
B4 | uint32 | MaximumVolumes | Максимально возможное количество объемов в контейнере |
B8 | tApFS_Ident | VolumesIdents[100] | Объем масива идентификаторов виртуальных объектов |
3D8 | uint64 | Counters[32] | Массив счетчиков, хранящих информацию о контейнере |
4D8 | tApFS_BlockRange | BlockedOutOfRange | Физический диапазон блоков, которые нельзя использовать |
4E8 | tApFS_Ident | MappingTreeIdent | Идентификатор физического объекта в дереве, используемый для отслеживания объектов, перемещаемых из заблокированного хранилища. |
4F0 | uint64 | OtherFlags | Карта других функций контейнера |
4F8 | tApFS_Address | JumpstartEFI | Id физического объекта с данными EFI-драйвера |
500 | tApFS_Uuid | FusionUuid | UUID контейнера Fusion или ноль для контейнеров, отличных от Fusion |
510 | tApFS_BlockRange | KeyLocker | Расположение ключевой метки контейнера |
520 | uint64 | EphemeralInfo[4] | Массив полей, используемый для управления логическими данными |
540 | tApFS_Ident | ReservedForTesting | |
548 | tApFS_Ident | FusionMidleTreeIdent | Только для обьединенных устройств |
550 | tApFS_Ident | FusionWriteBackIdent | Только для обьединенных устройств |
558 | tApFS_BlockRange | FusionWriteBackBlocks | Блоки, используемые для области кэша |
С определением типов:
uint8 tApFS_Uuid;
uint64 tApFS_Ident;
uint64 tApFS_Transaction;
int64 tApFS_Address;
uint64 tApFS_BTreeKey;
и
struct tApFS_BlockRange
{
tApFS_Address First; // Первый блок
uint64 Count; // Количество блоков
}
struct tApFS_COH
{
uint64 CheckSum; // Контрольная сумма блока
tApFS_Ident Ident; // Идентификатор
tApFS_Transaction Transaction; // Object change transaction number
uint16 Type; // Тип объекта
uint16 Flags; // Флаги объекта
uint32 SubType; // Подтип объекта
};
с перечнем типов объектов:
enum eApFS_ObjectType
{
eApFS_ObjectType_01_SuperBlock = 0x0001, //Суперблок контейнера
eApFS_ObjectType_02_BTreeRoot = 0x0002, // Би-дерево: узловой элемент
eApFS_ObjectType_03_BTreeNode = 0x0003, // Би-дерево: лист
eApFS_ObjectType_05_SpaceManager = 0x0005, // Менеджер пространства
eApFS_ObjectType_06_SpaceManagerCAB = 0x0006, // Менеджер пространства: адреса сегментов
eApFS_ObjectType_07_SpaceManagerCIB = 0x0007, // Менеджер пространства: информация сегментов
eApFS_ObjectType_08_SpaceManagerBitmap = 0x0008, // Карта свободного пространства используемая Менеджером пространства
eApFS_ObjectType_09_SpaceManagerFreeQueue = 0x0009, // Свободное место используемое менеджером пространства_ (ключи - _tApFS_09_SpaceManagerFreeQueue_Key_, значения - _tApFS_09_SpaceManagerFreeQueue_Value_)
eApFS_ObjectType_0A_ExtentListTree = 0x000A, // Дерево списка экстентов (ключи – смещение начального экстента_tApFS_Address_, значение – физическое расположение данных _tApFS_BlockRange_)
eApFS_ObjectType_0B_ObjectsMap = 0x000B, // Тип – Карта обьектов; subType – Дерево записей карты обьектов (ключи - _tApFS_0B_ObjectsMap_Key_, значения - _tApFS_0B_ObjectsMap_Value_)
eApFS_ObjectType_0C_CheckPointMap = 0x000C, // Карта контрольных точек (чекпоинтов)
eApFS_ObjectType_0D_FileSystem = 0x000D, // Файловая система тома
eApFS_ObjectType_0E_FileSystemTree = 0x000E, // Дерево файловой системы (ключи начинаются с _tApFS_BTreeKey_, описывает тип и значение ключа)
eApFS_ObjectType_0F_BlockReferenceTree = 0x000F, // Дерево ссылок на блоки (ключи - _tApFS_BTreeKey_, значения - _tApFS_0F_BlockReferenceTree_Value_)
eApFS_ObjectType_10_SnapshotMetaTree = 0x0010, // Дерево снимков (ключи - _tApFS_BTreeKey_, значения - _tApFS_10_SnapshotMetaTree_Value_)
eApFS_ObjectType_11_Reaper = 0x0011, // Reaper
eApFS_ObjectType_12_ReaperList = 0x0012, // Reaper List
eApFS_ObjectType_13_ObjectsMapSnapshot = 0x0013, // Дерево снимков карты обьектов (ключи - _tApFS_Transaction_, значения - _tApFS_13_ObjectsMapSnapshot_Value_)
eApFS_ObjectType_14_JumpStartEFI = 0x0014, // EFI Загрузчик
eApFS_ObjectType_15_FusionMiddleTree = 0x0015, // Дерево объединённых устройств для отслеживания блоков жестких дисков, кэшированных SSD (ключи - _tApFS_Address_, значения - _tApFS_15_FusionMiddleTree_Value_)
eApFS_ObjectType_16_FusionWriteBack = 0x0016, // Состояние кэша обратной записи объединённых устройств
eApFS_ObjectType_17_FusionWriteBackList = 0x0017, // Список кэша обратной записи объединённых устройств
eApFS_ObjectType_18_EncryptionState = 0x0018, // Шифрование
eApFS_ObjectType_19_GeneralBitmap = 0x0019, // General Bitmap
eApFS_ObjectType_1A_GeneralBitmapTree = 0x001A, // Дерево General Bitmap (keys - uint64, keys - uint64)
eApFS_ObjectType_1B_GeneralBitmapBlock = 0x001B, // Блок General Bitmap
eApFS_ObjectType_00_Invalid = 0x0000, // Недействителен как тип или отсутствует как подтип
eApFS_ObjectType_FF_Test = 0x00FF // Зарезервировано для тестирования (никогда не сохраняется на носителе)
eApFS_ObjectType_FF_Test = 0x00FF // Зарезервировано для тестирования (никогда не сохраняется на носителе)
};
enum eApFS_ObjectFlag
{
eApFS_ObjectFlag_Virtual = 0x0000, // Виртуальный объект
eApFS_ObjectFlag_Ephemeral = 0x8000, // Логический объект
eApFS_ObjectFlag_Physical = 0x4000, // Физический объект
eApFS_ObjectFlag_NoHeader = 0x2000, // Объект без заголовка _tApFS_ContainerObjectHeader_ (например, Карта (bitmap) менеджера пространства)
eApFS_ObjectFlag_Encrypted = 0x1000, // Зашифрованный объект
eApFS_ObjectFlag_NonPersistent = 0x0800, // Объект из этим флагом никогда не сохраняется на носителе
eApFS_ObjectFlag_StorageTypeMask = 0xC000, // Битовая (bitmask) маска для доступа к флагам категорий обьектов
eApFS_ObjectFlag_ValidMask = 0xF800 // Действительный флаг битовой маски
};
struct tApFS_0B_ObjectsMap_Key
{
tApFS_Ident ObjectIdent; // Идентификатор объекта
tApFS_Transaction Transaction; // Номер транзакции
};
struct tApFS_0B_ObjectsMap_Value
{
uint32 Flags; // Флаги
uint32 Size; // Размер объекта в байтах (кратный размеру блока контейнера)
tApFS_Address Address; // Адрес объекта
};
struct tApFS_09_SpaceManagerFreeQueue_Key
{
tApFS_Transaction sfqk_xid;
tApFS_Address sfqk_paddr;
};
struct tApFS_09_SpaceManagerFreeQueue_Value
{
uint64 sfq_count;
tApFS_Ident sfq_tree_oid;
tApFS_Transaction sfq_oldest_xid;
uint16 sfq_tree_node_limit;
uint16 sfq_pad16;
uint32 sfq_pad32;
uint64 sfq_reserved;
};
struct tApFS_10_SnapshotMetaTree_Value
{
tApFS_Ident ExtentRefIdent; // Идентификатор физического объекта Би-дерева, в котором хранится информация об экстенте
tApFS_Ident SuperBlockIdent; // Идентификатор суперблока
uint64 CreatedTime; // Время создания снимка (в наносекундах с полуночи 01/01/1970)
uint64 LastModifiedTime; // Время изменения снимка (в наносекундах с полуночи 01/01/1970)
uint64 iNum;
uint32 ExtentRefTreeType; // Тип Би-дерева, в котором хранится информация об экстентах
uint16 NameLength; // Длинна имени снимка (включая символ конца строки)
uint8 Name[]; // Имя снимка (заканчивается на 0)
};
struct tApFS_13_ObjectsMapSnapshot_Value
{
uint32 Flags; // Флаги снимков
uint32 Padding; // Зарезервировано (для корректировки)
tApFS_Ident Reserved; // Зарезервировано
};
struct tApFS_15_FusionMiddleTree_Value
{
tApFS_Address fmv_lba;
uint32 fmv_length;
uint32 fmv_flags;
};
Пример структуры файловой системы ApFS:
Volume Superblock (Суперблок тома)
Суперблок тома (Volume Superblock) - существует для каждого тома в файловой системе. Он содержит название тома, идентификатор и отметку времени. Подобно суперблоку контейнера (Container Superblock), он содержит указатель на карту блоков, которая отображает идентификаторы блоков на их смещения. Кроме того, в суперблоке тома хранится указатель на корневой каталог, который хранится как узел.
Смещение (HEX) | Тип | Id | Описание |
---|---|---|---|
0 | tApFS_COH | Header | Заголовок объекта-контейнера (Container Object Header) |
20 | uint32 | MagicNumber (APSB) | Значение, которое можно использовать для проверки того, что мы читаем экземпляр Volume Superblock |
24 | uint32 | IndexInSuperBlock | Индекс идентификатора объекта этого тома в массиве тома контейнера |
28 | uint64 | Features | Bitmap основных функций, используемых томом |
30 | uint64 | ReadOnlyFeatures | Bitmap основных функций (только для чтения), используемых томом |
38 | uint64 | IncompatibleFeatures | Битовая карта (Bitmap) несовместимых функций объема |
40 | uint64 | LastUnmountTime | Время последнего размонтирования тома (в наносекундах с полуночи 01.01.1970) |
48 | uint64 | ReservedBlocksCount | Количество блоков, зарезервированных для выделения тома |
50 | uint64 | QuotaBlocksCount | Максимальное количество блоков, которое этот том может выделить |
58 | uint64 | AllocatedCount | Количество блоков, выделенных в настоящее время файловой системе этого тома. |
60 | uint8 | MetaCryptoState[20] | Информация о ключе, используемом для шифрования метаданных для этого тома (экземпляр wrapped_meta_crypto_state_t) |
74 | uint32 | RootTreeType | Тип дерева корневой папки (обычно: тип ( eApFS_ObjectFlag_Virtual << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип eApFS_ObjectType_0E_FileSystemTree ) |
78 | uint32 | ExtentRefTreeType | Тип дерева привязки экстентов (обычно: тип ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип OBJECT_TYPE_BLOCKREF ) |
7C | uint32 | SnapshotMetaTreeType | Тип дерева метаданных снимка (обычно: тип ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип OBJECT_TYPE_BLOCKREF ) |
80 | tApFS_Ident | ObjectsMapIdent | Идентификатор физического объекта на карте объемного объекта |
88 | tApFS_Ident | RootTreeIdent | Идентификатор виртуального объекта дерева корневой папки |
90 | tApFS_Ident | ExtentRefTreeIdent | Идентификатор физического объекта дерева связей экстентов |
98 | tApFS_Ident | SnapshotMetaTreeIdent | Идентификатор виртуального объекта дерева метаданных снимка |
A0 | tApFS_Transaction | RevertToXid | Номер транзакции моментального снимка, в который будет возвращен том |
A8 | tApFS_Ident | RevertToSuperBlock | Идентификатор физического объекта VS, к которому вернется том |
B0 | uint64 | NextObjectIdent | Следующий идентификатор, который будет назначен объекту файловой системы на томе. |
B8 | uint64 | NumberOfFiles | Количество обычных файлов в томе |
C0 | uint64 | NumberOfDirectories | Количество папок в томе |
C8 | uint64 | NumberOfSymbolicLinks | Количество символьных ссылок в томе |
D0 | uint64 | NumberOfOtherObjects | Количество других объектов в томе (не включая x0B8_NumberOfFiles , x0C0_NumberOfDirectories и x0C8_NumberOfSymbolicLinks ) |
D8 | uint64 | NumberOfSnapshots | Количество снимков в этом томе |
E0 | uint64 | TotalBlocksAllocated | Общее количество блоков, выделенных этим томом |
E8 | uint64 | TotalBlocksFreed | Общее количество блоков, освобожденных этим томом |
F0 | tApFS_Uuid | Uuid | |
100 | uint64 | LastModifiedTime | Время последнего изменения этого объема (в наносекундах с полуночи 01.01.1970) |
108 | uint64 | Flags | |
110 | tApFS_0D_FSM | FormattedBy | Информация о программном обеспечении, создавшем этот том |
140 | tApFS_0D_FSM | ModifiedBy[8] | Информация о программном обеспечении, изменившем этот объем |
2C0 | uint8 | VolumeName[256] | Имя нулевого тома строки UTF-8 |
3C0 | uint32 | NextDocumentIdent | Следующий идентификатор документа, который будет назначен (хранится в расширенном поле APFS_0E_TYPE_DOCUMENT_ID документа) |
3C4 | uint16 | Role | Растровое изображение роли тома |
3C6 | uint16 | Reserved | |
3C8 | tApFS_Transaction | RootToXid | Номер транзакции снэпшота для некорневых или ноль для корневых |
3D0 | tApFS_Ident | EncryptStateIdent | Текущее состояние шифрования или дешифрования, или ноль, если нет шифрования |
Подробная иллюстрация «APFS»:
Checkpoint (Чекпоинт)
Чекпоинт - это временное состояние контейнера. Каждая контрольная точка инициализируется в Суперблоке контейнера, и текущее состояние обычно является последним. Чекпоинт включает метаданные как контейнера, так и тома. Точки восстановления и снимки похожи друг на друга. Основное различие между чекпоинтом и моментальным снимком заключается в возможности пользователя восстановить файловую систему из сохраненных моментальных снимков с помощью API файловой системы.
Checkpoint Superblock Descriptor (Дескриптор Чекпоинта Суперблока)
Этот блок содержит информацию о структурах метаданных в «ApFS» и является предшествующим блоком Дескриптора. Наиболее важной информацией в этом блоке является расположение Bitmap Structure (BMS), бывшего файла распределения в HFS +.
Дескриптор суперблока контрольной точки:
Bitmap Structures (Битовая карта или карта тома)
Записи об использованных и неиспользованных блоках. Существует только одна карта тома, которая покрывает весь контейнер и является общей для всех томов в файловой системе. «ApFS» использует набор блоков для хранения Карты тома (Bitmap Structures).
В «ApFS» карта являются общей для всех томов в контейнере. В каждом томе указаны котировки блока в контейнере, но сами блоки не находятся в выделенных областях. Ссылка на карту тома лежит в Дескрипторе чекпоинта суперблока (CSBD), в котором находиться информация о самом верхнем уровне структуры, дескрипторе битовой карты (BMD). На рисунке ниже показана базовая структура этой карты. Она разбита по уровням, где BMD находиться вверху и устанавливает границы. Внизу лежат «Bitmap Blocks» (BMB), которые отслеживают блоки в контейнере. Один байт в BMB отслеживает восемь блоков, каждый бит которых обеспечивает статус распределения. Каждый бит - это статус отдельного блока.
Таблицы (Tables)
Таблицы используются в каталоге и экстентах B-дерева, списке томов и карте идентификатора объекта.
Таблицы, используемые в «ApFS», представляют собой небольшие одноблочные «базы данных» с несколько иным назначением в структурах файловой системы. Поле типа таблицы состоит из 2 байтов, расположенных в блоке со смещением 0x20 непосредственно после заголовка узла. Существует восемь таблиц от 0 до 7. Последующие 2 байта обеспечивают уровень таблицы от 0 и выше. В таблице второго уровня будут записи, относящиеся к базовой таблице первого уровня. А таблицы нулевого уровня относятся к блокам, которые часто содержат метаданные файлов.
Типы таблиц различаются по структуре, но заголовок таблицы для всех типов имеет 24-байтовый вид.
На рисунке представлен образец структуры заголовка таблицы:
Описание значений полей в структуре заголовка:
Смещение (HEX) | Поле | Тип данных | Описание |
---|---|---|---|
20 | tableType | uint16 | Возможные значения 0-7. Это таблица 1 |
22 | tableLevel | uint16 | Указывает уровень B-дерева. |
24 | tableRecords | uint16 | Количество записей в таблице |
26 | Unknown 1 | uint16 | |
28 | Unknown 2 | uint16 | |
2A | tableIndexSize | uint16 | Размер области индекса таблицы. |
2C | tableKeyAreaSize | uint16 | Размер ключевой области таблицы. |
2E | tableFreeSpaceSize | uint16 | Размер свободной площади. Область данных таблицы заканчивается со смещением 0x38+tableIndexSize+tableKeyAreaSize+tableFreeSpaceSize. 0x38 + 0x80 + 0x170 + 0xd58 . |
30 | Unknown 3 | uint16 | |
32 | Unknown 4 | uint16 | |
34 | Unknown 5 | uint16 | |
36 | Unknown 6 | uint16 |
Здесь показан общий макет различных таблиц:
Не все элементы на картинке используются во всех таблицах. На рисунке показан полный блок с заголовком блока верхнего узла. Остальная часть блока составляет таблицу.
Сразу после заголовка таблицы идет индекс записи. Их есть 2 типа. Один с двумя значениями: смещением в ключах, и смещением в разделе данных для каждого из Uint16. Второй использует 4 значения Uint16 со смещением и длиной как для ключа, так и для разделов данных. Индекс записи таблицы содержит информацию о ключах и записях данных в таблице. Еще одно различие между типами таблиц - использование нижних колонтитулов.
В таблицах 1, 3, 5 и 7 в конце блока используется нижний колонтитул размером 0x28 байтов. В этих таблицах все смещения данных относятся к смещению 0xFD8, а нижний колонтитул содержит различные значения, специфичные для типа таблицы. Другие типы таблиц не имеют нижнего колонтитула, и все ссылки на содержимое раздела данных относятся к концу блока.
В B-деревьях с несколькими уровнями, - таблицы 1, 3, 5 и 7-я находятся на самом верхнем уровне, поскольку они имеют нижний колонтитул. Нижний колонтитул, используется для хранения информации о полном B-дереве. Одно из значений в нижнем колонтитуле - это общее количество записей в структуре этого дерева.
Определение таблицы начинается со смещения 0x20 в блоке. Здесь указан тип таблицы, количество строк, размер ключевого раздела и промежуток между ключом и разделом данных. После свойств таблицы, определения строк и столбцов описываются смещение 0x38. Таблица содержит заголовок, определения записей, разделы ключей и данных. У некоторых типов таблиц также есть нижний колонтитул. Заголовок начинается со смещения 0x20 и имеет длину 0x18 байт. Заголовок этого типа таблицы начинается с 16-битового значения, которое представляет тип таблицы. Затем следуют два байта, представляющие уровень в B-дереве, на котором используется таблица. Два последующих байта представляют количество строк в таблице. Длина записи определения сканирования находится в 0x2A, за которым следует Uint16, который записывает длину ключевого раздела. Далее следует разрыв между ключом и разделом данных. Нижний колонтитул таблицы всегда равен 0x28 байтам и всегда занимает конец блока. А индексы таблицы имеют 4 или 8 байтов каждый. На 8-байтовых индексах два первых «Uint16» - это смещение и длина ключевой записи. Следующие два «Uint16» - это смещение и длина записи данных в таблице. Таблицы с 4-байтовыми индексами имеют два значения Uint16, которые содержат смещение ключа и записей данных. Длина данных в двух записях предопределена. В таблицах с нижним колонтитулом смещение записи данных относительно начала нижнего колонтитула (0x28 байт). А для других типов таблиц это смещение относится к концу блока.
Большинство значений, касающихся заголовка и нижнего колонтитула таблицы, ясны, по крайней мере, для чтения типа таблицы. Смещение 0x18 в нижнем колонтитуле (смещение 0xFF в блоке 4 Кб) - это количество записей в таблице и во всех базовых таблицах (если это таблица с уровнем выше 0, по смещению 0x22). Смещение 0x20 в нижнем колонтитуле - это номер следующей записи в таблице.
Таблица 0
Таблица 0 типа лежит в структуре каталога B-дерева между узлами листьев и корневым узлом. Значения Неизвестно (Unknown) c 3 по 6 представлены в виде смещения и длины ключа. Смещения данных и длины следующей доступной записи. Если свободных индексных записей нет, смещения устанавливаются на «0xFFFF» и длину «0x00».
Записи в таблице представляют собой четыре значения «Uint16». Первые 2 - это смещение и длина значения в ключевом разделе, а следующие - это смещение и значение содержимого в разделе данных.
Примером таблицы 0 типа может быть идентификатор узла каталога, именной ключ в разделе ключей и идентификатор объекта в разделе данных. У этой таблицы нет нижнего колонтитула.
Таблица 1
Первая таблица имеет нижний колонтитул, а индекс таблицы содержит четыре 16-битных значений, где первые 2 значения представляют собой смещение записи в ключевом разделе и длину записи. Следующие 2 значения обеспечивают смещение записи в разделе данных и ее длину. Эта таблица часто встречается как в структуре каталога B-дерева, так и в дереве экстентов для узла верхнего уровня. Примером являются значения: «Parent ID» и имя ключа (имя файла или папки в структуре каталога, и начальный номер блока в B-дереве экстентов), идентификатор объекта при использовании в качестве корневого узла в структуре каталога или номер блока, когда используется в дереве экстентов.
Примеры этой таблицы приведены ниже:
Таблица 2
Вторая таблица. Первоначально эта таблица идентична предыдущей, но не имеет нижнего колонтитула. Этот тип таблицы очень часто встречается в конечных узлах в структуре каталога B-дерева, где ключевой раздел представлен с «Parent ID» и именем ключа.
Таблица 3
Третья таблица идентична предыдущей. Индекс таблицы такой же, как у первой таблицы. Типичные значения зависят от структуры, в которой они используются. В структуре каталога B-дерева и дереве экстентов эта таблица часто используется как узел верхнего уровня в небольших объемах, где корневым узлом одновременно является корневой и листовой узел. В таком примере использования, ключевой записью может быть «Parent ID». Именной ключ, и запись данных могут быть файлом метаданных с большим варьированием размера.
Другие записи таблицы — это идентификатор объекта «Object ID» и его тип в ключевой записи, с экстентами информации о файлах и записями данных. 3 таблица имеет нижний колонтитул.
Пример таблицы:
Таблица 4
4 таблица несколько отличается от предыдущих. В таблице нет нижнего колонтитула, а индекс таблицы имеет только 2 значения: смещение записи в ключевом разделе и 1 значение для раздела данных. Длина содержимого фиксирована и составляет 16 байтов в ключевом разделе и 8 байт в разделе данных. Смещения в разделе данных относятся к концу блока.
Таблица 5
5 таблица похожа на 4. Единственное отличие состоит в том, что у этого типа есть нижний колонтитул, и все смещения данных начинаются с «offset-0x28» (начало нижнего колонтитула). Записи в ключевом разделе составляют 16 байтов и 8 байт в разделе данных. Этот тип таблицы чаще всего наблюдается на узлах верхнего уровня в структуре каталога B-дерева и в больших контейнерах с многоуровневыми деревьями.
Таблица 6
6 таблица тоже похожа на 4. Индекс таблицы имеет только смещение к содержимому в разделе ключей и данных, но не ее длину. Длинна определена предварительно. Каждая запись составляет 16 байтов. Для этого типа таблицы нет нижнего колонтитула. Эта таблица часто встречается в конечных узлах структуры каталога B-дерева. Типичное содержимое раздела ключа включает в себя идентификатор объекта и ID Тома Чекпоинта Суперблока «Volume Checkpoint Superblock ID», в то время как в разделе данных обычно записывается их размер и номер блока.
Таблица 7
7 Таблица похожа на 6-ю. Единственным отличием является нижний колонтитул, который содержит информацию, аналогичную описанной для 1 таблицы. Этот тип таблицы наблюдается в широком диапазоне структур и часто встречается на самых верхних уровнях многослойной структуры или в однослойных структурах, таких как описание тома.
Пример
Сводка таблиц
В данной таблице показаны основные свойства различных типов таблиц:
Тип | Нижний колонтитул | Смещение ключевого раздела | Длина ключевого раздела | Смещение раздел данных | Длина раздел данных | Длина Ключа | Длина данныех |
---|---|---|---|---|---|---|---|
0 | НЕТ | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
1 | ДА | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
2 | НЕТ | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
3 | ДА | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
4 | НЕТ | uint16 | uint16 | 16 bytes | 8 bytes | ||
5 | ДА | uint16 | uint16 | 16 bytes | 8 bytes | ||
6 | НЕТ | uint16 | uint16 | 16 bytes | 16 bytes | ||
7 | ДА | uint16 | uint16 | 16 bytes | 16 bytes |
Одним из наиболее важных блоков в структуре каталога B-дерева является корневой узел, который является наивысшим уровнем в структуре папок. Этот узел использует ключи поиска переменной длины. Одной из улучшенных функций «ApFS» является быстрый поиск в каталогах. Одно из значений, которое тесно связано с этой функцией, - это количество всех записей в древовидной структуре, расположенной в нижнем колонтитуле таблицы.
У корневого узла структуры B-дерева есть 2 варианта выбора таблицы, поскольку у обоих есть нижние колонтитулы. 3 Таблица – как корневой узел, наблюдается только в небольших контейнерах с небольшим количеством файлов, где корневой узел также является индексным и листовым узлами.
В карте объектов для корневого узла используется только 5 таблица, за исключением очень маленьких структур, где может встречаться 7-я.
Интерпретация таблиц показывает, что таблицы 0 и 2 имеют одинаковые значения. То же самое наблюдается между таблицами 1 и 3. Эти таблицы, по-видимому, имеют разное назначение в зависимости от того, в какой структуре они находятся.
Моментальные снимки (Snapshots)
Моментальные снимки – это снимки файловой системы тома только для чтения. Операционная система может использовать эти снимки для более эффективной процедуры резервного копирования. Благодаря им Time Machine будет работать быстрее. И благодаря поддержке мгновенных образов «Time Machine», больше не нужно сохранять несколько полных копий файла на диск - она может просто отслеживать определенные изменения. Например, если вы редактируете файл, изменение с использованием HFS +, он сохраняет две копии файла, в первом записаны новые изменения, и второй на случай, если вы захотите вернуться к прежнему виду. В «APFS» сохраняется только исходный файл и записываются различия между исходным файлом и любыми обновленными версиями, занимая меньше места на диске. Как и в случае с улучшениями в Fusion Drive, информация занимает меньше места на диске.
Хотя «ApFS» и значительно уступает по своим возможностям 128-битной ZFS, которая поддерживается Linux, FreeBSD и другими бесплатными ОС, но со стороны Apple это шаг в правильном направлении.
Как упоминалось выше, Apple долгое время пыталась перенести ZFS на OS X. Позже OpenZFS был реализован для OS X (O3X) и MacZFX.
Nodes (узлы)
Узлы - это гибкие контейнеры, которые используются для хранения различных видов записей. Они могут быть частью B-дерева или существовать сами по себе. Узлы могут содержать записи гибкого или фиксированного размера. Узел начинается со списка указателей на ключи входа и записи входа. Таким образом, для каждой записи узел содержит заголовок записи в начале узла, ключ входа в середине узла и запись входа в конце узла.
позиция | размер | тип | ID |
---|---|---|---|
0 | 4 | uint32 | alignment |
4 | 4 | uint32 | ENTRY_COUNT |
10 | 2 | uint16 | HEAD_SIZE |
16 | 8 | entry | meta_entry |
24 | ... | entry | entries (repeat entry_count times) |
Структура заголовка узла (Node header):
Смещение | поле | Тип данных | Комментарии |
---|---|---|---|
0 | Checksum | Uint64 | Fletchers Checksum Algorithm |
8 | ID | Uint64 | Object-ID or Block# |
10 | Checkpoint | Uint64 | |
18 | Unknown | Uint16 | Possible level in B-Tree |
1A | Unknown | Uint16 | All observations shows value 0x4000 |
1C | Unknown | Uint16 | Flag? |
1E | Unknown | Uint16 | Often seen value 0x0b, 0x0e and 0x0f |
Менеджер пространства (Space Manager)
«Space Manager» (Менеджер пространства) используется для управления выделенными блоками в контейнере «ApFS». Хранит количество свободных блоков и указатель на файлы информации о размещении.
позиция | размер | тип | ID |
---|---|---|---|
0 | 4 | uint32 | размер блока |
16 | 8 | uint64 | totalblocks |
40 | 8 | uint64 | freeblocks |
144 | 8 | uint64 | prev_allocationinfofile_block |
352 | 8 | uint64 | allocationinfofile_block |
Allocation info file (Информационный файл распределения)
Файл распределения работает как отсутствующий заголовок. Здесь хранятся длина файлов размещения, версия и его смещение.
позиция | размер | тип | ID |
---|---|---|---|
4 | 4 | uint32 | alloc_file_length |
8 | 4 | uint32 | alloc_file_version |
24 | 4 | uint32 | TOTAL_BLOCKS |
28 | 4 | uint32 | free_blocks |
32 | 4 | uint32 | allocationfile_block |
Файл и папка B-дерева
Записи всех файлов и папок на томе. Они выполняют ту же роль, что и файлы каталога в «HFS+».
Extents (Экстенты B-дерева)
Отдельное B-дерево всех экстентов тома. Экстенты - это ссылки на содержимое файла с информацией о том, где начинается содержимое данных, и о их длине в блоках. Файл с некоторым содержимым будет иметь как минимум один экстент. А фрагментированный файл будет иметь несколько экстентов. Дерево экстентов - это отдельная структура.
В каждой записи файла, экстенты, определяются для каждого из этих файлов в B-дереве. Эта отдельная структура экстентов является частью функции моментального снимка.
64-bit inodes (index descriptors) - индексные дескрипторы
64-битные inodes значительно увеличивают пространство имен по сравнению с 32-битными идентификаторами в «HFS+». 64-разрядная файловая система «ApFS» поддерживает более 9 квинтиллионов файлов на каждом томе. Как сказал Билл Гейтс, этого должно хватить на всех.
«ApFS» предлагает возможность восстановления определенных состояний файловой системы, включая старые или удаленные версии файлов. Суперблок контейнера содержит ссылку на структуру контрольной точки. Контрольная точка ссылается на предыдущий суперблок контейнера, который содержит информацию в более старом состоянии файловой системы. Таким образом, можно восстановить несколько старых состояний путем анализа цепочки суперблока контейнера.
"Для запуска компьютера в режиме восстановления macOS выполните несколько действий:
На Mac выберите меню Apple > «Выключить».
Дождитесь полного выключения Mac. Компьютер Mac полностью выключен тогда, когда экран становится черным и гаснут все индикаторы (включая индикаторы панели Touch Bar).
Нажмите и удерживайте кнопку питания на Mac, пока не появится надпись «Загрузка параметров запуска».
Нажмите «Параметры», затем нажмите «Продолжить».
При появлении запроса выберите том для восстановления, затем нажмите «Далее».
Выберите учетную запись администратора, затем нажмите «Далее».
Введите пароль учетной записи администратора, затем нажмите «Продолжить».
Когда в строке меню появится приложение «Восстановление», выберите доступный вариант в окне или в строке меню"
"Дисковая утилита на Mac поддерживает несколько форматов файловых систем:
Apple File System (APFS). Файловая система, использующаяся в macOS 10.13 и новее.
Mac OS Extended. Файловая система, использующаяся в macOS 10.12 и ранее.
MS-DOS (FAT) и ExFAT. Файловые системы, совместимые с Windows."
"Для отформатирования диска в формат APFS (Apple File System) на компьютере Mac можно выполнить следующие шаги:
Откройте ""Дисковую утилиту"".
Выберите диск, который вы хотите отформатировать в формат APFS.
Нажмите кнопку ""Стереть"" (Erase) в верхней части окна.
В выпадающем меню ""Формат"" (Format) выберите ""APFS"".
Установите любое другое желаемое значение для имени и схемы разделов (Partition Scheme).
Нажмите кнопку ""Стереть"" (Erase), чтобы начать процесс форматирования."