Auf den ersten Blick ist es einfach dd
:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M
Das liest die gesamte Datei und schreibt den gesamten Inhalt zurück.
Um nur das Loch selbst zu schreiben, müssen Sie zuerst bestimmen, wo sich diese Löcher befinden. Sie können dies entweder mit filefrag
oder tun hdparm
:
filefrag:
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1048575: 187357696.. 188406271: 1048576:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188406272: last,eof
sparsefile: 2 extents found
hdparm:
# hdparm --fibmap sparsefile
sparsefile:
filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
byte_offset begin_LBA end_LBA sectors
0 1498861568 1507250175 8388608
6442450944 1605633024 1614021631 8388608
Diese Beispieldatei hat, wie Sie sagen, eine 10G
Größe mit einem 2G
Loch. Es hat zwei Ausdehnungen, die erste Abdeckung 0-1048575
, die zweite 1572864-2621439
, was bedeutet, dass das Loch ist 1048576-1572864
(in 4k großen Blöcken, wie durch gezeigt filefrag
). Die von hdparm
angezeigten Informationen sind die gleichen und werden nur unterschiedlich angezeigt (der erste Bereich umfasst 8388608
512-Byte-Sektoren ab 0, also 0-4294967295
Bytes, also ist das Loch 4294967296-6442450944
in Bytes.
Beachten Sie, dass Ihnen bei einer Fragmentierung möglicherweise ohnehin erheblich mehr Ausmaße angezeigt werden. Leider zeigt keiner der Befehle die Löcher direkt an, und ich kenne keinen, der dies tut. Sie müssen ihn daher aus den angezeigten logischen Offsets ableiten.
Das Füllen dieses 1048576-1572864
Lochs mit dd
wie oben gezeigt kann nun durch Hinzufügen geeigneter (identischer) seek
/ skip
Werte und erfolgen count
. Beachten Sie, dass das bs=
angepasst wurde, um die oben verwendeten 4k
Sektoren zu verwenden filefrag
. (Zum Beispiel bs=1M
müssten Sie die Werte für Suchen / Überspringen / Zählen anpassen, um die 1M
Größe der Blöcke widerzuspiegeln .)
dd if=sparsefile of=sparsefile conv=notrunc \
bs=4k seek=1048576 skip=1048576 count=$((-1048576+1572864))
Während Sie Löcher füllen könnten, /dev/zero
anstatt das Loch der Datei selbst zu lesen (was auch nur Nullen ergibt), ist es sicherer, aus dem zu lesen, sparsefile
damit Sie Ihre Daten nicht beschädigen, falls Sie einen falschen Offset haben.
In neueren Versionen von GNU dd
können Sie sich an eine größere Blockgröße halten und alle Werte in Bytes angeben:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M \
iflag=skip_bytes,count_bytes oflag=seek_bytes \
seek=4294967296 skip=4294967296 count=$((-4294967296+6442450944))
filefrag
nachdem ich das ausgeführt habe:
# sync
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1572863: 187357696.. 188930559: 1572864:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188930560: last,eof
sparsefile: 2 extents found
Aufgrund der Fragmentierung sind es immer noch zwei Bereiche. Die logischen Offsets zeigen jedoch, dass diesmal kein Loch vorhanden ist, sodass die Datei nicht mehr dünn ist.
Natürlich ist diese dd
Lösung der sehr manuelle Ansatz. Wenn Sie dies regelmäßig benötigen, ist es einfach, ein kleines Programm zu schreiben, das solche Lücken schließt. Wenn es bereits als Standardwerkzeug vorhanden ist, habe ich noch nichts davon gehört.
Es gibt doch ein Werkzeug, fallocate
das auf eine Art und Weise zu funktionieren scheint:
fallocate -l $(stat --format="%s" sparsefile) sparsefile
Im Fall von XFS wird zwar zwar physischer Bereich für diese Datei zugewiesen, dieser jedoch nicht auf Null gesetzt. filefrag
zeigt solche zugewiesenen, aber ungeschriebenen Ausmaße an.
2: 3.. 15: 7628851.. 7628863: 13: 7629020: unwritten
Dies ist nicht gut genug, wenn die richtigen Daten direkt vom Blockgerät gelesen werden sollen. Es reserviert nur den Speicherplatz, der für zukünftige Schreibvorgänge benötigt wird.
cat sparsefile 1<> sparsefile
. Möglicherweise können Sie unterfallocate
Linux verwenden, um zu vermeiden, dass diese NUL-Bytes geschrieben werden müssen, wenn Sie nur den zuzuweisenden Speicherplatz benötigen.fallocate
. Es hat--dig-holes
aber nein--fill-holes
. Es scheint jedoch gut genug zu funktionieren, wenn Sie die Größe angeben. Ich werde meine Antwort bearbeiten.fallocate
haben eine-z
, die in Linux 3.14 und höher unter ext4 und xfs verwendet werden kann (Sie müssten sie mit-o
und-l
für alle spärlichen Abschnitte ausführen, nehme ich an).-z
speichert Ihre Daten nicht, wenn Sie einen falschen Offset bekommen, also bleibe ichdd
dort ...