0. 环境与现象
- 设备:eMMC(
/dev/mmcblk0
) - 分区:
p1~p5
为引导/固件;p5
是只读squashfs
根/rom
;p6
是数据分区(先前只有 ~57 GiB) - 报错:
The primary GPT table is corrupt, but the backup appears OK…
1) 修复 GPT(只修元数据,不动分区内容)
sh
opkg update
opkg install sgdisk
# 备份当前 GPT(以防回滚)
sgdisk -b /root/mmcblk0.gpt.bak /dev/mmcblk0
# 校验现状(此时会有多条 GPT 不一致提示)
sgdisk -v /dev/mmcblk0
# 一键修复:把备份 GPT 挪回盘尾,并重建主表
sgdisk -e /dev/mmcblk0
# 再验证,应显示 No problems found
sgdisk -v /dev/mmcblk0
reboot
验证盘面与空闲区(重启后):
sh
parted /dev/mmcblk0 unit GiB print free
sgdisk -p /dev/mmcblk0
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,TYPE /dev/mmcblk0
2) 吃满剩余空间(两选一)
方案 A:把 p6 扩到盘尾(最简单)
若
p6
已挂载,先umount /dev/mmcblk0p6
(若已作为/overlay
使用,请在维护窗口操作)。
sh
parted -s /dev/mmcblk0 resizepart 6 100%
partprobe /dev/mmcblk0 2>/dev/null || true # 刷新分区表,不行就 reboot
方案 B(兜底):保持起始不变,删并重建同号分区到盘尾
不会动到数据起始位置,但务必确认 p6 起始扇区。
sh
sgdisk -p /dev/mmcblk0 # 记下 p6 的 Start(例如 1131520)
umount /dev/mmcblk0p6 2>/dev/null || true
sgdisk -d 6 /dev/mmcblk0
sgdisk -n 6:<起始LBA>:0 /dev/mmcblk0 # 0 表示一直到盘尾
partprobe /dev/mmcblk0 || true
3) 建/扩文件系统并挂载为下载盘(F2FS)
BT 下载盘推荐 F2FS。若你已有数据且 FS 已存在,请走“扩容”分支。
全新建立:
sh
opkg update
opkg install kmod-fs-f2fs f2fsck mkfs.f2fs block-mount
# 给 p6 创建 F2FS(会清空 p6)
mkfs.f2fs -l data /dev/mmcblk0p6
若要保留现有 F2FS 数据只扩容:
sh
opkg install f2fsck
fsck.f2fs -f /dev/mmcblk0p6
resize.f2fs /dev/mmcblk0p6
挂载点与挂载:
sh
mkdir -p /mnt/data
mount -t f2fs -o rw,noatime /dev/mmcblk0p6 /mnt/data
df -h /mnt/data
设为开机自挂 + BT 优化参数:
BT 下载盘推荐参数:
noatime,lazytime,nodiscard,background_gc=on,flush_merge,extent_cache,mode=adaptive,active_logs=6,alloc_mode=reuse,fsync_mode=posix
sh
# 创建一条新的 fstab 条目(用 label=data 更稳)
uci add fstab mount
uci set fstab.@mount[-1].label='data'
uci set fstab.@mount[-1].target='/mnt/data'
uci set fstab.@mount[-1].fstype='f2fs'
uci set fstab.@mount[-1].options='noatime,lazytime,nodiscard,background_gc=on,flush_merge,extent_cache,mode=adaptive,active_logs=6,alloc_mode=reuse,fsync_mode=posix'
uci set fstab.@mount[-1].enabled='1'
uci commit fstab
/etc/init.d/fstab enable
/etc/init.d/fstab restart
mount | grep /mnt/data
说明:关闭实时
discard
,改用定期fstrim
,通常能减少卡顿;lazytime
降低元数据同步写;其余选项旨在减少写放大与碎片。
4) 每周自动 fstrim
(替代实时 discard)
sh
opkg update && opkg install fstrim
CRON_LINE='0 4 * * 0 /usr/sbin/fstrim -av 2>&1 | logger -t fstrim-weekly'
grep -qxF "$CRON_LINE" /etc/crontabs/root || echo "$CRON_LINE" >> /etc/crontabs/root
/etc/init.d/cron enable
/etc/init.d/cron restart
# 手动验证一次
fstrim -av
logread | grep fstrim-weekly
如需改时间,把
0 4 * * 0
(周日 04:00)换成你想要的 cron 表达式即可。
5) (可选)把 overlay 迁到大分区
只在你想让系统可写层更大时需要。
sh
# 假设 p6 已是 F2FS 且空
mkdir -p /mnt/new
mount -t f2fs /dev/mmcblk0p6 /mnt/new
# 复制现有 overlay 内容(保持权限/属性)
tar -C /overlay -cpf - . | tar -C /mnt/new -xpf -
sync
# 改 fstab:目标改为 /overlay
uci add fstab mount
uci set fstab.@mount[-1].label='data'
uci set fstab.@mount[-1].target='/overlay'
uci set fstab.@mount[-1].fstype='f2fs'
uci set fstab.@mount[-1].options='noatime,lazytime,nodiscard,background_gc=on,flush_merge,extent_cache,mode=adaptive,active_logs=6,alloc_mode=reuse,fsync_mode=posix'
uci set fstab.@mount[-1].enabled='1'
uci commit fstab
reboot
mount | grep overlay
df -h | grep overlay
6) 备份分区表为 U-Boot 可恢复的 GPT_single_boot.bin
按 GPT 规范,前 34 个扇区包含保护 MBR + 主 GPT 头 + 主分区表(128 项时 = 32 扇区),备份表在盘尾(最后 33 个扇区)。
在系统中备份:
sh
# 盘头 34 扇区 -> U-Boot 可直接写回
dd if=/dev/mmcblk0 of=/root/GPT_single_boot.bin bs=512 count=34 conv=sync,fsync
# (可选)盘尾 33 扇区
SECTORS=$(blockdev --getsz /dev/mmcblk0)
START=$((SECTORS - 33))
dd if=/dev/mmcblk0 of=/root/GPT_backup_tail.bin bs=512 skip=$START count=33 conv=sync,fsync
sha256sum /root/GPT_single_boot.bin /root/GPT_backup_tail.bin
7) 常见坑位与回滚
- 千万别动
p1~p5
(引导/固件/只读根)。 partprobe
刷新不到位就 重启。- 若使用方案 B(删并重建分区),起始 LBA 必须与原来一致。
- 开启压缩对 BT 下载盘通常收益不大(多媒体/压缩包为主)。
- 任何涉及分区/格式化的操作均有风险,重要数据请先备份。
到这里,你已经:
- 修复了损坏的 GPT;
- 吃满了 eMMC 的全部空间;
- 用 F2FS + 合理参数挂载为 BT 下载盘;
- 配好了每周自动
fstrim
; - 导出了可被 U-Boot 恢复的
GPT_single_boot.bin
。