Tar-Archiv (oder ein anderes Archiv) mit Datenblock-Ausrichtung wie in Originaldateien für eine bessere Deduplizierung auf Blockebene erstellen?

8

Wie kann man eine TAR-Datei generieren, damit der Inhalt geteerter Dateien wie in den Originaldateien blockausgerichtet ist, sodass man von einer Deduplizierung auf Blockebene profitieren kann ( https://unix.stackexchange.com/a/208847/9689 ) ? ?

(Stimmt es, dass das Tar-Format nichts Eigenes enthält, das uns daran hindert, einen solchen Nutzen zu erzielen? Andernfalls, wenn nicht Tar, gibt es möglicherweise einen anderen Archivierer, in den eine solche Funktion integriert ist?)

PS Ich meine "unkomprimierter Teer" - nicht tar + gz oder so - unkomprimierter Teer und Frage fragt nach einem Trick, der das Ausrichten der Dateiblockstufe ermöglicht. AFAIRecall tar wurde für die Verwendung mit Bandmaschinen entwickelt. Ist das Hinzufügen einiger zusätzlicher Bits zur Ausrichtung im Dateiformat möglich und einfach? Ich hoffe es gibt vielleicht sogar ein Werkzeug dafür;). Soweit ich mich erinnere, können TAR-Dateien verkettet werden. Vielleicht gibt es also einen Trick, um Platz für die Ausrichtung zu schaffen.

Grzegorz Wierzowiecki
quelle
Normalerweise kombiniert man Teer mit einer Art Komprimierung, die, selbst wenn dies nur mit Teer funktionieren würde, sicherlich nicht mit Komprimierung funktioniert.
Psusi
Beeindruckend! Gute und kluge Frage.
Adam Ryczkowski

Antworten:

3

Theoretisch ist dies möglich. Aber es ist sehr hässlich und beinhaltet im Wesentlichen die Erstellung unseres Archivs von Hand.

Womit wir es zu tun haben

Das tarFormat arbeitet mit 512-Byte-Blöcken . Diese Größe ist fest und soll der herkömmlichen Größe des Festplattensektors entsprechen. Beim Speichern einer Datei in einem Archiv ist der erste 512-Byte-Block ein Header, der Dateimetadaten (Name, Größe, Typ usw.) enthält. Die folgenden Blöcke enthalten den Dateiinhalt. Unsere archivierten Daten werden also um 512 Bytes falsch ausgerichtet.

Die Blockgröße ("--sectorsize") von btrfs beträgt typischerweise 4096 Bytes . Theoretisch können wir dies wählen, aber in der Praxis sieht es so aus, als müsste es der Seitengröße unserer CPU entsprechen. Wir können also die Blöcke von btrfs nicht verkleinern.

Das tarProgramm hat ein Konzept einer größeren "Datensatzgröße", definiert als ein Vielfaches der Blockgröße, was fast so aussieht, als wäre es nützlich. Es stellt sich heraus, dass dies die Sektorgröße eines bestimmten Bandlaufwerks angeben soll, damit das tarSchreiben von Teilbanddatensätzen vermieden wird. Die Daten werden jedoch immer noch in Einheiten von 512 Bytes erstellt und gepackt, sodass wir diese nicht verwenden können, um tardie Blöcke zu vergrößern , wie Sie es sich erhofft hatten.

Ein letzter Punkt der Daten zu wissen ist , dass tar‚s End-of-Archiv Marker zwei aufeinanderfolgenden all-Nullen - Blöcke ist, es sei denn, diese Blöcke innerhalb von Dateidaten. Daher werden naive Polsterblöcke wahrscheinlich nicht akzeptiert.

Der Hack

Wir können Auffülldateien einfügen. Bevor wir die Datei hinzufügen, die wir deduplizieren möchten (nennen dupwir sie ), fügen wir zu Beginn unseres Archivs eine Datei hinzu pad, deren Größe so ist

pad's header + pad's data + dup's header = 4096 bytes.

Auf diese Weise beginnen dupdie Daten an einer Blockgrenze und können dedupliziert werden.

Dann müssen wir für jede nachfolgende Datei auch die Größe der vorherigen Datei verfolgen, um die richtige Auffüllung zu berechnen. Wir müssen auch vorhersagen, ob eine Art Header-Erweiterung erforderlich sein wird: Beispielsweise bietet der grundlegende Tar-Header nur Platz für 100 Byte Dateipfad, sodass längere Pfade mit einer strukturell speziell benannten Datei codiert werden, deren Daten sind der volle Weg. Im Allgemeinen ist die Vorhersage der tarHeadergröße sehr komplex - das Dateiformat enthält viele Informationen aus mehreren historischen Implementierungen.

Ein kleiner Silberstreifen ist, dass alle Auffülldateien denselben Namen haben können. Wenn wir also entpacken, erhalten wir nur eine zusätzliche Datei mit einer Größe von weniger als 4096 Bytes.

Der sauberste Weg, ein solches Archiv zuverlässig zu erstellen, besteht wahrscheinlich darin, das GNU- tarProgramm zu ändern . Wenn Sie jedoch auf Kosten der CPU- und E / A-Zeit schnell und schmutzig sein möchten, können Sie für jede Datei Folgendes tun:

#!/bin/bash

# Proof of concept and probably buggy.
# If I ever find this script in a production environment,
# I don't know whether I'll laugh or cry.

my_file="$2"
my_archive="$1"

file_size="$(wc -c <"$my_file")"
arch_size="$(tar cb 1 "$my_file" | wc -c)"  # "b 1": Remember that record size I mentioned?  Set it to equal the block size so we can measure usefully.
end_marker_size=1024  # End-of-archive marker: 2 blocks' worth of 0 bytes

hdr_size="$(( (arch_size - file_size - end_marker_size) % 4096 ))"
pad_size="$(( (4096 - 512 - hdr_size) % 4096 ))"
(( pad_size < 512 )) && pad_size="$(( pad_size + 4096 ))"

# Assume the pre-existing archive is already a multiple of 4096 bytes long
# (not including the end-of-archive marker), and add extra padding to the end
# so that it stays that way.
file_blocks_size="$(( ((file_size+511) / 512) * 512 ))"
end_pad_size="$(( 4096 - 512 - (file_blocks_size % 4096) ))"
(( end_pad_size < 512 )) && end_pad_size="$(( end_pad_size + 4096 ))"

head -c $pad_size /dev/zero > _PADDING_
tar rf "$my_archive" _PADDING_ "$my_file"
head -c $end_pad_size /dev/zero > _PADDING_
tar rf "$my_archive" _PADDING_
Jander
quelle