OpenWRT(x86_64)中squashfs韌體磁碟空間擴容方法:Overlay擴容,帶有efi的和不帶efi的

Magiclala發表於2024-09-21

在OpenWrt中,最困難,也最痛苦的就是給squashfs韌體磁碟擴容了!

官方擴容的文件

我是研究大神的影片後學習到的,在此自己整理的筆記,大家一起學習吧!

重要提示:在新版本OpenWrt中,如果你的磁碟是M.2口的SSD,那麼你在X86裝置上硬碟刷寫韌體時,很大機率檔案系統會被寫成f2fs檔案系統(不是常規的ext4檔案系統),並且無法線上掛載擴容,因此“很多人(M.2固態刷了squashfs韌體的玩家)無法實現硬碟擴容”

識別檔案系統的方法很簡單:

df -Th或者lsblk -f檢視即可辨別

1.安裝需要的軟體:

root@ImmortalWrt:~# opkg install lsblk fdisk resize2fs losetup blkid f2fs-tools tree
Installing lsblk (2.39-2) to root...
Downloading https://mirrors.vsean.net/openwrt/releases/23.05.3/packages/x86_64/base/lsblk_2.39-2_x86_64.ipk
Installing libmount1 (2.39-2) to root...
Downloading https://mirrors.vsean.net/openwrt/releases/23.05.3/packages/x86_64/base/libmount1_2.39-2_x86_64.ipk
Package fdisk (2.39-2) installed in root is up to date.
Installing resize2fs (1.47.0-2) to root...
Downloading https://mirrors.vsean.net/openwrt/releases/23.05.3/packages/x86_64/base/resize2fs_1.47.0-2_x86_64.ipk
Installing losetup (2.39-2) to root...
Downloading https://mirrors.vsean.net/openwrt/releases/23.05.3/packages/x86_64/base/losetup_2.39-2_x86_64.ipk
Installing blkid (2.39-2) to root...
Downloading https://mirrors.vsean.net/openwrt/releases/23.05.3/packages/x86_64/base/blkid_2.39-2_x86_64.ipk
Installing f2fs-tools (1.16.0-1) to root...
Downloading https://mirrors.vsean.net/openwrt/releases/23.05.3/packages/x86_64/base/f2fs-tools_1.16.0-1_x86_64.ipk
Installing f2fsck (1.16.0-1) to root...
Downloading https://mirrors.vsean.net/openwrt/releases/23.05.3/packages/x86_64/base/f2fsck_1.16.0-1_x86_64.ipk
Configuring f2fsck.
Configuring f2fs-tools.
Configuring resize2fs.
Configuring libmount1.
Configuring lsblk.
Configuring losetup.
Configuring blkid.
Configuring tree.

2.檢視磁碟分割槽情況

root@ImmortalWrt:~# fdisk -l
Disk /dev/loop0: 291.06 MiB, 305201152 bytes, 596096 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
GPT PMBR size mismatch (680479 != 123091919) will be corrected by write.
The backup GPT table is corrupt, but the primary appears OK, so that will be used.
The backup GPT table is not on the end of the device.


Disk /dev/sda: 58.69 GiB, 63023063040 bytes, 123091920 sectors
Disk model: SanDisk SSD i110
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: gpt
Disk identifier: 20C60F33-AFC6-96E2-AE0B-E001AE609500

Device      Start    End Sectors  Size Type
/dev/sda1     512  66047   65536   32M Linux filesystem
/dev/sda2   66048 680447  614400  300M Linux filesystem
/dev/sda128    34    511     478  239K BIOS boot

Partition table entries are not in disk order.

我們明確了幾個點:

1、我們需要操作的整個磁碟叫 /dev/sda ,總容量58.69G(Disk /dev/sda: 58.69 GiB)

2、我們需要擴容的分割槽是/dev/sda2 ,這裡的Start是66048,原始空間300M(/dev/sda2 66048 680447 614400 300M Linux filesystem)

3.使用fdisk命令對磁碟從新分割槽(擴容)

1、fdisk /dev/sda擴容磁碟

2、輸入p回車(列印磁碟資訊),觀察後確人:將來要刪除的是第二個盤 /dev/sda2(以p列印的順序為準)

root@ImmortalWrt:~# fdisk /dev/sda

Welcome to fdisk (util-linux 2.39).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

GPT PMBR size mismatch (680479 != 123091919) will be corrected by write.
The backup GPT table is corrupt, but the primary appears OK, so that will be used.
The backup GPT table is not on the end of the device. This problem will be corrected by write.
This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.


Command (m for help): p

Disk /dev/sda: 58.69 GiB, 63023063040 bytes, 123091920 sectors
Disk model: SanDisk SSD i110
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: gpt
Disk identifier: 20C60F33-AFC6-96E2-AE0B-E001AE609500

Device      Start    End Sectors  Size Type
/dev/sda1     512  66047   65536   32M Linux filesystem
/dev/sda2   66048 680447  614400  300M Linux filesystem
/dev/sda128    34    511     478  239K BIOS boot

Partition table entries are not in disk order.

Command (m for help): 

3、輸入d回車(刪除分割槽命令),選擇2回車(選擇刪除第二個分割槽)

Device      Start    End Sectors  Size Type
/dev/sda1     512  66047   65536   32M Linux filesystem
/dev/sda2   66048 680447  614400  300M Linux filesystem
/dev/sda128    34    511     478  239K BIOS boot

Partition table entries are not in disk order.

Command (m for help): d
Partition number (1,2,128, default 128): 2

Partition 2 has been deleted.

Command (m for help): 

4、輸入n回車(建立一個新分割槽),輸入2回車(設定盤序號還是剛剛的2號盤),然後必須要注意,之前2號盤的Start是66048,所以新建立的盤的Start也必須是66048然後回車。

輸入+5g,代表直接新建分割槽為5GB(這樣寫方便,不用計算)

Do you want to remove the signature? [Y]es/[N]o: n(移除之前的識別符號這裡一定要選n

列印分割槽表,確認無誤後,輸入w(儲存,正式寫入,並同步分割槽表)

Command (m for help): n
Partition number (2-127, default 2): 2
First sector (66048-123091886, default 67584): 66048
Last sector, +/-sectors or +/-size{K,M,G,T,P} (66048-123091886, default 123090943): +5g

Created a new partition 2 of type 'Linux filesystem' and of size 5 GiB.
Partition #2 contains a squashfs signature.

Do you want to remove the signature? [Y]es/[N]o: n

Command (m for help): p

Disk /dev/sda: 58.69 GiB, 63023063040 bytes, 123091920 sectors
Disk model: SanDisk SSD i110
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: gpt
Disk identifier: 20C60F33-AFC6-96E2-AE0B-E001AE609500

Device      Start      End  Sectors  Size Type
/dev/sda1     512    66047    65536   32M Linux filesystem
/dev/sda2   66048 10551295 10485248    5G Linux filesystem
/dev/sda128    34      511      478  239K BIOS boot

Partition table entries are not in disk order.

Command (m for help): w
The partition table has been altered.
Syncing disks.

root@ImmortalWrt:~# 

4.檢查新的分割槽表狀態

1、使用fdisk -l列出所有磁碟上的分割槽表資訊,我們看到磁碟分割槽表已經是5G的空間狀態了

root@ImmortalWrt:~# fdisk -l
Disk /dev/loop0: 291.06 MiB, 305201152 bytes, 596096 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


Disk /dev/sda: 58.69 GiB, 63023063040 bytes, 123091920 sectors
Disk model: SanDisk SSD i110
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: gpt
Disk identifier: 20C60F33-AFC6-96E2-AE0B-E001AE609500

Device      Start      End  Sectors  Size Type
/dev/sda1     512    66047    65536   32M Linux filesystem
/dev/sda2   66048 10551295 10485248    5G Linux filesystem
/dev/sda128    34      511      478  239K BIOS boot

Partition table entries are not in disk order.

2、使用df -Th檢視檔案系統磁碟空間使用情況

root@ImmortalWrt:~# df -Th
Filesystem           Type            Size      Used Available Use% Mounted on
/dev/root            squashfs        9.0M      9.0M         0 100% /rom
tmpfs                tmpfs         906.0M      1.1M    904.9M   0% /tmp
/dev/loop0           f2fs          289.1M     63.1M    226.0M  22% /overlay
overlayfs:/overlay   overlay       289.1M     63.1M    226.0M  22% /
/dev/sda1            vfat           31.9M      7.9M     24.1M  25% /boot
/dev/sda1            vfat           31.9M      7.9M     24.1M  25% /boot
tmpfs                tmpfs         512.0K         0    512.0K   0% /dev
/dev/sda1            vfat           31.9M      7.9M     24.1M  25% /mnt/sda1
root@ImmortalWrt:~# 

我們看到,檔案系統並沒有正確識別到新分配的overlay的 / 根分割槽的空間,還是289.1M

5.檢視當前掛載的迴圈裝置狀態

root@ImmortalWrt:~# losetup
NAME       SIZELIMIT  OFFSET AUTOCLEAR RO BACK-FILE  DIO LOG-SEC
/dev/loop0         0 9371648         1  0 /sda2        0     512
root@ImmortalWrt:~# 

結合df-Th命令我們看到,/ 這個掛載點使用了 overlay 檔案系統技術,並且要記住“OFFSET的偏移量是9371648”,未來也要一致才可以!

loop 裝置 /dev/loop0 被對映到了 /sda2 檔案上,也就是說現在/sda2用overlay技術,掛載為/目錄

總結

  • 只讀層/dev/root(型別為 squashfs)。
  • 可寫層/overlay(型別為 f2fs,透過 /dev/loop0 對映到 /sda2 檔案)。
  • 最終掛載點/(型別為 overlay,整合了只讀層和可寫層)。

這就是為什麼squashfs的檔案系統可以有“恢復到出廠設定”功能,而ext4檔案系統沒法恢復的原理。(因為這個根目錄既可以有隻讀層的資料,又有安裝軟體,修改配置檔案的資料)

6.現在我們要重新掛載剛剛建立好的迴圈裝置,以實現替換的目的

因為剛剛講了這個/根目錄是混合型的,必須精確指明哪裡是隻讀的,哪裡是可寫的,所以這個“OFFSET的偏移量是9371648

root@ImmortalWrt:~# losetup -f -o 9371648 /dev/sda2
root@ImmortalWrt:~# losetup
NAME       SIZELIMIT  OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop1         0 9371648         0  0 /dev/sda2   0     512
/dev/loop0         0 9371648         1  0 /sda2       0     512
root@ImmortalWrt:~# 

這裡注意區別,/dev/sda2是分割槽,沒有掛載具體位置,/sda2已經掛載在/根目錄,

7.為了確保資料的一致性,我們先掛載一下資料,檢查一下資料是否存在,在解除安裝釋放資源。因為磁碟剛剛被全刪除了,後面重啟可能會丟失資料,這樣做保險一些。

root@ImmortalWrt:~# mount /dev/loop1 /mnt
root@ImmortalWrt:/mnt# tree -L 2 /mnt
/mnt
├── upper
│   ├── boot
│   ├── etc
│   ├── lib
│   ├── mnt
│   ├── sbin
│   └── usr
└── work
    └── work

10 directories, 0 files
root@ImmortalWrt:~# umount /dev/loop1

8.確認掛載的迴圈裝置的檔案系統格式(是f2fs,還是)

root@ImmortalWrt:/# lsblk -f
NAME     FSTYPE   FSVER LABEL       UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
loop0    f2fs           rootfs_data 1858fcd6-7767-11ef-979c-5fec82ce50f5  225.9M    22% /overlay
loop1    f2fs           rootfs_data 1858fcd6-7767-11ef-979c-5fec82ce50f5                
sda                                                                                     
├─sda1   vfat           kernel      1234-ABCD                              24.1M    25% /mnt/sda1
│                                                                                       /boot
│                                                                                       /boot
├─sda2   squashfs                                                              0   100% /rom
└─sda128                                                                                
root@ImmortalWrt:/# 

9.如果是f2fs的檔案系統,執行擴容命令,重新整理檔案

root@ImmortalWrt:/# resize.f2fs -f /dev/loop1
Info: Force to resize
Info: MKFS version
  "Linux version 5.15.162 (buildbot@buildbot.infra.immortalwrt.org) (x86_64-openwrt-linux-musl-gcc (OpenWrt GCC 12.3.0 r27917-81a1f98d5b) 12.3.0, GNU ld (GNU Binutils) 2.40.0) #0 SMP Thu Jul 18 06:35:54 2024"
Info: FSCK version
  from "Linux version 5.15.162 (buildbot@buildbot.infra.immortalwrt.org) (x86_64-openwrt-linux-musl-gcc (OpenWrt GCC 12.3.0 r27917-81a1f98d5b) 12.3.0, GNU ld (GNU Binutils) 2.40.0) #0 SMP Thu Jul 18 06:35:54 2024"
    to "Linux version 5.15.162 (buildbot@buildbot.infra.immortalwrt.org) (x86_64-openwrt-linux-musl-gcc (OpenWrt GCC 12.3.0 r27917-81a1f98d5b) 12.3.0, GNU ld (GNU Binutils) 2.40.0) #0 SMP Thu Jul 18 06:35:54 2024"
Info: superblock features = 0 : 
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: Segments per section = 1
Info: Sections per zone = 1
Info: total FS sectors = 596096 (291 MB)
Info: CKPT version = 43a353a3
Info: Duplicate valid checkpoint to mirror position 512 -> 1024
Info: Write valid nat_bits in checkpoint
[FIX] (move_one_curseg_info:2921)  --> Move curseg[0] 3 -> 10 after 2c00

[FIX] (move_one_curseg_info:2921)  --> Move curseg[1] 6 -> 13 after 2c00

[FIX] (move_one_curseg_info:2921)  --> Move curseg[2] 4 -> 11 after 2c00

[FIX] (move_one_curseg_info:2921)  --> Move curseg[3] 0 -> e after 2c00

[FIX] (move_one_curseg_info:2921)  --> Move curseg[4] 1 -> f after 2c00

[FIX] (move_one_curseg_info:2921)  --> Move curseg[5] 2 -> 14 after 2c00

Info: Write valid nat_bits in checkpoint
Try to do defragement: Done
[migrate_ssa: 272] Info: Done to migrate SSA blocks: sum_blkaddr = 0xe00 -> 0x2200
[migrate_nat: 389] Info: Done to migrate NAT blocks: nat_blkaddr = 0xa00 -> 0xa00
[migrate_sit: 447] Info: Done to restore new SIT blocks: 0x600
[rebuild_checkpoint: 486] Info: Overprovision ratio = 2.150%
[rebuild_checkpoint: 487] Info: Overprovision segments = 55 (GC reserved = 53)
Info: Write valid nat_bits in checkpoint
[rebuild_checkpoint: 603] Info: Done to rebuild checkpoint blocks
[update_superblock: 765] Info: Done to update superblock

Done: 0.799958 secs
root@ImmortalWrt:/# 

10.如果是ext4檔案系統,執行擴容命令,重新整理檔案

root@ImmortalWrt:/# resize2fs -f /dev/loop1
resize2fs 1.46.5 (30-Dec-2021)
Filesystem at /dev/sdb1 is mounted on /overlay; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 24
The filesystem on /dev/loop1 is now 52428539 (4k) blocks long.

11.擴容後,重啟前的最後一件重要的事(有EFI引導的要注意)

如果你的韌體是帶efi的

# 帶-efi的
immortalwrt-23.05.3-x86-64-generic-squashfs-combined-efi.img
immortalwrt-23.05.3-x86-64-generic-ext4-combined-efi.img
# 不帶-efi的
immortalwrt-23.05.3-x86-64-generic-squashfs-combined.img
immortalwrt-23.05.3-x86-64-generic-ext4-combined.img

確認你的uuid,是sda2的PARTUUID="cfd7abf3-cf18-4a4a-95e4-46f2013c080f",

root@ImmortalWrt:/# blkid
/dev/loop1: LABEL="rootfs_data" UUID="1858fcd6-7767-11ef-979c-5fec82ce50f5" BLOCK_SIZE="4096" TYPE="f2fs"
/dev/loop0: LABEL="rootfs_data" UUID="1858fcd6-7767-11ef-979c-5fec82ce50f5" BLOCK_SIZE="4096" TYPE="f2fs"
/dev/sda2: BLOCK_SIZE="262144" TYPE="squashfs" PARTUUID="cfd7abf3-cf18-4a4a-95e4-46f2013c080f"
/dev/sda128: PARTUUID="20c60f33-afc6-96e2-ae0b-e001ae609580"
/dev/sda1: SEC_TYPE="msdos" LABEL_FATBOOT="kernel" LABEL="kernel" UUID="1234-ABCD" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="20c60f33-afc6-96e2-ae0b-e001ae609501"
root@ImmortalWrt:/# 

並修改你的系統啟動引導

root@ImmortalWrt:/# vim /boot/grub/grub.cfg 

把裡面的2個uuid都改成,sda2的PARTUUID cfd7abf3-cf18-4a4a-95e4-46f2013c080f

root@ImmortalWrt:/# cat /boot/grub/grub.cfg
serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1 --rtscts=off
terminal_input console serial; terminal_output console serial

set default="0"
set timeout="3"
search -l kernel -s root

menuentry "ImmortalWrt" {
	linux /boot/vmlinuz root=PARTUUID=cfd7abf3-cf18-4a4a-95e4-46f2013c080f rootwait   console=tty0 console=ttyS0,115200n8 noinitrd
}
menuentry "ImmortalWrt (failsafe)" {
	linux /boot/vmlinuz failsafe=true root=PARTUUID=cfd7abf3-cf18-4a4a-95e4-46f2013c080f rootwait   console=tty0 console=ttyS0,115200n8 noinitrd
}
root@ImmortalWrt:/# 

12.執行reboot,重啟後生效,檢查最後的分割槽成果!

BusyBox v1.36.1 (2024-07-18 06:35:54 UTC) built-in shell (ash)

.___                               __         .__
|   | _____   _____   ____________/  |______  |  |
|   |/     \ /     \ /  _ \_  __ \   __\__  \ |  |
|   |  Y Y  \  Y Y  (  <_> )  | \/|  |  / __ \|  |__
|___|__|_|  /__|_|  /\____/|__|   |__| (____  /____/
          \/      \/  BE FREE AND UNAFRAID  \/
 -----------------------------------------------------
 ImmortalWrt 23.05.3, r27917-81a1f98d5b
 -----------------------------------------------------
root@ImmortalWrt:~# df -Th
Filesystem           Type            Size      Used Available Use% Mounted on
/dev/root            squashfs        9.0M      9.0M         0 100% /rom
tmpfs                tmpfs         906.0M    104.0K    905.9M   0% /tmp
/dev/loop0           f2fs            5.0G    162.8M      4.8G   3% /overlay
overlayfs:/overlay   overlay         5.0G    162.8M      4.8G   3% /
tmpfs                tmpfs         512.0K         0    512.0K   0% /dev
/dev/sda1            vfat           31.9M      7.9M     24.1M  25% /mnt/sda1
root@ImmortalWrt:~# 

我們可以看到,可用空間已經變成了5G,大功告成。

13.有EFI引導的,必須修改引導,沒有EFI引導的(傳統bios引導的,這取決你當時安裝的是什麼版本),可以跳過這步,直接reboot,重啟後就擴容成功了。

相關文章