將稀疏文件原地轉換為非稀疏文件
在 Linux 上,給定一個稀疏文件,如何使其不稀疏?
可以用 複製
cp --sparse=never ...
,但是如果文件是10G,洞是2G(即分配的空間是8G),如何讓文件系統分配剩餘的2G而不將原來的8G複製到新文件?
從表面上看,這很簡單
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
高畫質晰度:
# 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
,第二個1572864-2621439
,這意味著孔是1048576-1572864
(在 4k 大小的塊中,如圖所示filefrag
)。顯示的資訊hdparm
是相同的,只是顯示方式不同(第一個範圍覆蓋8388608
從 0 開始的 512 字節扇區,所以它是0-4294967295
字節,所以孔4294967296-6442450944
以字節為單位。請注意,如果有任何碎片,您可能會看到更多的範圍。不幸的是,這兩個命令都沒有直接顯示漏洞,而且我不知道有哪個命令會這樣做,因此您必須從顯示的邏輯偏移中推斷出它。
現在,可以通過添加適當的(相同的) /值和來填充該
1048576-1572864
孔,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))
雖然您可以用填充孔
/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
由於碎片化,它仍然是兩個範圍。但是,邏輯偏移顯示這一次,沒有洞,所以文件不再稀疏。
當然,這個
dd
解決方案是非常手動的方法。如果您經常需要它,那麼編寫一個填補這些空白的小程序會很容易。如果它已經作為標準工具存在,我還沒有聽說過。畢竟有一個工具,
fallocate
似乎工作,在時尚之後:fallocate -l $(stat --format="%s" sparsefile) sparsefile
然而,最後在 XFS 的情況下,雖然它確實為這個文件分配了物理區域,但它實際上並沒有將它歸零。
filefrag
顯示已分配但未寫入的範圍。2: 3.. 15: 7628851.. 7628863: 13: 7629020: unwritten
如果目的是能夠直接從塊設備讀取正確的數據,這還不夠好。它只保留未來寫入所需的儲存空間。