Skip to content

ext4 根分区转换为 Btrfs

作者名字

btrfs-convert 可以把现有的 ext2/3/4 文件系统原地转换为 Btrfs,不需要先删除分区再重装系统。但它仍然是一次高风险的磁盘操作:转换会重写文件系统元数据,断电、设备选错、备份不可用或引导配置没有更新,都可能让系统无法启动甚至丢失数据。

这篇文章记录一套适合公开分享、也适合自己照着执行的流程。示例环境是 Debian 13(trixie)、x86_64、UEFI、GRUB,以及一块 NVMe 磁盘上的 ext4 根分区。命令中的设备名和 UUID 只代表示例,必须以你在 Live 环境中重新执行的检查结果为准

先说结论:什么时候不要做

如果重要数据只有 Ventoy U 盘上的一份备份,建议先暂停转换。这个 U 盘既是备份介质,又是唯一的救援启动介质,属于明显的单点故障。把 ISO 文件复制到 Ventoy 数据分区本身不会格式化 U 盘,但它不能替代第二份独立备份;U 盘损坏时,备份和 Live 环境可能同时失效。

至少满足下面条件后再继续:

官方文档也提醒,原地转换依赖源文件系统的空闲空间,无法事先精确估算所需空间;如果可以接受重新分区和复制数据,重新格式化为 Btrfs 再从备份恢复通常更干净。Btrfs btrfs-convert 文档把这种方案列为应当考虑的替代方案。

我的本地环境

本文写作时检查到的环境如下:

项目当前值
系统Debian GNU/Linux 13(trixie)
内核6.12.85,x86_64
启动方式UEFI
系统盘/dev/nvme0n1,约 954 GiB
EFI 系统分区/dev/nvme0n1p1,约 976 MiB,vfat,挂载到 /boot/efi
根分区/dev/nvme0n1p2,约 921 GiB,ext4,挂载到 /
交换分区/dev/nvme0n1p6,约 31.7 GiB
根分区使用量约 447 GiB / 906 GiB,52%
根分区 UUIDb81fd5ad-9c5f-4b60-9ae1-d884ab37145d
EFI UUIDD941-6C56
当前启动项Debian 的 shimx64.efi

这个布局意味着本次转换的对象只有 /dev/nvme0n1p2。EFI 分区、交换分区和分区表不需要转换,/home 也在根分区里面,因此根分区转换会同时覆盖系统文件和 /home 中的文件。

本机当前没有安装 btrfs-progs,所以不能在已启动的系统里直接执行 btrfs-convert;转换工具应该从 Live 环境提供,转换完成后还要把 btrfs-progs 安装进目标 Debian 系统。GRUB 文件实际位于 /usr/sbin/grub-install,只是当前普通用户的 PATH 没有包含 /usr/sbin,不要仅凭 command -v 的结果判断 GRUB 是否安装。

一、准备 Ventoy Live 环境

1. 下载并校验 ISO

对于这台 Debian 13 amd64 机器,可以从 Debian Live 官方页面 下载 amd64 Live ISO。桌面版比较大,标准版比较小;转换时只要能进入终端、联网安装工具即可。

下载 ISO 后,先计算校验和,并与 Debian 发布目录中的 SHA256SUMS 对比:

sha256sum debian-live-13*-amd64-*.iso

不要跳过校验。ISO 下载不完整或被替换,会让唯一的救援介质变得不可靠。

2. 把 ISO 复制到 Ventoy 数据分区

确认插入的是 Ventoy U 盘后再执行:

lsblk -e7 -o NAME,PATH,MODEL,SIZE,TYPE,FSTYPE,LABEL,UUID,MOUNTPOINTS
findmnt -D

Ventoy 的数据分区通常是 exFAT、NTFS 或 ext4。把 ISO 作为普通文件复制到这个数据分区,不要对整个 U 盘执行 dd,也不要运行任何格式化命令。复制完成后执行 sync

本文开始检查时没有检测到已插入的 Ventoy 设备,说明不能凭当前系统输出推断 U 盘的设备名。插入后必须重新运行 lsblk;尤其不要把 /dev/nvme0n1/dev/nvme0n1p2 误认为 U 盘。

3. 从 UEFI 模式启动 Live ISO

重启,在固件启动菜单中选择带有 UEFI 字样的 USB/Ventoy 项,再选择 Live ISO。进入终端后确认:

test -d /sys/firmware/efi && echo "UEFI mode" || echo "Legacy BIOS mode"

如果输出是 Legacy BIOS,先重启并改用 UEFI 项。当前机器的启动项是 Debian 的 shimx64.efi,不要在 Legacy 模式下进行转换。

二、进入 Live 环境后的安全检查

1. 安装或确认工具

Live 环境可能没有预装 Btrfs 工具。连接网络后执行:

sudo apt update
sudo apt install btrfs-progs e2fsprogs efibootmgr
btrfs --version
btrfs-convert --version
fsck.ext4 -V
efibootmgr -v

如果 Live 环境没有网络,要么换一个带工具的 Live ISO,要么提前准备好 btrfs-progs 及其依赖。在无法安装目标系统所需工具之前,不要重启进入转换后的系统。

2. 重新识别目标分区

在原系统中可以先记录自己的 /etc/fstab;进入 Live 后,下面这些命令用于重新识别磁盘,不要直接照抄本文 UUID。注意:Live 环境里的 /etc/fstab 属于 Live 系统,不是硬盘上的 Debian;目标系统的 fstab 要在后面挂载到 TARGET 后再读取。

lsblk -e7 -o NAME,PATH,MODEL,SIZE,TYPE,FSTYPE,FSVER,LABEL,UUID,MOUNTPOINTS,PARTUUID
findmnt -no SOURCE,TARGET,FSTYPE,OPTIONS /
findmnt -no SOURCE,TARGET,FSTYPE,OPTIONS /boot/efi
swapon --show

本文对应的机器应类似于:

/dev/nvme0n1p1  vfat  /boot/efi
/dev/nvme0n1p2  ext4  /
/dev/nvme0n1p6  swap  [SWAP]

如果设备名、容量、挂载点或文件系统类型有任何不同,停止并重新判断。 /dev/sda/dev/nvme0n1/dev/nvme0n1p2 不是可以互换的写法。

3. 检查备份和空间

转换前至少保存并核对 /home 中的重要文档、照片、代码和密钥,以及 ~/.ssh、GPG 密钥、服务配置和数据。也应保存 /etc/etc/fstab 和已安装软件清单。

df -hT /
sudo cp -a /etc/fstab /path/to/your/backup/fstab.before-btrfs
dpkg --get-selections > /path/to/your/backup/dpkg-selections.before-btrfs.txt

/path/to/your/backup 换成备份介质上的实际路径。仅仅看到备份文件存在不等于备份可恢复,至少要抽查并打开几个重要文件。

转换利用 ext4 的空闲空间。当前根分区使用率约 52%,比接近满盘宽裕,但这不是成功保证;所需空间取决于文件布局和元数据。空间紧张时只能清理可重新下载的缓存,不要为了挤空间删除尚未备份的重要文件。

三、卸载根分区并检查 ext4

假设已经确认设备,先写入变量。下面的值只适用于本文记录的本地环境:

ROOT_DEV=/dev/nvme0n1p2
ESP_DEV=/dev/nvme0n1p1
SWAP_DEV=/dev/nvme0n1p6
TARGET=/mnt/ext4-to-btrfs
printf 'root=%s\nesp=%s\nswap=%s\n' "$ROOT_DEV" "$ESP_DEV" "$SWAP_DEV"
lsblk -o PATH,SIZE,TYPE,FSTYPE,MOUNTPOINTS "$ROOT_DEV" "$ESP_DEV" "$SWAP_DEV"

Live 桌面可能自动挂载内部磁盘。先查看并卸载对应挂载点:

findmnt -S "$ROOT_DEV"
findmnt -S "$ESP_DEV"
sudo swapoff "$SWAP_DEV"

确保根分区完全卸载后,执行强制检查:

sudo fsck.ext4 -f "$ROOT_DEV"

只有检查完成且没有待修复错误时才能继续。如果 fsck 修复了问题,修复后再运行一次;如果检查失败、要求人工处理或报告硬件 I/O 错误,停止转换。

四、执行原地转换

这是风险最高的一步。转换前再次确认目标分区未挂载、备份可恢复、Live 以 UEFI 启动,且笔记本接通电源。然后执行:

sudo btrfs-convert --progress "$ROOT_DEV"

等待命令完整结束并返回成功。不要在进度停顿时反复按 Ctrl+C,也不要在失败后直接重试;转换耗时可能从几分钟到数小时。

转换成功后,Btrfs 中会保留名为 ext2_saved 的原 ext4 元数据镜像。转换成功不代表可以立刻重启,要先验证文件并修正启动配置。

转换异常与回滚

出现错误时先保存终端输出,保持分区不变,不要运行 fsck.ext4mkfs.btrfs、balance 或压缩命令。

ext2_saved 仍然存在、且没有改变转换后 Btrfs 布局的操作时,官方提供了回滚方式:

sudo btrfs-convert --rollback "$ROOT_DEV"

回滚会丢弃转换后的 Btrfs 改动。特别要记住:准备回滚时不要执行 balance;官方文档明确指出,balance 会改变 extent 布局,使原地回滚不可用。如果错误状态不明确,不要猜测,优先保留现场并从独立备份恢复。

五、挂载并验证结果

sudo mkdir -p "$TARGET"
sudo mount "$ROOT_DEV" "$TARGET"
sudo mkdir -p "$TARGET/boot/efi"
sudo mount "$ESP_DEV" "$TARGET/boot/efi"
findmnt "$TARGET"
sudo btrfs filesystem show "$TARGET"
sudo btrfs filesystem usage "$TARGET"
sudo btrfs subvolume list "$TARGET"
sudo ls -la "$TARGET"
sudo ls -la "$TARGET/ext2_saved"

随机打开或校验几个重要文件,尤其是 /home 下的大文件和密钥文件。转换后的 Btrfs UUID 通常会与原 ext4 UUID 不同:

NEW_UUID=$(sudo blkid -s UUID -o value "$ROOT_DEV")
printf 'new Btrfs UUID=%s\n' "$NEW_UUID"
sudo blkid "$ROOT_DEV"

如果 blkid 没有输出,先不要修改 fstab,检查挂载和 btrfs filesystem show 的结果。

六、修改 Debian 的 fstab

先备份并编辑目标系统配置:

sudo cp -a "$TARGET/etc/fstab" "$TARGET/etc/fstab.before-btrfs"
sudoedit "$TARGET/etc/fstab"

当前根分区行类似:

UUID=b81fd5ad-9c5f-4b60-9ae1-d884ab37145d / ext4 errors=remount-ro 0 1

转换后改成下面的结构,把新 UUID 填入:

UUID=<NEW_BTRFS_UUID> / btrfs compress=zstd:3 0 0
UUID=D941-6C56 /boot/efi vfat umask=0077 0 0
UUID=d316d907-75d8-40b1-a747-1187b8ad8b35 none swap sw 0 0

要点是:根分区类型改为 btrfs;根 UUID 使用新值;Btrfs 根分区最后一列设为 0。当前 ext4 行的 errors=remount-ro 不要原样保留。 compress=zstd:3 是可选参数,也可以首次启动时先去掉,确认成功后再加入;它不会自动压缩转换前已经存在的数据。

如果 fstab 使用的是 PARTUUID,转换文件系统通常不会改变 GPT 分区表里的 PARTUUID,但仍要以实际检查为准。EFI 和 swap 的行不要无故改动。

七、chroot、initramfs 与 GRUB

把 Live 环境的设备、伪文件系统和运行时目录绑定到目标系统:

for dir in /dev /dev/pts /proc /sys /run; do
  sudo mount --rbind "$dir" "$TARGET$dir"
  sudo mount --make-rslave "$TARGET$dir"
done
sudo chroot "$TARGET" /bin/bash
export HOME=/root
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

当前目标系统没有 btrfs-progs,这一步不能省略:

apt-get update
apt-get install btrfs-progs
update-initramfs -u -k all

检查配置并重新生成 Debian 的 UEFI GRUB:

findmnt -no SOURCE,FSTYPE,UUID /
grep -nE 'root=|btrfs|ext4' /etc/fstab /boot/grub/grub.cfg 2>/dev/null
update-grub

当前环境使用 Debian 的 shimx64.efi。如果 EFI 文件或启动项本身需要修复,再执行:

grub-install \
  --target=x86_64-efi \
  --efi-directory=/boot/efi \
  --bootloader-id=debian \
  --recheck
update-grub

如果 grub-install 报告 EFI 变量不可用,先退出并确认 Live 是 UEFI 模式;不要在 Legacy 模式下盲目写引导器。启用 Secure Boot 时保留 Debian 的 shim-signed 和签名 GRUB。

退出并卸载:

exit
sudo umount -R "$TARGET"
sudo reboot

八、第一次启动后的验证

进入系统后,先不要删除 ext2_saved,也不要立即 balance:

findmnt -no SOURCE,FSTYPE,UUID,OPTIONS /
lsblk -f
df -hT /
sudo btrfs filesystem usage /
sudo btrfs subvolume list /
sudo btrfs device stats /

预期根分区的 FSTYPEbtrfs,根目录可读写,EFI 和 swap 正常。然后检查服务、桌面、网络、重要文件和常用软件。

建议做一次 scrub:

sudo btrfs scrub start -B /
sudo btrfs scrub status /
sudo btrfs device stats /

Scrub 会验证数据和元数据校验和;单磁盘 Btrfs 没有第二份副本,因此发现不可纠正错误时不能凭空恢复数据。如果出现 uncorrectablecsum 或 I/O 错误,停止大量写入,先复制还能读取的数据到独立磁盘。

至少经过几次正常重启、重要文件抽查、服务验证和一次成功 scrub 后,再考虑删除回滚镜像:

sudo btrfs subvolume delete /ext2_saved

删除后就不能再使用 btrfs-convert --rollback 回到 ext4,因此不要在刚启动成功时急着做。

九、整理、压缩、快照与维护

原地转换会继承 ext4 的数据布局,Btrfs 元数据块组可能比较碎。确认已经放弃回滚后才考虑整理;无过滤条件的 balance 会搬迁整个文件系统,耗时、耗 I/O,并需要额外工作空间。Btrfs balance 文档明确提醒 full balance 可能非常耗时。

可选的整理命令如下,首次启动不需要执行:

sudo btrfs filesystem defrag -v -r -f -t 32M /
sudo btrfs balance start -m /
sudo btrfs balance status /

compress=zstd:3 只影响之后写入的文件。如果已经完成备份、验证并删除 ext2_saved,可以只对特定目录压缩:

sudo btrfs filesystem defrag -v -r -f -czstd /home

对已经压缩的媒体、加密文件或数据库,收益可能很小;对含有快照的目录执行 defrag 也可能改变共享 extent,应该先理解子卷布局。

Btrfs 快照适合应对误删和错误更新,但同一块物理磁盘损坏时快照也会一起丢失。快照不是独立备份,重要数据仍要复制到另一块设备或另一台机器。

可以手动定期 scrub:

sudo btrfs scrub start /
sudo btrfs scrub status /
systemctl list-unit-files 'btrfs-scrub@*.timer'
sudo systemctl enable --now btrfs-scrub@-.timer

最后一条只有在前一条确实列出对应 unit 时才执行;不同发行版的 unit 名称和默认周期可能不同。

十、常见失败场景

空间不足或转换失败

不要直接删除数据、缩小分区或重试。先记录错误,确认是否仍可回滚;如果转换已经开始,不能把它当作普通命令失败。分区缩放是另一项高风险操作,必须先有独立备份并阅读针对该错误的官方说明。

能进 GRUB,但找不到根文件系统

从 Live 启动并挂载目标,检查新 UUID 是否写入 fstab

sudo mount "$ROOT_DEV" "$TARGET"
sudo grep -n ' / ' "$TARGET/etc/fstab"
sudo blkid "$ROOT_DEV"

多数情况是仍使用旧 ext4 UUID,或 initramfs/GRUB 没重建。修正后按本文 chroot 步骤重新执行 update-initramfs -u -k allupdate-grub

Btrfs 出现校验错误

先停止 balance、压缩和大量写入:

sudo btrfs scrub start -B /
sudo btrfs scrub status /
sudo btrfs device stats /
dmesg -T | grep -iE 'btrfs|I/O error|checksum|csum' | tail -n 80

单盘没有冗余副本时,scrub 只能报告问题,不能保证修复。优先复制仍可读取的重要数据并检查 SSD 健康状态;不要直接使用 btrfs check --repair

系统能启动,但回滚不了

常见原因是已经删除 ext2_saved,或者执行了 balance 改变 extent 布局。回滚能力只是临时安全网,不是完整备份;真正的数据安全来自独立、可验证的备份。

最后的执行清单

这次迁移真正改变的不是一条命令,而是系统的故障模型:Btrfs 提供校验、快照、子卷和透明压缩,但不会替你创建第二份数据。只有把 Live 救援环境、可验证备份、可回滚窗口和启动配置一起准备好,ext4 到 Btrfs 的转换才是一次可管理的迁移,而不是一次碰运气的重启。

参考资料

Editar este post
Siguiente
中文博客写作示例:一篇覆盖常用格式的模板