本文主要记录把 OpenWrt 从较小磁盘克隆到更大 NVMe 后,出现 GPT 备份表位置错误、数据分区仍保持旧容量时的处理步骤:用 gdisk 修复 GPT 并扩展末尾分区,再用 e2fsck / resize2fs 扩展 ext 文件系统。

分区与文件系统操作有数据丢失风险。操作前应备份重要数据;下列设备名、扇区号来自当时环境,换盘后必须按本机 fdisk/gdisk 输出重算,不要照抄扇区数字

问题现象

克隆到更大容量磁盘后:

  1. fdisk -l 报 GPT 与磁盘尺寸不匹配,例如:
GPT PMBR size mismatch (... != ...) will be corrected by write.
The backup GPT table is not on the end of the device.
  1. 数据分区(示例中为第 4 分区)容量仍接近克隆源(约 11G),未吃到新盘剩余空间(示例整盘约 477G)。

示意(型号与容量为历史环境):

Disk /dev/nvme0n1: 476.94 GiB, ... sectors
Device             Start      End  Sectors  Size Type
/dev/nvme0n1p1       512   262655   ...     128M Linux filesystem
/dev/nvme0n1p2    262656   786943   ...     256M Linux filesystem
/dev/nvme0n1p3    786944  4981247   ...       2G Linux filesystem
/dev/nvme0n1p4   4982784 28131294   ...      11G Linux filesystem
/dev/nvme0n1p128      34      511   ...     239K BIOS boot

环境背景

项目说明(示例)
系统OpenWrt(BusyBox 用户态,工具需 opkg 安装)
磁盘NVMe,设备节点 /dev/nvme0n1
表类型GPT(含 BIOS boot 小分区,编号可能为 128)
待扩分区末尾 Linux 数据分区(示例 p4,ext4)
工具gdiskfdiske2fsckresize2fs

准备工作

安装 GPT 工具:

opkg update
opkg install gdisk

确认目标盘、分区号与挂载点:

fdisk -l /dev/nvme0n1
mount | grep nvme
df -h

若 p4 是当前 root 或重要数据分区,扩容前规划是否需要 live 环境 / 卸载;已挂载的 ext 分区在部分步骤需要先 umount

修复 GPT 备份表位置

克隆后主 GPT 仍按旧盘末尾记录 secondary header,需把备份表移到新盘末尾。

gdisk /dev/nvme0n1

交互要点:

  1. p 打印分区表,确认 last usable sector 仍偏小(旧盘尺寸)。
  2. x 进入 expert 菜单。
  3. 使用将备份结构移到磁盘末尾的选项(当时环境通过 expert 流程触发;gdiskw 时也可能提示 Secondary header is placed too early)。
  4. w 写入;若提示纠正 secondary header,选 Y

成功后可能看到:

Have moved second header and partition table to correct location.
OK; writing new GUID partition table (GPT) to /dev/nvme0n1.
Warning: The kernel is still using the old partition table.
... run partprobe(8) or kpartx(8)

可执行 partprobe /dev/nvme0n1 或重启后再查。此时 fdisk -l 不应再报 backup GPT 不在盘尾;但 p4 大小可能仍是 11G,只是 free space 已出现在表中。

再次 gdiskp,应能看到较大的 Total free space(示例约 463.5 GiB)。

扩展分区

目标:删除末尾数据分区表项后,以相同起始扇区重建更大分区,使文件系统超级块仍落在原位置,数据可保留。

gdisk /dev/nvme0n1
  1. p 记录 p4 的 Start (sector)(示例 4982784)与类型码(8300)。
  2. d → 分区号 4(只删分区表项;在起始扇区不变且未 mkfs 的前提下,ext 数据仍在盘上)。
  3. n 新建分区:
    • 分区号:4
    • First sector:必须填原起始扇区(示例 4982784),不要用可能对齐到其它边界的默认值(除非你确认默认值相同)
    • Last sector:回车使用默认(盘尾)或显式指定
    • 类型:8300
  4. p 确认 p4 已到预期大容量(示例约 474.6 GiB)。
  5. w 写入并确认 Y

再次提示内核仍用旧表时,执行:

partprobe /dev/nvme0n1
# 或重启
fdisk -l /dev/nvme0n1

期望 p4 的 End/Sectors/Size 已扩大。

扩展文件系统

分区变大后,ext 文件系统仍保持旧块数,需要 resize2fs

若分区已挂载,先卸载(挂载点以现场为准):

umount /dev/nvme0n1p4

若直接 resize2fs 提示 already N blocks 或要求先 fsck:

e2fsck -f /dev/nvme0n1p4
resize2fs /dev/nvme0n1p4

成功示意:

Resizing the filesystem on /dev/nvme0n1p4 to <new-blocks> (4k) blocks.
The filesystem on /dev/nvme0n1p4 is now <new-blocks> (4k) blocks long.

重新挂载后:

mount /dev/nvme0n1p4 <mount-point>
df -h <mount-point>

容量应接近分区大小。

验证结果

检查项期望
fdisk -l无 PMBR/backup GPT 尺寸告警;p4 为扩容后大小
df -h文件系统可用空间显著增加
业务/配置OpenWrt 配置与数据目录仍在(未 mkfs)

历史环境最终分区表示意:p4 约 474.6G,整盘约 476.94 GiB

注意事项

  • 起始扇区写错等于放弃旧文件系统,可能需要备份恢复;操作前抄写 gdisk 的 Start/End。
  • Partition table entries are not in disk order 常见于 BIOS boot 分区号靠后;多数情况可忽略。若需整理,gdisk expert 下有 sort 类操作,整理后注意引导项是否仍指向正确分区,非必须步骤
  • 文件系统若不是 ext4,不要用 resize2fs;btrfs/xfs/f2fs 等换对应工具。
  • 若 p4 是 root 且无法 umount,需进 failsafe、Live USB 或另一系统挂载后再 resize。
  • OpenWrt 分区布局因版本/目标板而异(可能没有 p128 BIOS boot);以本机表为准。
  • 整盘克隆涉及磁盘序列号、UUID、网络配置等,扩容之外的克隆问题不在本文范围。

参考资料