Zunächst einmal sind Sie nicht allein , wenn Sie über diese Art von Problemen rätseln.
Dies ist nicht nur auf NFSv4 beschränkt, tmpfs
sondern wurde bereits als Problem angeführt
.
Wenn eine Anwendung "Löcher" in einer Sparse-Datei liest, konvertiert das Dateisystem leere Blöcke in "echte" Blöcke, die mit Nullen gefüllt sind, und gibt sie an die Anwendung zurück.
Wenn md5sum
versucht wird, eine Datei zu scannen, wird dies explizit in
sequenzieller Reihenfolge ausgeführt , was sehr sinnvoll ist, wenn man davon ausgeht, was md5sum versucht.
Da die Datei im Grunde genommen "Lücken" aufweist, führt dieses sequentielle Lesen (in einigen Situationen) dazu, dass beim Schreiben eine Kopie die Datei ausfüllt. Dies führt dann zu einer tieferen Frage, ob dies fallocate()
vom Dateisystem unterstützt wird oder nicht FALLOC_FL_PUNCH_HOLE
.
Glücklicherweise wird dies nicht nur tmpfs
unterstützt, sondern es gibt auch einen Mechanismus, um die Löcher wieder auszugraben.
Mit dem CLI-Dienstprogramm können fallocate
wir diese Löcher erfolgreich erkennen und neu graben.
Wie pro man 1 fallocate
:
-d, --dig-holes
Detect and dig holes. This makes the file sparse in-place, without
using extra disk space. The minimum size of the hole depends on
filesystem I/O block size (usually 4096 bytes). Also, when using
this option, --keep-size is implied. If no range is specified by
--offset and --length, then the entire file is analyzed for holes.
You can think of this option as doing a "cp --sparse" and then
renaming the destination file to the original, without the need for
extra disk space.
See --punch-hole for a list of supported filesystems.
fallocate
arbeitet jedoch auf Dateiebene und wenn Sie md5sum
gegen ein Blockgerät laufen (das sequentielle Lesevorgänge anfordert), stoßen Sie auf die genaue Lücke zwischen der Funktionsweise des fallocate()
Syscalls. Wir können dies in Aktion sehen:
In Aktion sehen wir anhand Ihres Beispiels Folgendes:
$ fs=$(mktemp -d)
$ echo ${fs}
/tmp/tmp.ONTGAS8L06
$ dd if=/dev/zero of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2>/dev/null
$ echo "Before:" "$(ls ${fs}/sparse100M -s)"
Before: 0 /tmp/tmp.ONTGAS8L06/sparse100M
$ sudo losetup /dev/loop0 ${fs}/sparse100M
$ sudo md5sum /dev/loop0
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 102400 /tmp/tmp.ONTGAS8L06/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ONTGAS8L06/sparse100M
Nun ... das beantwortet Ihre grundlegende Frage. Mein allgemeines Motto ist "werde komisch", also habe ich mich weiter eingegraben ...
$ fs=$(mktemp -d)
$ echo ${fs}
/tmp/tmp.ZcAxvW32GY
$ dd if=/dev/zero of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2>/dev/null
$ echo "Before:" "$(ls ${fs}/sparse100M -s)"
Before: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo losetup /dev/loop0 ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 1036 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51 /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 1036 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 520 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51 /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 520 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 516 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51 /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 512 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51 /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
Sie sehen , dass nur der Akt der Durchführung der losetup
die Größe der Datei mit geringer Dichte ändert. Dies wird zu einer interessanten Kombination aus tmpfs
der Schnittstelle zwischen HOLE_PUNCH-Mechanismus fallocate
und Blockgeräten.