
Linuxでスパースファイルがある場合、それをスパースファイルにする方法は?
copyを使用できますが、cp --sparse=never ...
ファイルが10Gでホールが2Gの場合(つまり、割り当てられたスペースが8Gの場合)、元の8Gを新しいファイルにコピーせずにファイルシステムに残りの2Gを割り当てる方法を教えてください。
答え1
表面的にこれは簡単ですdd
。
dd if=sparsefile of=sparsefile conv=notrunc bs=1M
ファイル全体を読み、内容全体を書き換えます。
穴自体のみを書き込むには、まず穴がどこにあるかを確認する必要があります。filefrag
または、以下を使用してこれを実行できますhdparm
。
ファイルの断片:
# 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
HDパラメータ:
# 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
あなたが言ったように、このサンプルファイルにはサイズに穴が10G
あります。2G
これには、最初のカバー0-1048575
と2番目のカバーの2つの範囲があります1572864-2621439
。これは、穴が1048576-1572864
(図のように4kサイズのチャンクfilefrag
)であることを意味します。表示される情報hdparm
は同じですが、別の方法で表示されます(最初の範囲は8388608
0から始まる512バイトのセクタを含むため、バイトである0-4294967295
ため、脆弱性は4294967296-6442450944
バイト単位です)。
断片化がある場合は、より多くの範囲を表示できます。残念ながら、両方のコマンドは脆弱性を直接表示せず、どのコマンドも脆弱性を表示しないため、表示された論理オフセットからこれを推論する必要があります。
1048576-1572864
これで、適切な(同じ)/値sumを追加して、上記のようにこの穴を埋めることができます。上記で使用したセクタを使用するように調整されました。 ( の場合、チャンクサイズを反映するようにナビゲーション/スキップ/カウント値を調整する必要があります。)dd
seek
skip
count
bs=
4k
filefrag
bs=1M
1M
dd if=sparsefile of=sparsefile conv=notrunc \
bs=4k seek=1048576 skip=1048576 count=$((-1048576+1572864))
ファイル自体を読み取る代わりに(0のみが作成された)穴を埋めることもできますが、オフセットが間違っている場合はデータが破損しないように/dev/zero
読み取る方が安全です。sparsefile
最新バージョンでは、GNU dd
より大きなブロックサイズに固執し、すべての値をバイト単位で指定できます。
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
実行後:
# 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
断片化のため、まだ2つの範囲です。しかし、論理オフセットによると、今回は穴がないため、ファイルはもはや希薄ではありません。
もちろん、このdd
ソリューションは非常に受動的なアプローチです。定期的にこの機能が必要な場合は、これらのスペースを埋めるために小さなプログラムを書くのが簡単です。既に標準ツールとして存在する場合は聞いたことがありません。
結局、fallocate
ある程度動作するように見えるツールがあります。
fallocate -l $(stat --format="%s" sparsefile) sparsefile
しかし、最後に、XFSの場合、ファイルに物理領域を割り当てますが、実際にはゼロにはなりません。filefrag
割り当てられたが記録されていない範囲を表示します。
2: 3.. 15: 7628851.. 7628863: 13: 7629020: unwritten
ブロックデバイスから直接正しいデータを読み取ることが目的であれば、これは十分ではない。今後の書き込みに必要な記憶領域のみを予約します。