Filesystems

向左擴展分區後將文件系統向左移動

  • September 6, 2021

TL;博士

我有一個具有多個分區的dd圖像。disk.dd最終目標是減小此dd圖像文件的大小。

在刪除並重新創建一個編號start sector offset比以前低的分區後(即向左擴展分區)我有一個分區,其中有一個文件系統,它primary superblock位於該分區內的某個位置,我知道哪個扇區這primary superblock住。

我怎樣才能讓e2fsck這個文件系統移動到分區的開頭?

這樣之後我就可以縮小這個文件系統,resize2fs然後從右邊縮小這個分區,即(用較低的重新創建這個分區end sector offset

然後我將在之後的分區上重複這個過程,直到最後一個分區,有效地縮小所有分區,從而減小dd圖像的大小

請不要建議gparted。我正在尋找命令行解決方案

另外,我知道使用LVM. 但是這個遺留系統


長版


我有一個disk.dd使用以下內容拍攝的 dd 圖像

dd if=/dev/sda of=/path/to/disk.dd

具有以下佈局的系統

Disk /dev/loop15: 465.78 GiB, 500107862016 bytes, 976773168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x54093dd5

Device        Boot     Start       End   Sectors   Size Id Type
/dev/loop15p1 *         2048  81922047  81920000  39.1G 83 Linux
/dev/loop15p2       81922048 143362047  61440000  29.3G 82 Linux swap / Solaris
/dev/loop15p3      143362048 163842047  20480000   9.8G 83 Linux
/dev/loop15p4      163842048 976773167 812931120 387.7G  5 Extended
/dev/loop15p5      163844096 976773119 812929024 387.7G 83 Linux

現在,在不同的系統上,我disk.dd通過循環設備使用

losetup --find --partscan disk.dd

我調整了所有ext4文件系統的大小

resize2fs -M /dev/loopNpartX
resize2fs /dev/loopNpartX FSsize

即分區p1p3p5

有了dumpe2fs,我可以看到logical block size文件系統,它是4096所有文件系統的字節ext4,在我上面顯示的情況下,這些文件系統託管在 3 個分區上

現在,如果我在口頭上正確閱讀此內容(如果我在這裡錯了,請糾正我)

文件系統的主超級塊“通常預期”位於0分區的塊中

所以,我可以轉儲超級塊資訊

dumpe2fs -h -o superblock=0 -o blocksize=4096 /dev/loopNpartX

現在是時候縮小分區以減小disk.dd文件大小了


block count再次使用每個文件系統dumpe2fs

fdisk適用於設備的physical block sizeOR sectors,在我的情況下是512字節

因此,為了找到sectors足以容納文件系統的數量,我使用了以下公式

Required Sectors = ( ( Block Count + 100 ) * Logical Block Size ) / Physical Block Size

100充當緩衝區,以防萬一我遺漏了有關文件系統組織的一些內容,這應該足夠了

我對每個文件系統都這樣做了


現在


有了lsblk -f,我得到了現有文件系統的 UUID

使用fdisk -l,我得到要保持打開的boot flag分區

現在要縮小分區,我將使用刪除並重新創建它們fdisk

– 第一個分區

start sector offset = 2048
last sector offset  = 2048 + "Required Sectors" for this filesystem

– 第二分區

現有磁碟上的第二個分區是swap,所以我不會縮小它,只是將它向左移動

start sector offset = "last sector offset" of first partition + 1
last sector offset  = "start sector offset" + Total sectors as as on existing partition

然後我將其類型更改為Swap 然後tune2fs -U將 UUID 更改回dd圖像上的內容

– 第三分區

start sector offset = "last sector offset" of second partition + 1
last sector offset  = "start sector offset" + "Required Sectors" for this filesystem

這是我卡住的地方


將第三個分區向左擴展後,該分區有一個文件系統,我知道它的起始扇區(即具有 的扇區primary superblock

但我不知道如何讓e2fsck這個文件系統在分區上更正它,以便文件系統向左移動到分區的開頭

fsck 是不可能的。在文件系統中,所有東西都有偏移量,如果你改變起始扇區,所有這些偏移量都會改變。fsck 根本無法重寫所有內容(超級塊、日誌、目錄、文件段等)的所有偏移量。即使你能做到這一點,它也只有在新的起始扇區與內部文件系統結構一致的情況下才會起作用。

所以這沒有完成。

相反,您必須使用 dd 將所有數據向左移動(本質上是 gparted 所做的)。只有完全移動文件系統,其中的偏移量才能保持不變。

原則上 dd 命令可以像這樣工作。它以不同的偏移量讀取和寫入同一設備。這僅適用於向左移動,因此 seek(寫入)必須小於skip(讀取)。512b 扇區中的所有單元(如果您指定bs=1M,則您的分區必須是 MiB 對齊的,並且所有單元都在 MiB 中)

dd if=/dev/sdx of=/dev/sdx \
  seek=newpartitionstart \
  skip=oldpartitionstart \
  count=filesystemsize

但是,這是非常危險的。*需要您自擔風險使用它。*請務必花時間先備份您的數據。

向右移動會更複雜。您必須向後工作,否則您會覆蓋尚未讀取的數據,並破壞過程中的所有內容。


我所知道的(或多或少)不移動數據的唯一工具是blocks --lvmify,它通過將現有文件系統分區轉換為 LVM 來實現。使用 LVM,您可以在邏輯上向右擴展,而它在物理上儲存在左側。如果沒有 LVM,您也可以手動設置線性設備映射,但您會遇到非標準解決方案。


解決此類問題(如果您不想使用 gparted)最明智的方法是備份所有數據,然後以您喜歡的任何佈局創建新的分區和文件系統,然後恢復您的數據。

如果此 dd 映像是您的備份解決方案,請考慮改為備份文件。磁碟映像可能很難處理,特別是如果您想在之後轉換它們。


如果您的主要目標是減少映像文件的儲存需求,您可以做的是fstrim(對於循環安裝的文件系統 - 失去所有可用空間),或blkdiscard(對於循環交換分區 - 失去所有數據)。

如果儲存圖像的文件系統支持稀疏文件和打孔,它將使 dd 圖像使用更少的儲存空間而無需更改任何佈局,因為圖像中的任何可用空間也將被釋放用於支持文件系統。

同樣,這是危險的,如果您丟棄圖像文件的錯誤部分,圖像文件將受到不可恢復的損壞。為圖像文件創建循環設備並安裝它的簡單行為已經修改/損壞了圖像文件。

如果源磁碟是 SSD,並且它已經定期使用 fstrim,並且將修剪區域讀取為二進制零,那麼您可以首先使用dd conv=sparse if=/dev/ssd of=ssd.img. 這樣,任何二進制零區域都不會佔用 ssd.img 文件中的空間。請注意,conv=sparse在還原到非零目標驅動器時,在其他方向使用時可能會導致損壞的結果。

引用自:https://unix.stackexchange.com/questions/667877