APFS: Algorithmus zur Datenwiederherstellung des Dateisystems
“ApFS” bietet die Möglichkeit, bestimmte Zustände des Dateisystems wiederherzustellen, einschließlich alter oder gelöschter Versionen von Dateien . Der Container-Superblock enthält einen Link zur Checkpoint-Struktur. Der Prüfpunkt bezieht sich auf den vorherigen Superblock des Containers, der Informationen im älteren Zustand des Dateisystems enthält Auf diese Weise ist es möglich, mehrere alte Zustände wiederherzustellen indem die Container-Superblock-Kette analysiert wird.
- Container und Volumen
- Block Header
- Container Superblock
- Volume Superblock
- Checkpoint
- Checkpoint Superblock Descriptor
- Bitmap Structures
- Tables
- Zusammenfassung der Tabellen
- Snapshots
- Nodes
- Space Manager
- Allocation info file (Verteilungsinformationsdatei)
- B-Tree Datei und Ordner
- Extents (Erweiterungen des B- Baums)
- 64-bit inodes (index descriptors)
- Fragen und Antworten
- Bemerkungen
Container und Volumen
Die Struktur des APFS-Dateisystems hat die Form eines B-Baums, wobei das Stammdatenverzeichnis die Blätter dieses Baums sind. Alle Zweige speichern nur Links zum nächsten Knoten, bis sie die Blätter erreichen. Das Dateisystem verwendet Container als Speicherorte. Diese Container können mehrere Volumes enthalten. Es ist auch das Hauptobjekt zum Speichern von Daten. Für ein Volume muss die Containergröße mehr als 512 MB betragen, für zwei Volumes mehr als 1024 MB usw.
Die folgende Abbildung zeigt die Struktur des Dateisystems «ApFS».
Jedes Element dieser Struktur (mit Ausnahme der Zuordnungsdatei) beginnt mit einem 32-Byte-Blockheader, der einige allgemeine Informationen zum Block enthält. Als nächstes folgt der Hauptteil des Dateisystems. Es besteht aus den folgenden Elementen:
- 0x01: Container Superblock
- 0x02: Knoten (Node)
- 0x05: Raummanager (Space manager)
- 0x07: Platzierungsdatei (Allocation Info File)
- 0x0C: Kontrollpunkt (Checkpoint)
- 0x0D: Superblock Volume (Volume Superblock)
Container sind normalerweise genau die gleichen wie Einträge in einer GUID-Partitionstabelle (GPT). Sie haben ein eigenes Absturzsicherungs- und Festplattenzuweisungsschema. Jeder Container enthält ein oder mehrere Volumes mit jeweils einem eigenen Namespace, einer Reihe von Dateien und Verzeichnissen.
Das Dateisystem «ApFS» unterstützt die Software «RAID»,nicht direkt, kann jedoch mit Apple RAID-Volumes verwendet werden, um Striping (RAID 0), Spiegelung (RAID 1) und Spleißen (JBOD) zu unterstützen.
Mit einem 64-Bit-Index unterstützen Volume «ApFS» bis zu 9 Billionen (1018) Dateien.
Das neue Dateisystem von Apple verwendet Nanosekunden, um Zeitstempel festzulegen. In HFS + wurden Zeitstempel auf die nächste Sekunde gesetzt. Dadurch wird die Anzahl der Fehler bei Datenübertragungen und anderen Dateivorgängen verringert.
«ApFS» verfügt über eine integrierte Verschlüsselung und verwendet je nach Gerät AES-XTS oder AES-CBC. Der Benutzer kann mehrere Verschlüsselungsschlüssel verwenden, um die Datensicherheit auch bei «physischem Hacking» des Mediums zu gewährleisten.
Dies ist keine vollständige Liste der Innovationen, die «ApFS»hat.
Partitionen, die in «ApFS», formatiert sind, werden von OS X 10.11 Yosemite und früheren Versionen des Betriebssystems nicht erkannt.
Block Header
Jede Dateisystemstruktur in «ApFS» beginnt mit einem Blockheader. Und der Header selbst beginnt mit einer Checksumme. Weitere Informationen im Header umfassen die Copy-on-Write-Version des Blocks, die Block-ID und den Blocktyp.
Schiebe | Größe | Typ | ID |
---|---|---|---|
0 | 8 | uint64 | Checksumme (checksum) |
8 | 8 | uint64 | Identität (block_id) |
16 | 8 | uint64 | Version (version) |
24 | 2 | uint16 | Blocktyp (block_type) |
26 | 2 | uint16 | Zeroflage (flags) |
28 | 4 | uint32 | Einrückung (padding) |
Aus der Tabelle können wir sehen, dass 1uint = 1 Bit, 8 Bit = 1 Byte, aus diesem uint64 = 8, uint32 = 4 und uint16 = 2 Bytes.
Container Superblock
Der Container-Superblock (Superblock Container) – ist der Einstiegspunkt in das Dateisystem. Aufgrund der Struktur des Dateisystems mit Containern und Diskettenvolumes muss die Verteilung auf Containerebene erfolgen. Der Container-Superblock enthält Informationen zur Größe des Blocks, seiner Anzahl und Zeiger im Space Manager für diese Aufgabe. Darüber hinaus speichert der Superblock Block-IDs für alle Volumes. Um Blockkennungen Verschiebungsblöcken zuzuordnen, wird ein Zeiger auf die B-Baum-Blockkarte gespeichert. Dieser Baum enthält Einträge für jedes Volume mit seiner ID und seinem Schiebe. Der Container-Superblock ist die höchste Ebene des Dateisystems.
Es hat die folgende Form:
Schiebe (HEX) | Typ | Id | Definieren |
---|---|---|---|
0 | tApFS_Schlafmodus | Header | Containerobjekt-Header (Container Object Header) |
20 | uint32 | MagicNumber (NXSB) | Der Wert, der zum Lesen des Container-Superblocks überprüft werden soll. |
24 | uint32 | BlockSize | Containerblockgröße (Bytes) |
28 | uint64 | BlocksCount | Anzahl der Containerblöcke |
30 | uint64 | Features | Karte (bitmap) der Hauptfunktionen des Containers |
38 | uint64 | ReadOnlyFeatures | Karte (bitmap) der Grundfunktionen des Containers (schreibgeschützt) |
40 | uint64 | IncompatibleFeatures | Karte (bitmap) der wichtigsten inkompatiblen Containerfunktionen |
48 | tApFS_Uuid | Uuid | Container-UUID |
58 | tApFS_Ident | NextIdent | Nächste Kennung für neues logisches oder virtuelles Objekt |
60 | tApFS_Transaction | NextTransaction | Nächste Transaktionsnummer |
68 | uint32 | DescriptorBlocks | Anzahl der vom Deskriptor verwendeten Blöcke |
6C | uint32 | DataBlocks | Anzahl der von Daten verwendeten Blöcke |
70 | tApFS_Address | DescriptorBase | Basisadresse eines Deskriptors oder Bezeichners eines physischen Objekts mit einem Adressbaum |
78 | int32 | DataBase | Datenbankadresse oder Kennung eines physischen Objekts mit einem Adressbaum |
80 | uint32 | DescriptorNext | Nächster Deskriptorindex |
84 | uint32 | DataNext | Nächster Datenindex |
88 | uint32 | DescriptorIndex | Der Index des ersten gültigen Elements im Deskriptorsegment |
8C | uint32 | DescriptorLength | Die Anzahl der Blöcke im Deskriptorsegment, die vom Superblock verwendet werden |
90 | uint32 | DataIndex | Der Index des ersten gültigen Elements im Datensegment |
94 | uint32 | DataLength | Anzahl der Blöcke im Datensegment, die vom Superblock verwendet werden |
98 | tApFS_Ident | SpaceManagerIdent | Logische Objektkennung Space Manager |
A0 | tApFS_Ident | ObjectsMapIdent | Die Kennung des physischen Kartenobjekts des Containerobjekts |
A8 | tApFS_Ident | ReaperIdent | Logische Objektkennung |
B0 | uint32 | ReservedForTesting | |
B4 | uint32 | MaximumVolumes | Die maximal mögliche Anzahl von Volumes in einem Container |
B8 | tApFS_Ident | VolumesIdents[100] | Volumen des Arrays virtueller Objektkennungen |
3D8 | uint64 | Counters[32] | Array von Zählern, die Informationen über den Container speichern |
4D8 | tApFS_BlockRange | BlockedOutOfRange | Physischer Bereich von Blöcken, die nicht verwendet werden können |
4E8 | tApFS_Ident | MappingTreeIdent | Die Kennung eines physischen Objekts im Baum, mit der Objekte verfolgt werden, die aus dem gesperrten Speicher verschoben wurden. |
4F0 | uint64 | OtherFlags | Karte anderer Containerfunktionen |
4F8 | tApFS_Address | JumpstartEFI | ID eines physischen Objekts mit EFI-Treiberdaten |
500 | tApFS_Uuid | FusionUuid | UUID des Fusionscontainers oder Null für Nicht-Fusionscontainer |
510 | tApFS_BlockRange | KeyLocker | Standort der Container-Schlüsselmarke |
520 | uint64 | EphemeralInfo[4] | Array von Feldern, mit denen logische Daten bearbeitet werden |
540 | tApFS_Ident | ReservedForTesting | |
548 | tApFS_Ident | FusionMidleTreeIdent | Nur für gepoolte Geräte |
550 | tApFS_Ident | FusionWriteBackIdent | Nur für gepoolte Geräte |
558 | tApFS_BlockRange | FusionWriteBackBlocks | Blöcke, die für den Cache-Bereich verwendet werden |
Mit Typdefinitionen:
uint8 tApFS_Uuid;
uint64 tApFS_Ident;
uint64 tApFS_Transaction;
int64 tApFS_Address;
uint64 tApFS_BTreeKey;
и
struct tApFS_BlockRange
{
tApFS_Address First; // Erster Block
uint64 Count; // Anzahl der Blöcke
}
struct tApFS_COH
{
uint64 CheckSum; //CheckSum Blocks
tApFS_Ident Ident; // Kennung
tApFS_Transaction Transaction; // Object change transaction number
uint16 Type; // Objekttyp
uint16 Flags; // Objektflags
uint32 SubType; // Objektuntertyp
};
mit einer Liste von Objekttypen:
enum eApFS_ObjectType
{
eApFS_ObjectType_01_SuperBlock = 0x0001, //Superblock des Containers
eApFS_ObjectType_02_BTreeRoot = 0x0002, // Bi-Baum: Knoten- Element
eApFS_ObjectType_03_BTreeNode = 0x0003, // Bi-Baum: Blatt
eApFS_ObjectType_05_SpaceManager = 0x0005, // Raum- Manager
eApFS_ObjectType_06_SpaceManagerCAB = 0x0006, // Raum- Manager: Segment Adressen
eApFS_ObjectType_07_SpaceManagerCIB = 0x0007, // Raum- Manager: Segment- Informationen
eApFS_ObjectType_08_SpaceManagerBitmap = 0x0008, // Karte Frei Raum die vom Space Manager verwendet wird
eApFS_ObjectType_09_SpaceManagerFreeQueue = 0x0009, // Freier Speicherplatz der vom Space Manager verwendet wird_ (die Schlüssel - _tApFS_09_SpaceManagerFreeQueue_Key_, Angabe - _tApFS_09_SpaceManagerFreeQueue_Value_)
eApFS_ObjectType_0A_ExtentListTree = 0x000A, // Baum der Liste der Erweiterung (die Schlüssel – Schiebe der anfänglichen Erweiterung_tApFS_Address_, Angabe – physischer Ort der Daten _tApFS_BlockRange_)
eApFS_ObjectType_0B_ObjectsMap = 0x000B, // Typ – Karte der Objekten; subType – Baum des Datensatzes Karte der Objekten (die Schlüssel - _tApFS_0B_ObjectsMap_Key_, Angabe - _tApFS_0B_ObjectsMap_Value_)
eApFS_ObjectType_0C_CheckPointMap = 0x000C, // Karte der festen Punkte (CheckPoint)
eApFS_ObjectType_0D_FileSystem = 0x000D, // Datei system des Volumes
eApFS_ObjectType_0E_FileSystemTree = 0x000E, // Baum des Datei Systems (die Schlüssel starten mit _tApFS_BTreeKey_, beschreibt den Typ und den Wert des Schlüssels)
eApFS_ObjectType_0F_BlockReferenceTree = 0x000F, // Baum der Verknüpfungen zu den Blöcken (die Schlüssel - _tApFS_BTreeKey_, Angabe - _tApFS_0F_BlockReferenceTree_Value_)
eApFS_ObjectType_10_SnapshotMetaTree = 0x0010, // Baum Screenshot (die Schlüssel - _tApFS_BTreeKey_, Angabe - _tApFS_10_SnapshotMetaTree_Value_)
eApFS_ObjectType_11_Reaper = 0x0011, // Reaper
eApFS_ObjectType_12_ReaperList = 0x0012, // Reaper List
eApFS_ObjectType_13_ObjectsMapSnapshot = 0x0013, // Baum Screenshot Karten der Objekten (die Schlüssel - _tApFS_Transaction_, Angabe - _tApFS_13_ObjectsMapSnapshot_Value_)
eApFS_ObjectType_14_JumpStartEFI = 0x0014, // EFI Programmlader
eApFS_ObjectType_15_FusionMiddleTree = 0x0015, // Baum der kombinierten Geräten zur Nachverfolgung der Blöcken der Festplatten, der zwischengespeicherten SSD (die Schlüssel - _tApFS_Address_, Angabe - _tApFS_15_FusionMiddleTree_Value_)
eApFS_ObjectType_16_FusionWriteBack = 0x0016, // Auflösungsstatus des Caches Rück- schreiben der kombinierten Geräten
eApFS_ObjectType_17_FusionWriteBackList = 0x0017, // Listenfeld des Caches Rück- schreiben der kombinierten Geräten
eApFS_ObjectType_18_EncryptionState = 0x0018, // Verschlüsseln
eApFS_ObjectType_19_GeneralBitmap = 0x0019, // General Bitmap
eApFS_ObjectType_1A_GeneralBitmapTree = 0x001A, // Baum General Bitmap (keys - uint64, keys - uint64)
eApFS_ObjectType_1B_GeneralBitmapBlock = 0x001B, // Block General Bitmap
eApFS_ObjectType_00_Invalid = 0x0000, // Als Typ ungültig oder als Subtyp fehlt
eApFS_ObjectType_FF_Test = 0x00FF // Zum Testen reserviert (nie auf den Datenträgern gespeichert)
eApFS_ObjectType_FF_Test = 0x00FF // Zum Testen reserviert (nie auf den Datenträgern gespeichert)
};
enum eApFS_ObjectFlag
{
eApFS_ObjectFlag_Virtual = 0x0000, // virtuelles Objekt
eApFS_ObjectFlag_Ephemeral = 0x8000, // logisches Objekt
eApFS_ObjectFlag_Physical = 0x4000, // physikalisches Objekt
eApFS_ObjectFlag_NoHeader = 0x2000, // Objekt ohne Header _tApFS_ContainerObjectHeader_ (z. B., Karte (bitmap) Raum- Manager)
eApFS_ObjectFlag_Encrypted = 0x1000, // Verschlüsseltes Objekt
eApFS_ObjectFlag_NonPersistent = 0x0800, // Ein Objekt mit diesem Flag wird nie auf den Datenträgern gespeichert
eApFS_ObjectFlag_StorageTypeMask = 0xC000, // Bit- (bitmask) maske für den Zugriff auf Flags Objekt- kategorien
eApFS_ObjectFlag_ValidMask = 0xF800 // Gültiger Flag Der Bit- Maske
};
struct tApFS_0B_ObjectsMap_Key
{
tApFS_Ident ObjectIdent; // Identität des Objekts
tApFS_Transaction Transaction; // Tan- Nummer
};
struct tApFS_0B_ObjectsMap_Value
{
uint32 Flags; // Flags
uint32 Size; // Größe des Objekts in Bytes (Vielfaches der Container- Blockgröße)
tApFS_Address Address; // Adresse des Objekts
};
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; // Die Kennung des physischen Objekts, des Bi-Baums in dem die Extent-Informationen gespeichert sind
tApFS_Ident SuperBlockIdent; // Kennung des Superblocks
uint64 CreatedTime; // Zeit der Schöpfung der Aufnahme (in Nanosekunden seit Mitternacht 01/01/1970)
uint64 LastModifiedTime; // Änderungszeit des Schnappschusses (in Nanosekunden seit Mitternacht 01/01/1970)
uint64 iNum;
uint32 ExtentRefTreeType; // Bi- Baum-Typ, in dem die Informationen über Erweiterung gespeichert sind
uint16 NameLength; // Länge des Schnappschussnamens (einschließlich des Symbols Zeilen- Schluß)
uint8 Name[]; // Schnappschuss- Name (endet mit 0)
};
struct tApFS_13_ObjectsMapSnapshot_Value
{
uint32 Flags; // Flags der Schnappschschüssen
uint32 Padding; // Reserviert (für Korrektion)
tApFS_Ident Reserved; // Reserviert
};
struct tApFS_15_FusionMiddleTree_Value
{
tApFS_Address fmv_lba;
uint32 fmv_length;
uint32 fmv_flags;
};
Beispiel für eine Dateisystemstruktur:
Volume Superblock
Volume Superblock - existiert für jedes Volume im Dateisystem. Es enthält den Datenträgernamen, die ID und den Zeitstempel. Wie der Container-Superblock enthält er einen Zeiger auf eine Blockzuordnung, die Block-IDs an ihren Schieben abbildet. Darüber hinaus speichert der Volume-Superblock einen Zeiger auf das Stammverzeichnis, das als Knoten gespeichert wird.
Schiebe (HEX) | Typ | Id | Definieren |
---|---|---|---|
0 | tApFS_COH | Header | Containerobjekt-Header (Container Object Header) |
20 | uint32 | MagicNumber (APSB) | Ein Wert, mit dem überprüft werden kann, ob eine Instanz Volume Superblock gelesen wird |
24 | uint32 | IndexInSuperBlock | Der Index der Objekt-ID dieses Volumes im Volume-Array des Containers |
28 | uint64 | Features | Bitmap der vom Volume verwendeten Hauptfunktionen |
30 | uint64 | ReadOnlyFeatures | Bitmap der vom Volume verwendeten Grundfunktionen (schreibgeschützt) |
38 | uint64 | IncompatibleFeatures | Bitmap inkompatibler Volume-Funktionen |
40 | uint64 | LastUnmountTime | Die Zeit, zu der das Volume zuletzt abgemeldet wurde (in Nanosekunden seit Mitternacht, 01.01.1970) |
48 | uint64 | ReservedBlocksCount | Anzahl der für die Datenträgerzuweisung reservierten Blöcke |
50 | uint64 | QuotaBlocksCount | Die maximale Anzahl von Blöcken, die dieses Volume zuweisen kann |
58 | uint64 | AllocatedCount | Die Anzahl der Blöcke, die derzeit dem Dateisystem dieses Volumes zugeordnet sind. |
60 | uint8 | MetaCryptoState[20] | Informationen zum Schlüssel, mit dem die Metadaten für dieses Volume verschlüsselt werden (Instanz wrapped_meta_crypto_state_t) |
74 | uint32 | RootTreeType | Stammordner-Baumtyp (normalerweise: Typ ( eApFS_ObjectFlag_Virtual << 16) \ eApFS_ObjectType_02_BTreeRoot , Subtyp eApFS_ObjectType_0E_FileSystemTree ) |
78 | uint32 | ExtentRefTreeType | Bindungsbaumtyp der Erweiterungen (normalerweise: Typ ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , Subtyp OBJECT_TYPE_BLOCKREF ) |
7C | uint32 | SnapshotMetaTreeType | Snapshot-Metadatenbaumtyp (normalerweise: Typ ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , Subtyp OBJECT_TYPE_BLOCKREF ) |
80 | tApFS_Ident | ObjectsMapIdent | Physische Objektkennung auf der volumetrischen Objektkarte |
88 | tApFS_Ident | RootTreeIdent | ID des virtuellen Objekts des Stammordnerbaums |
90 | tApFS_Ident | ExtentRefTreeIdent | Die Kennung des physischen Objekts des Verknüpfungsbaums der Erweiterungen |
98 | tApFS_Ident | SnapshotMetaTreeIdent | ID des virtuellen Objekts des Snapshot-Metadatenbaums |
A0 | tApFS_Transaction | RevertToXid | Die Transaktionsnummer des Snapshots, an den das Volume zurückgegeben wird |
A8 | tApFS_Ident | RevertToSuperBlock | ID des physischen VS-Objekts, auf das das Volume zurückgesetzt wird |
B0 | uint64 | NextObjectIdent | Die nächste Kennung, die dem Dateisystemobjekt auf dem Volume zugewiesen wird. |
B8 | uint64 | NumberOfFiles | Anzahl der einfachen Dateien in einem Volume |
C0 | uint64 | NumberOfDirectories | Anzahl der Ordner in einem Volume |
C8 | uint64 | NumberOfSymbolicLinks | Anzahl der symbolischen Links pro Volume |
D0 | uint64 | NumberOfOtherObjects | Anzahl anderer Objekte im Volume (nicht inbegriffen x0B8_NumberOfFiles , x0C0_NumberOfDirectories und x0C8_NumberOfSymbolicLinks ) |
D8 | uint64 | NumberOfSnapshots | Anzahl der Schnappschüsse in diesem Volume |
E0 | uint64 | TotalBlocksAllocated | Die Gesamtzahl der von diesem Volume zugewiesenen Blöcke |
E8 | uint64 | TotalBlocksFreed | Die Gesamtzahl der von diesem Volume freigegebenen Blöcke |
F0 | tApFS_Uuid | Uuid | |
100 | uint64 | LastModifiedTime | Zeitpunkt der letzten Änderung dieses Volumens (in Nanosekunden seit Mitternacht 01.01.1970) |
108 | uint64 | Flags | |
110 | tApFS_0D_FSM | FormattedBy | Informationen zu der Software, die dieses Volume erstellt hat |
140 | tApFS_0D_FSM | ModifiedBy[8] | Informationen zu Software, die dieses Volume geändert hat |
2C0 | uint8 | VolumeName[256] | Name des Volumes Null der Zeile UTF-8 |
3C0 | uint32 | NextDocumentIdent | Die nächste zuzuweisende Dokument-ID (im erweiterten Feld APFS_0E_TYPE_DOCUMENT_ID des Dokuments gespeichert) |
3C4 | uint16 | Role | Volume Role Bitmap |
3C6 | uint16 | Reserved | |
3C8 | tApFS_Transaction | RootToXid | Snapshot-Transaktionsnummer für Nicht-Root oder Null für Root |
3D0 | tApFS_Ident | EncryptStateIdent | Der aktuelle Status der Ver- oder Entschlüsselung oder Null, wenn keine Verschlüsselung vorhanden ist |
Detaillierte Abbildung «APFS»:
Checkpoint
Checkpoint ist ein temporärer Status des Containers. Jeder Prüfpunkt wird im Superblock des Containers initialisiert, und der aktuelle Status ist normalerweise der letzte. Checkpoint enthält Metadaten sowohl für den Container als auch für das Volume. Wiederherstellungspunkte und Schnappschüsse ähneln sich. Der Hauptunterschied zwischen Checkpoint und einem Snapshot besteht in der Fähigkeit des Benutzers, ein Dateisystem aus gespeicherten Snapshots mithilfe der Dateisystem-API wiederherzustellen.
Checkpoint Superblock Descriptor
Dieser Block enthält Informationen zu den Metadatenstrukturen in «ApFS» und ist der vorhergehende Deskriptorblock. Die wichtigste Information in diesem Block ist der Ort Bitmap Structure (BMS), die frühere Verteilungsdatei in в HFS +.
Superblock-Deskriptor des Checkpoints:
Bitmap Structures
Aufzeichnungen über verwendete und nicht verwendete Blöcke. Es gibt nur eine Volume-Map, die den gesamten Container abdeckt und allen Volumes im Dateisystem gemeinsam ist. ApFS verwendet eine Reihe von Blöcken zum Speichern der Volume Map (Bitmap-Strukturen).
In «ApFS» ist die Karte allen Volumes im Container gemeinsam. Jedes Volume enthält Anführungszeichen für den Block im Container, aber die Blöcke selbst befinden sich nicht in den zugewiesenen Bereichen. Der Verweis auf die Volume Map befindet sich im Superblock Checkpoint Descriptor (CSBD), der Informationen über die oberste Ebene der Struktur, den Bitmap Descriptor (BMD), enthält. Die folgende Abbildung zeigt die Grundstruktur dieser Karte. Es ist in Ebenen unterteilt, wobei BMD an der Spitze steht und Grenzen setzt. Unten liegen «Bitmap Blocks» (BMB), die die Blöcke im Container verfolgen. Ein Byte im BMB verfolgt acht Blöcke, von denen jedes Bit einen Zuordnungsstatus liefert. Jedes Bit ist der Status eines separaten Blocks.
Tables
Tabellen werden im B-Tree-Katalog und in den Bereichen, der Volumenliste und der Objekt-ID-Zuordnung verwendet.
Tabellen verwendet in «ApFS», sind klein einteilig «Datenbank» mit einem etwas anderen Zweck in den Strukturen des Dateisystems. Das Tabellentypfeld besteht aus 2 Bytes, die sich in einem Block mit dem Offset 0x20 unmittelbar nach dem Knotenheader befinden. Es gibt acht Tabellen von 0 bis 7. Die nächsten 2 Bytes stellen Tabellenebene 0 und höher bereit. Die Tabelle der zweiten Ebene enthält Datensätze, die sich auf die Basistabelle der ersten Ebene beziehen. Tabellen auf Nullebene beziehen sich auf Blöcke, die häufig Dateimetadaten enthalten.
Tabellentypen unterscheiden sich in der Struktur, aber der Tabellenkopf für alle Typen ist 24 Byte.
Die Abbildung zeigt eine Beispieltabellen-Header-Struktur:
Beschreibung der Feldwerte in der Kopfstruktur:
Schiebe (HEX) | Rand | Datentyp | Definieren |
---|---|---|---|
20 | tableType | uint16 | Mögliche Werte sind 0-7. Dies ist Tabelle 1 |
22 | tableLevel | uint16 | Zeigt die Ebene des B-Baums an. |
24 | tableRecords | uint16 | Anzahl der Datensätze in der Tabelle |
26 | Unknown 1 | uint16 | |
28 | Unknown 2 | uint16 | |
2A | tableIndexSize | uint16 | Größe des Tabellenindexbereichs. |
2C | tableKeyAreaSize | uint16 | Schlüsselbereichsgröße der Tabelle. |
2E | tableFreeSpaceSize | uint16 | Freie Flächengröße. Der Tabellendatenbereich endet mit einem Schiebe 0x38+tableIndexSize+tableKeyAreaSize+tableFreeSpaceSize. 0x38 + 0x80 + 0x170 + 0xd58 . |
30 | Unknown 3 | uint16 | |
32 | Unknown 4 | uint16 | |
34 | Unknown 5 | uint16 | |
36 | Unknown 6 | uint16 |
Hier ist ein allgemeines Grunddesign der verschiedenen Tabellen:
Nicht alle Elemente im Bild werden in allen Tabellen verwendet. Die Abbildung zeigt einen vollständigen Block mit dem Header des oberen Knotenblocks. Der Rest des Blocks bildet eine Tabelle.
Der Index des Datensatzes folgt unmittelbar nach dem Tabellenkopf. Es gibt 2 Arten von ihnen. Einer mit zwei Werten: Schiebe in den Schlüsseln und Schiebe im Datenbereich für jeden Uint16. Die zweite verwendet 4 Uint16-Werte mit Schiebe und Länge für Schlüssel- und Datenpartitionen. Der Tabellendatensatzindex enthält Informationen zu den Schlüsseln und Datensätzen in der Tabelle. Ein weiterer Unterschied zwischen den Tabellentypen ist die Verwendung von Fußzeilen.
In den Tabellen 1, 3, 5 und 7 wird am Ende des Blocks eine 0x28-Byte-Fußzeile verwendet. In diesen Tabellen beziehen sich alle Datenschieben auf den Schiebe 0xFD8, und die Fußzeile enthält verschiedene tabellentypspezifische Werte. Andere Tabellentypen haben keine Fußzeile, und alle Verweise auf den Inhalt des Datenabschnitts beziehen sich auf das Ende des Blocks.
In B-Bäume mit mehreren Ebenen - Die Tabellen 1, 3, 5 und 7 befinden sich auf der obersten Ebene, da sie eine Fußzeile haben. Fußzeile, in der Informationen zum gesamten B-Baum gespeichert werden. Einer der Werte in der Fußzeile ist die Gesamtzahl der Datensätze in der Struktur dieses Baums.
Die Tabellendefinition beginnt bei Schiebe 0x20 im Block. Dies zeigt den Tabellentyp, die Anzahl der Zeilen, die Größe des Schlüsselabschnitts und die Lücke zwischen dem Schlüssel und dem Datenabschnitt. Der Schiebe 0x38 wird nach Tabelleneigenschaften, Zeilen- und Spaltendefinitionen beschrieben. Die Tabelle enthält einen Titel, Datensatzdefinitionen, Schlüssel- und Datenabschnitte. Einige Arten von Tabellen haben auch eine Fußzeile. Der Header beginnt bei Schiebe 0x20 und ist 0x18 Byte lang. Der Header dieses Tabellentyps beginnt mit einem 16-Bit-Wert, der den Tabellentyp darstellt. Dann folgen zwei Bytes, die die Ebene im B-Baum darstellen, auf der die Tabelle verwendet wird. Die nächsten zwei Bytes geben die Anzahl der Zeilen in der Tabelle an. Die Länge des Scan-Definitionsdatensatzes liegt bei 0x2A, gefolgt von Uint16, das die Länge des Schlüsselabschnitts aufzeichnet. Als nächstes kommt die Lücke zwischen dem Schlüssel und dem Datenabschnitt. Die Tabellenfußzeile ist immer 0x28 Byte groß und belegt immer das Ende des Blocks. Und Tabellenindizes sind jeweils 4 oder 8 Bytes. Bei 8-Byte-Indizes sind die ersten beiden «Uint16» - der Schiebe und die Länge des Schlüsseleintrags. Die nächsten beiden «Uint16» - sind der Schiebe und die Länge des Datensatzes in der Tabelle. Tabellen mit 4-Byte-Indizes haben zwei Uint16-Werte, die den Schiebe des Schlüssels und der Datensätze enthalten. Die Länge der Daten in zwei Datensätzen ist vordefiniert. In Tabellen mit Fußzeilen der Schiebe des Datensatzes relativ zum Anfang der Fußzeile (0x28 Byte). Bei anderen Tabellentypen bezieht sich dieser Schiebe auf das Ende des Blocks.
Die meisten Bedeutungen in Bezug auf die Kopf- und Fußzeile der Tabelle sind klar, zumindest zum Lesen des Tabellentyps. Der Fußzeilenschiebe 0x18 (Schiebe 0xFF im 4-KB-Block) ist die Anzahl der Datensätze in der Tabelle und in allen Basistabellen (wenn es sich um eine Tabelle mit einer höheren Ebene als 0 handelt, bei Schiebe 0x22). Der Schiebe 0x20 in der Fußzeile ist die Nummer des nächsten Eintrags in der Tabelle.
Tabellenblatt 0
Eine Tabelle vom Typ 0 liegt in der B-Tree-Verzeichnisstruktur zwischen den Blattknoten und dem Wurzelknoten. Unbekannte Werte 3 bis 6 werden als Schiebe und Schlüssellänge dargestellt. Datenversätze und Länge des nächsten verfügbaren Datensatzes. Wenn keine freien Indexdatensätze vorhanden sind, werden die Schieben auf «0xFFFF» und die Länge «0x00»gesetzt.
Die Einträge in der Tabelle sind vier «Uint16»-Werte. Die ersten 2 sind der Schiebe und die Länge des Werts im Schlüsselabschnitt und die nächsten sind der Schiebe und der Wert des Inhalts im Datenabschnitt.
Ein Beispiel für eine Tabelle vom Typ 0 wäre die Katalogknoten-ID, der Namensschlüssel im Schlüsselabschnitt und die Objekt-ID im Datenabschnitt. Diese Tabelle hat keine Fußzeile.
Tabellenblatt 1
Die erste Tabelle hat eine Fußzeile und der Tabellenindex enthält vier 16-Bit-Werte, wobei die ersten beiden Werte den Schiebe des Eintrags im Schlüsselabschnitt und die Länge des Eintrags darstellen. Die nächsten 2 Werte geben den Schiebe des Datensatzes im Datenabschnitt und seine Länge an. Diese Tabelle befindet sich häufig sowohl in der B-Tree-Verzeichnisstruktur als auch im Extent-Tree für den Knoten der obersten Ebene.Ein Beispiel sind die Werte: «Parent ID» und den Schlüsselnamen (den Namen einer Datei oder eines Ordners in der Verzeichnisstruktur und die Startblocknummer im Extent-B-Baum), die Objekt-ID bei Verwendung als Stammknoten in der Verzeichnisstruktur oder die Blocknummer bei Verwendung im Extent-Baum.
Beispiele für diese Tabelle sind unten angegeben:
Tabellenblatt 2
Tabellenblatt 2. Anfangs ist diese Tabelle mit der vorherigen identisch, hat jedoch keine Fußzeile. Dieser Tabellentyp ist in Blattknoten in der B-Tree-Verzeichnisstruktur sehr verbreitet, in denen der Schlüsselabschnitt mit «Parent ID» und dem Namen des Schlüssels dargestellt wird.
Tabellenblatt 3
Die dritte Tabelle ist identisch mit der vorherigen. Der Tabellenindex entspricht der ersten Tabelle. Typische Werte hängen von der Struktur ab, in der sie verwendet werden. In der B-Baum-Verzeichnisstruktur und im Extent-Baum wird diese Tabelle häufig als Knoten der obersten Ebene in kleinen Volumes verwendet, wobei der Wurzelknoten sowohl der Wurzelknoten als auch der Blattknoten ist. In einem solchen Anwendungsfall könnte der Schlüsseleintrag «Parent ID»sein. Der benannte Schlüssel und Datensatz kann eine Metadatendatei mit großen Größenunterschieden sein.
Die anderen Datensätze in der Tabelle sind «Object ID» und ihr Typ im Schlüsseldatensatz mit Dateieinformationsbereichen und Datensätzen.Tabellenblatt 3 hat eine Fußzeile.
Beispieltabelle:
Tabellenblatt 4
Tabelle 4 unterscheidet sich etwas von den vorherigen. Die Tabelle enthält keine Fußzeile und der Tabellenindex enthält nur zwei Werte: den Datensatzschiebe im Schlüsselabschnitt und einen Wert für den Datenabschnitt. Die Inhaltslänge ist im Schlüsselabschnitt auf 16 Byte und im Datenabschnitt auf 8 Byte festgelegt. Schieben im Datenabschnitt beziehen sich auf das Ende des Blocks.
Tabellenblatt 5
In 5 ist die Tabelle ähnlich zu 4. Der einzige Unterschied besteht darin, dass dieser Typ eine Fußzeile hat und alle Datenversätze mit «offset-0x28» (dem Anfang der Fußzeile) beginnen. Die Einträge im Schlüsselabschnitt sind 16 Bytes und 8 Bytes im Datenabschnitt. Diese Art von Tabelle wird am häufigsten auf Knoten der obersten Ebene in der B-Tree-Verzeichnisstruktur und in großen Containern mit mehrstufigen Bäumen angezeigt.
Tabellenblatt 6
In 6 ähnelt die Tabelle auch 4. Der Index einer Tabelle hat nur einen Schiebe zum Inhalt des Schlüssel- und Datenabschnitts, nicht jedoch zu seiner Länge. Die Länge ist vordefiniert. Jeder Eintrag ist 16 Bytes. Für diese Art von Tabelle gibt es keine Fußzeile. Diese Tabelle befindet sich häufig in den Blattknoten der B-Tree-Verzeichnisstruktur. Typische Inhalte eines Schlüsselabschnitts umfassen die Objekt-ID und die Volume-ID des «Volume Checkpoint Superblock ID», während der Datenabschnitt normalerweise deren Größe und Blocknummer aufzeichnet.
Tabellenblatt 7
Die 7. Tabelle ähnelt der 6. Der einzige Unterschied ist die Fußzeile, die ähnliche Informationen wie in Tabelle 1 enthält. Diese Art von Tabelle ist in einer Vielzahl von Strukturen zu finden und findet sich häufig auf den obersten Ebenen einer Mehrschichtstruktur oder in Einschichtstrukturen wie einer Volumenbeschreibung.
Beispiel
Zusammenfassung der Tabellen
Diese Tabelle zeigt die Haupteigenschaften verschiedener Tabellentypen:
Typ | Fußzeile | Schiebe des Schlüsselabschnittes | Länge des Schlüsselabschnittes | Schiebe des Datenabschnittes | Länge des Datenabschnittes | Schlüssellänge | Länge der Daten |
---|---|---|---|---|---|---|---|
0 | NEIN | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
1 | JA | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
2 | NEIN | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
3 | JA | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
4 | NEIN | uint16 | uint16 | 16 bytes | 8 bytes | ||
5 | JA | uint16 | uint16 | 16 bytes | 8 bytes | ||
6 | NEIN | uint16 | uint16 | 16 bytes | 16 bytes | ||
7 | JA | uint16 | uint16 | 16 bytes | 16 bytes |
Einer der wichtigsten Blöcke in der B-Tree-Verzeichnisstruktur ist der Stammknoten, der die höchste Ebene in der Ordnerstruktur darstellt. Dieser Knoten verwendet Suchschlüssel mit variabler Länge. Eine der verbesserten Funktionen von «ApFS» ist die schnelle Verzeichnissuche. Ein Wert, der eng mit dieser Funktion zusammenhängt, ist die Anzahl aller Einträge in der Baumstruktur in der Tabellenfußzeile.
Der Wurzelknoten der B-Baum-Struktur verfügt über zwei Tabellenauswahloptionen, da beide Fußzeilen haben. 3. Tabelle - kann als Stammknoten nur in kleinen Containern mit einer kleinen Anzahl von Dateien beobachtet werden, wobei der Wurzelknoten auch der Index- und der Blattknoten ist.
In der Feature-Map für den Stammknoten wird nur die 5. Tabelle verwendet, mit Ausnahme sehr kleiner Strukturen, in denen die 7. auftreten kann.
Die Interpretation der Tabellen zeigt, dass die Tabellen 0 und 2 dieselbe Bedeutung haben. Dasselbe wird zwischen den Tabellen 1 und 3 beobachtet. Diese Tabellen scheinen je nach Struktur unterschiedliche Zwecke zu haben.
Snapshots
Snapshots sind schreibgeschützte Dateisystem-Snapshots eines Volumes. Das Betriebssystem kann diese Snapshots für effizientere Sicherungen verwenden. Dank ihnen läuf Time Machine schneller. Dank der Unterstützung für Sofortbilder «Time Machine», müssen Sie nicht mehr mehrere vollständige Kopien einer Datei auf der Festplatte speichern, sondern können einfach bestimmte Änderungen verfolgen. Wenn Sie beispielsweise eine mit HFS + geänderte Datei bearbeiten, werden zwei Kopien der Datei gespeichert, wobei die erste die neuen Änderungen aufzeichnet und die zweite, falls Sie zur vorherigen Ansicht zurückkehren möchten. «APFS» behält nur die Originaldatei bei und zeichnet die Unterschiede zwischen der Originaldatei und allen aktualisierten Versionen auf, wodurch weniger Speicherplatz benötigt wird. Wie bei den Verbesserungen in Fusion Drive, beanspruchen Informationen weniger Speicherplatz.
Obwohl «ApFS» in seinen Fähigkeiten 128-Bit-ZFS deutlich unterlegen ist, die von Linux, FreeBSD und anderen kostenlosen Betriebssystemen unterstützt, aber von Apples Seite ist dies ein Schritt in die richtige Richtung.
Wie oben erwähnt, hat Apple lange versucht, ZFS auf OS X zu vertauschen. Später wurde OpenZFS für OS X (O3X) und MacZFX implementiert.
Nodes
Knoten(Nodes) sind flexible Container, in denen verschiedene Arten von Datensätzen gespeichert werden. Sie können Teil des B-Baums sein oder alleine existieren. Knoten können Datensätze mit flexibler oder fester Größe enthalten. Der Knoten beginnt mit einer Liste von Zeigern auf Eingabeschlüssel und Eintragseinträge. Daher enthält der Knoten für jeden Datensatz den Datensatzkopf am Anfang des Knotens, den Eingabeschlüssel in der Mitte des Knotens und den Eintragseintrag am Ende des Knotens.
Position | Größe | Typ | 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) |
Knoten-Header-Struktur (Node header):
Schiebe | Rand | Datentyp | Kommentare |
---|---|---|---|
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» wird verwendet, um zugewiesene Blöcke in einem Container «ApFS» zu verwalten. Speichert die Anzahl der freien Blöcke und einen Zeiger auf Zuordnungsinformationsdateien.
Position | Größe | Typ | ID |
---|---|---|---|
0 | 4 | uint32 | Größe des Blocks |
16 | 8 | uint64 | totalblocks |
40 | 8 | uint64 | freeblocks |
144 | 8 | uint64 | prev_allocationinfofile_block |
352 | 8 | uint64 | allocationinfofile_block |
Allocation info file (Verteilungsinformationsdatei)
Die Verteilungsdatei fungiert als fehlender Header. Hier werden die Länge der Platzierungsdateien, die Version und deren Schiebe gespeichert.
Position | Größe | Typ | 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-Tree Datei und Ordner
Aufzeichnungen aller Dateien und Ordner auf dem Volume. Sie haben dieselbe Rolle wie Katalogdateien in «HFS+».
Extents (Erweiterungen des B- Baums)
Ein separater B-Baum aller Erweiterungen (Extents) des Volumes. Extents sind Links zum Inhalt einer Datei mit Informationen darüber, wo der Inhalt der Daten beginnt, und deren Länge in Blöcken. Eine Datei mit einigen Inhalten hat mindestens eine Erweiterung. Eine fragmentierte Datei hat mehrere Extents. Der Extent-Baum ist eine separate Struktur.
In jedem Dateieintrag werden Extents für jede dieser Dateien im B-Baum definiert. Diese separate Extent-Struktur ist Teil der Snapshot-Funktion.
64-bit inodes (index descriptors)
64-Bit-Inodes erhöhen den Namespace gegenüber 32-Bit-Bezeichnern in «HFS+»erheblich. Das 64-Bit-Dateisystem «ApFS» unterstützt mehr als 9 Billionen Dateien pro Volume. Wie Bill Gates sagte, sollte dies für alle ausreichen.
«ApFS» bietet die Möglichkeit, bestimmte Zustände des Dateisystems wiederherzustellen, einschließlich alter oder gelöschter Versionen von Dateien. Der Container-Superblock enthält einen Link zur Checkpoint-Struktur. Checkpoint bezieht sich auf den vorherigen Superblock des Containers, der Informationen im älteren Zustand des Dateisystems enthält. Somit ist es möglich, mehrere alte Zustände wiederherzustellen, indem die Container-Superblock-Kette analysiert wird.