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 filefragoder 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 10GGröße mit einem 2GLoch. 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 hdparmangezeigten Informationen sind die gleichen und werden nur unterschiedlich angezeigt (der erste Bereich umfasst 8388608512-Byte-Sektoren ab 0, also 0-4294967295Bytes, also ist das Loch 4294967296-6442450944in 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-1572864Lochs mit ddwie oben gezeigt kann nun durch Hinzufügen geeigneter (identischer) seek/ skipWerte und erfolgen count. Beachten Sie, dass das bs=angepasst wurde, um die oben verwendeten 4kSektoren zu verwenden filefrag. (Zum Beispiel bs=1Mmüssten Sie die Werte für Suchen / Überspringen / Zählen anpassen, um die 1MGröß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/zeroanstatt das Loch der Datei selbst zu lesen (was auch nur Nullen ergibt), ist es sicherer, aus dem zu lesen, sparsefiledamit Sie Ihre Daten nicht beschädigen, falls Sie einen falschen Offset haben.
In neueren Versionen von GNU ddkö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 ddLö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, fallocatedas 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. filefragzeigt 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 unterfallocateLinux verwenden, um zu vermeiden, dass diese NUL-Bytes geschrieben werden müssen, wenn Sie nur den zuzuweisenden Speicherplatz benötigen.