本文主要记录把 OpenWrt 从较小磁盘克隆到更大 NVMe 后,出现 GPT 备份表位置错误、数据分区仍保持旧容量时的处理步骤:用 gdisk 修复 GPT 并扩展末尾分区,再用 e2fsck / resize2fs 扩展 ext 文件系统。
分区与文件系统操作有数据丢失风险。操作前应备份重要数据;下列设备名、扇区号来自当时环境,换盘后必须按本机 fdisk/gdisk 输出重算,不要照抄扇区数字。
问题现象
克隆到更大容量磁盘后:
fdisk -l报 GPT 与磁盘尺寸不匹配,例如:
GPT PMBR size mismatch (... != ...) will be corrected by write.
The backup GPT table is not on the end of the device.
- 数据分区(示例中为第 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) |
| 工具 | gdisk、fdisk、e2fsck、resize2fs |
准备工作
安装 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
交互要点:
p打印分区表,确认last usable sector仍偏小(旧盘尺寸)。x进入 expert 菜单。- 使用将备份结构移到磁盘末尾的选项(当时环境通过 expert 流程触发;
gdisk在w时也可能提示 Secondary header is placed too early)。 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 已出现在表中。
再次 gdisk → p,应能看到较大的 Total free space(示例约 463.5 GiB)。
扩展分区
目标:删除末尾数据分区表项后,以相同起始扇区重建更大分区,使文件系统超级块仍落在原位置,数据可保留。
gdisk /dev/nvme0n1
p记录 p4 的 Start (sector)(示例4982784)与类型码(8300)。d→ 分区号4(只删分区表项;在起始扇区不变且未 mkfs 的前提下,ext 数据仍在盘上)。n新建分区:- 分区号:
4 - First sector:必须填原起始扇区(示例
4982784),不要用可能对齐到其它边界的默认值(除非你确认默认值相同) - Last sector:回车使用默认(盘尾)或显式指定
- 类型:
8300
- 分区号:
p确认 p4 已到预期大容量(示例约 474.6 GiB)。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 分区号靠后;多数情况可忽略。若需整理,gdiskexpert 下有 sort 类操作,整理后注意引导项是否仍指向正确分区,非必须步骤。- 文件系统若不是 ext4,不要用
resize2fs;btrfs/xfs/f2fs 等换对应工具。 - 若 p4 是 root 且无法 umount,需进 failsafe、Live USB 或另一系统挂载后再 resize。
- OpenWrt 分区布局因版本/目标板而异(可能没有 p128 BIOS boot);以本机表为准。
- 整盘克隆涉及磁盘序列号、UUID、网络配置等,扩容之外的克隆问题不在本文范围。
参考资料
- GPT fdisk (gdisk) 手册
- e2fsprogs:resize2fs / e2fsck
- OpenWrt 文档中关于存储与 fstab 的说明(按当前版本查阅)