Получи скидку или подарок!

APFS: алгоритм восстановления данных файловой системы и ее структура

«ApFS» предлагает возможность восстановления определенных состояний файловой системы, включая старые или удаленные версии файлов. Суперблок контейнера содержит ссылку на структуру контрольной точки. Контрольная точка ссылается на предыдущий суперблок контейнера, который содержит информацию в более старом состоянии файловой системы. Таким образом, можно восстановить несколько старых состояний путем анализа цепочки суперблока контейнера.

APFS: алгоритм восстановления данных файловой системы и ее структура

Содержание:

Контейнеры и Тома

Структура файловой системы APFS имеет вид b-дерева, где корневой каталог с данными — это листья этого дерева. Все ветви хранят лишь ссылки на следующий узел пока не дойдут до листьев. Файловая система использует контейнеры в качестве ячеек хранения. Эти контейнера могут содержать несколько томов. Также он является основным объектом для хранения данных. Для одного тома размер контейнера должен быть более 512 МБ, для двух томов – более 1024Мб и т.д.

На рисунке ниже представлена структура файловой системы «ApFS».

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
08uint64Контрольная сумма (checksum)
88uint64Идентификатор (block_id)
168uint64Версия (version)
242uint16Тип блока (block_type)
262uint16Флаги (flags)
284uint32Отступ (padding)

Из таблицы мы видим, что 1uint = 1 бит, 8 бит = 1 байту, из этого uint64 = 8, uint32 = 4, и uint16 = 2 байтам.

Container Superblock

Суперблок контейнера (Container Superblock) – это входная точка в файловую систему. Из-за структуры файловой системы с контейнерами и гибкими томами, распределение необходимо обрабатывать на уровне контейнера. Суперблок контейнера содержит информацию о размере блока, их количестве и указателях в менеджере пространства для этой задачи. Кроме того, в суперблоке хранятся идентификаторы (ID) блоков всех томов. Для сопоставления идентификаторов блоков блокам смещения, сохраняется указатель на карту блоков B-дерева. Это дерево содержит записи для каждого тома с его идентификатором и смещением. Суперблок контейнера – это самый высокий уровень файловой системы.

Он имеет следующий вид:

Смещение (HEX)ТипIdОписание
0tApFS_COHHeaderЗаголовок объекта-контейнера (Container Object Header)
20uint32MagicNumber (NXSB)Значение для проверки чтения Суперблока контейнера.
24uint32BlockSizeРазмер блока контейнера (в байтах)
28uint64BlocksCountКоличество контейнерных блоков
30uint64FeaturesКарта (bitmap) основных функций контейнера
38uint64ReadOnlyFeaturesКарта (bitmap) базовых функций контейнера (только для чтения)
40uint64IncompatibleFeaturesКарта (bitmap) основных несовместимых функций контейнера
48tApFS_UuidUuidUUID контейнера
58tApFS_IdentNextIdentСледующий идентификатор для нового логического или виртуального объекта
60tApFS_TransactionNextTransactionНомер следующей транзакции
68uint32DescriptorBlocksКоличество блоков, используемых дескриптором
6Cuint32DataBlocksКоличество блоков, используемых данными
70tApFS_AddressDescriptorBaseБазовый адрес дескриптора или идентификатор физического объекта с деревом адресо
78int32DataBaseАдрес базы данных или идентификатор физического объекта с адресным деревом
80uint32DescriptorNextИндекс следующего дескриптора
84uint32DataNextСледующий индекс данных
88uint32DescriptorIndexИндекс первого действительного элемента в сегменте дескриптора
8Cuint32DescriptorLengthКоличество блоков в сегменте дескриптора, используемого суперблоком
90uint32DataIndexИндекс первого действительного элемента в сегменте данных
94uint32DataLengthКоличество блоков в сегменте данных, используемом суперблоком
98tApFS_IdentSpaceManagerIdentИдентификатор логического объекта Space Manager
A0tApFS_IdentObjectsMapIdentИдентификатор физического объекта карты объекта контейнера
A8tApFS_IdentReaperIdentИдентификатор логического объекта
B0uint32ReservedForTesting
B4uint32MaximumVolumesМаксимально возможное количество объемов в контейнере
B8tApFS_IdentVolumesIdents[100]Объем масива идентификаторов виртуальных объектов
3D8uint64Counters[32]Массив счетчиков, хранящих информацию о контейнере
4D8tApFS_BlockRangeBlockedOutOfRangeФизический диапазон блоков, которые нельзя использовать
4E8tApFS_IdentMappingTreeIdentИдентификатор физического объекта в дереве, используемый для отслеживания объектов, перемещаемых из заблокированного хранилища.
4F0uint64OtherFlagsКарта других функций контейнера
4F8tApFS_AddressJumpstartEFIId физического объекта с данными EFI-драйвера
500tApFS_UuidFusionUuidUUID контейнера Fusion или ноль для контейнеров, отличных от Fusion
510tApFS_BlockRangeKeyLockerРасположение ключевой метки контейнера
520uint64EphemeralInfo[4]Массив полей, используемый для управления логическими данными
540tApFS_IdentReservedForTesting
548tApFS_IdentFusionMidleTreeIdentТолько для обьединенных устройств
550tApFS_IdentFusionWriteBackIdentТолько для обьединенных устройств
558tApFS_BlockRangeFusionWriteBackBlocksБлоки, используемые для области кэша

С определением типов:

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:

Пример структуры файловой системы ApFS

Volume Superblock (Суперблок тома)

Суперблок тома (Volume Superblock) – существует для каждого тома в файловой системе. Он содержит название тома, идентификатор и отметку времени. Подобно суперблоку контейнера (Container Superblock), он содержит указатель на карту блоков, которая отображает идентификаторы блоков на их смещения. Кроме того, в суперблоке тома хранится указатель на корневой каталог, который хранится как узел.

Смещение (HEX)ТипIdОписание
0tApFS_COHHeader Заголовок объекта-контейнера (Container Object Header)
20uint32 MagicNumber (APSB) Значение, которое можно использовать для проверки того, что мы читаем экземпляр Volume Superblock
24uint32IndexInSuperBlock Индекс идентификатора объекта этого тома в массиве тома контейнера
28uint64Features Bitmap основных функций, используемых томом
30uint64ReadOnlyFeatures Bitmap основных функций (только для чтения), используемых томом
38uint64IncompatibleFeatures Битовая карта (Bitmap) несовместимых функций объема
40uint64LastUnmountTime Время последнего размонтирования тома (в наносекундах с полуночи 01.01.1970)
48uint64ReservedBlocksCount Количество блоков, зарезервированных для выделения тома
50uint64QuotaBlocksCount Максимальное количество блоков, которое этот том может выделить
58uint64AllocatedCount Количество блоков, выделенных в настоящее время файловой системе этого тома.
60uint8 MetaCryptoState[20] Информация о ключе, используемом для шифрования метаданных для этого тома (экземпляр wrapped_meta_crypto_state_t)
74uint32RootTreeType Тип дерева корневой папки (обычно: тип ( eApFS_ObjectFlag_Virtual << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип eApFS_ObjectType_0E_FileSystemTree )
78uint32ExtentRefTreeType Тип дерева привязки экстентов (обычно: тип ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип OBJECT_TYPE_BLOCKREF )
7Cuint32SnapshotMetaTreeType Тип дерева метаданных снимка (обычно: тип ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип OBJECT_TYPE_BLOCKREF )
80tApFS_IdentObjectsMapIdent Идентификатор физического объекта на карте объемного объекта
88tApFS_IdentRootTreeIdent Идентификатор виртуального объекта дерева корневой папки
90tApFS_IdentExtentRefTreeIdent Идентификатор физического объекта дерева связей экстентов
98tApFS_IdentSnapshotMetaTreeIdent Идентификатор виртуального объекта дерева метаданных снимка
A0tApFS_TransactionRevertToXid Номер транзакции моментального снимка, в который будет возвращен том
A8tApFS_IdentRevertToSuperBlock Идентификатор физического объекта VS, к которому вернется том
B0uint64NextObjectIdent Следующий идентификатор, который будет назначен объекту файловой системы на томе.
B8uint64NumberOfFiles Количество обычных файлов в томе
C0uint64NumberOfDirectories Количество папок в томе
C8uint64NumberOfSymbolicLinks Количество символьных ссылок в томе
D0uint64NumberOfOtherObjects Количество других объектов в томе (не включая x0B8_NumberOfFiles , x0C0_NumberOfDirectories и x0C8_NumberOfSymbolicLinks )
D8uint64NumberOfSnapshots Количество снимков в этом томе
E0uint64TotalBlocksAllocated Общее количество блоков, выделенных этим томом
E8uint64TotalBlocksFreed Общее количество блоков, освобожденных этим томом
F0tApFS_UuidUuid
100uint64LastModifiedTime Время последнего изменения этого объема (в наносекундах с полуночи 01.01.1970)
108uint64Flags
110tApFS_0D_FSMFormattedByИнформация о программном обеспечении, создавшем этот том
140tApFS_0D_FSMModifiedBy[8] Информация о программном обеспечении, изменившем этот объем
2C0uint8 VolumeName[256]Имя нулевого тома строки UTF-8
3C0uint32NextDocumentIdent Следующий идентификатор документа, который будет назначен (хранится в расширенном поле APFS_0E_TYPE_DOCUMENT_ID документа)
3C4uint16Role Растровое изображение роли тома
3C6uint16Reserved
3C8 tApFS_TransactionRootToXid Номер транзакции снэпшота для некорневых или ноль для корневых
3D0tApFS_IdentEncryptStateIdent Текущее состояние шифрования или дешифрования, или ноль, если нет шифрования

Подробная иллюстрация «APFS»:

Подробная иллюстрация APFS

Checkpoint (Чекпоинт)

Чекпоинт – это временное состояние контейнера. Каждая контрольная точка инициализируется в Суперблоке контейнера, и текущее состояние обычно является последним. Чекпоинт включает метаданные как контейнера, так и тома. Точки восстановления и снимки похожи друг на друга. Основное различие между чекпоинтом и моментальным снимком заключается в возможности пользователя восстановить файловую систему из сохраненных моментальных снимков с помощью API файловой системы.

Checkpoint Superblock Descriptor (Дескриптор Чекпоинта Суперблока)

Этот блок содержит информацию о структурах метаданных в «ApFS» и является предшествующим блоком Дескриптора. Наиболее важной информацией в этом блоке является расположение Bitmap Structure (BMS), бывшего файла распределения в HFS +.

Дескриптор суперблока контрольной точки:

Дескриптор суперблока контрольной точки

Bitmap Structures (Битовая карта или карта тома)

Записи об использованных и неиспользованных блоках. Существует только одна карта тома, которая покрывает весь контейнер и является общей для всех томов в файловой системе. «ApFS» использует набор блоков для хранения Карты тома (Bitmap Structures).

В «ApFS» карта являются общей для всех томов в контейнере. В каждом томе указаны котировки блока в контейнере, но сами блоки не находятся в выделенных областях. Ссылка на карту тома лежит в Дескрипторе чекпоинта суперблока (CSBD), в котором находиться информация о самом верхнем уровне структуры, дескрипторе битовой карты (BMD). На рисунке ниже показана базовая структура этой карты. Она разбита по уровням, где BMD находиться вверху и устанавливает границы. Внизу лежат «Bitmap Blocks» (BMB), которые отслеживают блоки в контейнере. Один байт в BMB отслеживает восемь блоков, каждый бит которых обеспечивает статус распределения. Каждый бит – это статус отдельного блока.

Bitmap Blocks

Таблицы (Tables)

Таблицы используются в каталоге и экстентах B-дерева, списке томов и карте идентификатора объекта.

Таблицы, используемые в «ApFS», представляют собой небольшие одноблочные «базы данных» с несколько иным назначением в структурах файловой системы. Поле типа таблицы состоит из 2 байтов, расположенных в блоке со смещением 0x20 непосредственно после заголовка узла. Существует восемь таблиц от 0 до 7. Последующие 2 байта обеспечивают уровень таблицы от 0 и выше. В таблице второго уровня будут записи, относящиеся к базовой таблице первого уровня. А таблицы нулевого уровня относятся к блокам, которые часто содержат метаданные файлов.

Типы таблиц различаются по структуре, но заголовок таблицы для всех типов имеет 24-байтовый вид.

На рисунке представлен образец структуры заголовка таблицы:

На рисунке представлен образец структуры заголовка таблицы

Описание значений полей в структуре заголовка:

Смещение (HEX)ПолеТип данныхОписание
20tableTypeuint16Возможные значения 0-7. Это таблица 1
22tableLeveluint16Указывает уровень B-дерева.
24tableRecordsuint16Количество записей в таблице
26Unknown 1uint16
28Unknown 2uint16
2AtableIndexSizeuint16Размер области индекса таблицы.
2CtableKeyAreaSizeuint16Размер ключевой области таблицы.
2EtableFreeSpaceSizeuint16Размер свободной площади. Область данных таблицы заканчивается со смещением
0x38+tableIndexSize+tableKeyAreaSize+tableFreeSpaceSize. 0x38 + 0x80 + 0x170 + 0xd58 .
30Unknown 3uint16
32Unknown 4uint16
34Unknown 5uint16
36Unknown 6uint16

Здесь показан общий макет различных таблиц:

Здесь показан общий макет различных таблиц

Не все элементы на картинке используются во всех таблицах. На рисунке показан полный блок с заголовком блока верхнего узла. Остальная часть блока составляет таблицу.

Сразу после заголовка таблицы идет индекс записи. Их есть 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НЕТuint16uint16uint16uint16VariesPossible
1ДАuint16uint16uint16uint16VariesPossible
2НЕТuint16uint16uint16uint16VariesPossible
3ДАuint16uint16uint16uint16VariesPossible
4НЕТuint16uint1616 bytes8 bytes
5ДАuint16uint1616 bytes8 bytes
6НЕТuint16uint1616 bytes16 bytes
7ДАuint16uint1616 bytes16 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-дерева или существовать сами по себе. Узлы могут содержать записи гибкого или фиксированного размера. Узел начинается со списка указателей на ключи входа и записи входа. Таким образом, для каждой записи узел содержит заголовок записи в начале узла, ключ входа в середине узла и запись входа в конце узла.

Nodes (узлы)
позицияразмертипID
04uint32alignment
44uint32ENTRY_COUNT
102uint16HEAD_SIZE
168entrymeta_entry
24entryentries (repeat entry_count times)

Структура заголовка узла (Node header):

СмещениеполеТип данныхКомментарии
0ChecksumUint64Fletchers Checksum Algorithm
8IDUint64Object-ID or Block#
10CheckpointUint64
18UnknownUint16Possible level in B-Tree
1AUnknownUint16All observations shows value 0x4000
1CUnknownUint16Flag?
1EUnknownUint16Often seen value 0x0b, 0x0e and 0x0f

Менеджер пространства (Space Manager)

«Space Manager» (Менеджер пространства) используется для управления выделенными блоками в контейнере «ApFS». Хранит количество свободных блоков и указатель на файлы информации о размещении.

позицияразмертипID
04uint32размер блока
168uint64totalblocks
408uint64freeblocks
1448uint64prev_allocationinfofile_block
3528uint64allocationinfofile_block

Allocation info file (Информационный файл распределения)

Файл распределения работает как отсутствующий заголовок. Здесь хранятся длина файлов размещения, версия и его смещение.

позицияразмертипID
44uint32alloc_file_length
84uint32alloc_file_version
244uint32TOTAL_BLOCKS
284uint32free_blocks
324uint32allocationfile_block

Файл и папка B-дерева

Записи всех файлов и папок на томе. Они выполняют ту же роль, что и файлы каталога в «HFS+».

Extents (Экстенты B-дерева)

Отдельное B-дерево всех экстентов тома. Экстенты – это ссылки на содержимое файла с информацией о том, где начинается содержимое данных, и о их длине в блоках. Файл с некоторым содержимым будет иметь как минимум один экстент. А фрагментированный файл будет иметь несколько экстентов. Дерево экстентов – это отдельная структура.

В каждой записи файла, экстенты, определяются для каждого из этих файлов в B-дереве. Эта отдельная структура экстентов является частью функции моментального снимка.

64-bit inodes (index descriptors) – индексные дескрипторы

64-битные inodes значительно увеличивают пространство имен по сравнению с 32-битными идентификаторами в «HFS+». 64-разрядная файловая система «ApFS» поддерживает более 9 квинтиллионов файлов на каждом томе. Как сказал Билл Гейтс, этого должно хватить на всех.

«ApFS» предлагает возможность восстановления определенных состояний файловой системы, включая старые или удаленные версии файлов. Суперблок контейнера содержит ссылку на структуру контрольной точки. Контрольная точка ссылается на предыдущий суперблок контейнера, который содержит информацию в более старом состоянии файловой системы. Таким образом, можно восстановить несколько старых состояний путем анализа цепочки суперблока контейнера.

Рекомендуем для вас