Auf meiner ext4
Dateisystempartition kann ich den folgenden Code ausführen:
fs="/mnt/ext4"
#create sparse 100M file on ${fs}
dd if=/dev/zero \
of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2> /dev/null
#show its actual used size before
echo "Before:"
ls ${fs}/sparse100M -s
#setting the sparse file up as loopback and run md5sum on loopback
losetup /dev/loop0 ${fs}/sparse100M
md5sum /dev/loop0
#show its actual used size afterwards
echo "After:"
ls ${fs}/sparse100M -s
#release loopback and remove file
losetup -d /dev/loop0
rm ${fs}/sparse100M
was ergibt
Before:
0 sparse100M
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
After:
0 sparse100M
Unter tmpfs dasselbe tun wie unter:
fs="/tmp"
Ausbeuten
Before:
0 /tmp/sparse100M
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
After:
102400 /tmp/sparse100M
was bedeutet eigentlich, dass etwas, von dem ich erwartet hatte, dass es nur die Daten liest, dazu führte, dass die dünne Datei "wie ein Ballon explodierte"?
Ich tmpfs
gehe davon aus, dass dies an der weniger perfekten Unterstützung für Sparse-Dateien im Dateisystem liegt, insbesondere an der fehlenden FIEMAP ioctl, aber ich bin nicht sicher, was dieses Verhalten verursacht. Kannst du mir sagen?
ext4
tmpfs
sparse-files
Mensch und Frieden
quelle
quelle
Antworten:
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
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 nichtFALLOC_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
:fallocate
arbeitet jedoch auf Dateiebene und wenn Siemd5sum
gegen ein Blockgerät laufen (das sequentielle Lesevorgänge anfordert), stoßen Sie auf die genaue Lücke zwischen der Funktionsweise desfallocate()
Syscalls. Wir können dies in Aktion sehen:In Aktion sehen wir anhand Ihres Beispiels Folgendes:
Nun ... das beantwortet Ihre grundlegende Frage. Mein allgemeines Motto ist "werde komisch", also habe ich mich weiter eingegraben ...
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 austmpfs
der Schnittstelle zwischen HOLE_PUNCH-Mechanismusfallocate
und Blockgeräten.quelle
tmpfs
spärliche Dateien und punch_hole unterstützt werden. Das ist es, was es so verwirrend macht -tmpfs
unterstützt dies. Warum sollten Sie also die spärlichen Löcher füllen, wenn Sie durch ein Loop-Gerät lesen?losetup
Ändert nicht die Dateigröße, sondern erstellt ein Blockgerät, das dann auf den meisten Systemen nach Inhalten durchsucht wird, z. B .: Gibt es eine Partitionstabelle? Gibt es ein Dateisystem mit UUID? soll ich dann einen / dev / disk / by-uuid / symlink erstellen? Und diese Lesevorgänge führen bereits dazu, dass Teile der Sparse-Datei zugewiesen werden, da tmpfs aus mysteriösen Gründen Lücken bei (einigen) Lesevorgängen füllt.loop.c
) durchsucht und festgestellt, dass es zwei relevante Funktionen gibt :lo_read_simple
&lo_read_transfer
. Es gibt einige kleinere Unterschiede, wie sie geringe Speicherzuweisung tun ...lo_read_transfer
tatsächlich anfordert non-blocking io ausslab.h
(GFP_NOIO
) , während ein Durchführenalloc_page()
Anruf.lo_read_simple()
auf der anderen Seite nicht durchführenalloc_page()
.