这个被誉为“下一代文件系统”的神器,你得来看看!

Btrfs 是一种支持写入时复制 COW 的文件系统,具有很好的扩展性、可靠性和易管理性,被 Linux 基金会前 CTO、Ext4 文件系统主要维护者 Theodore Ts'o 誉为下一代文件系统。由于 Btrfs 基于 BTree 和 COW 的实现特性,开发者可实现各种强大的功能,如子卷、快照、RAID 等。

本文由 deepin(深度)社区用户 Ziggy 撰写,详细讲解了如何将系统正确安装到 Btrfs 子卷,并创建一个恢复环境。

前期准备

安装准备

1、准备一个系统安装镜像并刻录到移动存储设备,最好是 5.10+ 内核,对 Btrfs 支持会更好。

2、提前分两个区:

  • 一个 Btrfs 分区作为母卷 rootfs;
  • 一个可以作为完整系统运行的 live 盘;
  • 一个独立分区用于安装初始系统,可以安装到 Btrfs 分区以外的独立硬盘中,当 Btrfs 所在硬盘损坏时可以作为 Rootb 备份进行还原。建议使用非 Btrfs 格式用于区分。

Btrfs分区划分子卷

1、将 Btrfs 分区挂载到 /mnt 中,开始创建所需的子卷。

ziggy@ziggy-PC:~$ lsblk -f
NAME   FSTYPE FSVER LABEL     UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
sdb                                                     
├─sdb1 vfat   FAT32           DCF5-3A2C                                           /boot/efi
├─sdb2 swap   1     swap      e2a198a1-6e12-4248-bca8-b5cfbf4ce723                [SWAP]
├─sdb3 btrfs        deepin    68e253cf-9282-47b3-b087-9c5910950c88   89.9G    32% /

根据 lsblk 得出 Btrfs 分区为 /dev/sdb3,挂载:

root@ziggy-PC:~# mount /dev/sdb3 /mnt/

当 Btrfs 分区被挂载到 /mnt 后,此时 /mnt 为 Btrfs 母卷,本身不具备任何子卷功能。并且 Btrfs 目前仍处于发展阶段,以及取决于 Btrfs+GRUB 引导顺序,建议在系统子卷以外单独设置一个根子卷充当引导中转的作用。

以下示例依次设置子卷"@main(Btrfs根),@home(用户主目录),@opt(应用目录),@root(root主目录,可选)"。

root@ziggy-PC:/mnt# btrfs subvolume create /mnt/@main
root@ziggy-PC:/mnt# btrfs subvolume create /mnt/@home
root@ziggy-PC:/mnt# btrfs subvolume create /mnt/@opt
root@ziggy-PC:/mnt# btrfs subvolume create /mnt/@root

系统部署

初始系统安装

引导进入安装介质,选择非 Btrfs 格式的卷作为"/"挂载点进行安装,安装时尽量选择仅"/"挂载点进行安装,方便后续进行数据迁移,建议的挂载方案:"/"根目录(必须),交换文件 swap files(可选),EFI(如果是 UEFI 引导的话)。

乾坤大挪移

由于众所周知的两个原因,在安装完初始系统后,如果想要让系统正常在 Btrfs 卷上运行并使能快照功能,就需要手动将已经安装好的系统迁移到 Btrfs 子卷中。

  • 目前安装器暂不支持直接将系统安装到 Btrfs 子卷中;
  • deepin 安装器目前策略导致安装完系统但并未进入用户配置阶段时,此时的系统拥有相对最干净的环境;
  • 通过查看 lsblk,记录 /dev/sda1 为初始系统的安装目录,/dev/sdb3/@main 则为 Btrfs 分区中的根卷。
sda                                                     
├─sda1 ext4   1.0   Roota     a7f4b3d4-5d3d-45a1-a27b-798aa6fbae48   30.7G    26% /media/ziggy/Roota
sdb                                                     
├─sdb1 vfat   FAT32           DCF5-3A2C                                           /boot/efi
├─sdb2 swap   1     swap      e2a198a1-6e12-4248-bca8-b5cfbf4ce723                [SWAP]
├─sdb3 btrfs        deepin    68e253cf-9282-47b3-b087-9c5910950c88   89.9G    32% /mnt

确认后通过 rsync 来进行数据迁移,由于本示例中还单独划分了"@home,@opt,@root",因此还需要将初始系统中对应目录的数据迁移到子卷中。

root@ziggy-PC:/mnt# rsync -avrP /media/ziggy/Roota /mnt/@main
root@ziggy-PC:/mnt# rsync -avrP /media/ziggy/Roota/opt /mnt/@opt
root@ziggy-PC:/mnt# rsync -avrP /media/ziggy/Roota/home /mnt/@home
root@ziggy-PC:/mnt# rsync -avrP /media/ziggy/Roota/root /mnt/@root

文件配置

数据迁移完成后,由于 Btrfs 卷与系统原安装路径不一致以及系统安装到 Btrfs 子卷后的引导顺序,需要对数个配置文件进行重新配置:

"Firmware固件==>efi引导文件==>Grub==>Btrfs母卷==>Btrfs子卷Grub==>Btrfs子卷rootfs"

/boot目录

/boot 目录中需要对 grub.cfg 引导文件进行修改,这里可以分为几步:

1、通过搜索将初始系统的 UUID 批量替换为 Btrfs 母卷的 UUID。

这个被誉为“下一代文件系统”的神器,你得来看看!

2、观察 grub.cfg 文件中对系统绝对路径的引用,在"/"前加上"/@main",表明该路径修改后为子卷中的路径。

这个被誉为“下一代文件系统”的神器,你得来看看!

在 Linux 行内核启动参数中添加"rootflags=subvol=@main"指示 GRUB 引导 Btrfs 母卷中的@main子卷。

linux   /@main/boot/vmlinuz-6.1.32-amd64-desktop-hwe root=UUID=68e253cf-9282-47b3-b087-9c5910950c88 ro splash quiet rootflags=subvol=@main DEEPIN_GFXMODE=$DEEPIN_GFXMODE
initrd  /@main/boot/initrd.img-6.1.32-amd64-desktop-hwe

/etc目录

1、修改 fstab 文件,根据实际的子卷和需求情况来修改挂载信息,此处核心的为根目录挂载点设置,其他挂载点可以参考根目录挂载点来进行修改,仅需修改 subvol 指向子卷。

# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# /dev/sdb1 LABEL=Roota
UUID=68e253cf-9282-47b3-b087-9c5910950c88       /       
 btrfs           rw,relatime,ssd,compress=zstd,subvol=@main     0 1
UUID=68e253cf-9282-47b3-b087-9c5910950c88       /home           btrfs           rw,relatime,ssd,subvol=@home 0 1
UUID=68e253cf-9282-47b3-b087-9c5910950c88       /opt            btrfs           rw,relatime,ssd,subvol=@opt  0 1

2、修改 /etc/default/grub文件,在"GRUB_CMDLINE_LINUX_DEFAULT"字段中添加“rootflags=subvol=@main”,这样在 GRUB update 后才会自动在新的 GRUB 文件中自动添加该启动命令。

root@ziggy-PC:/boot/grub# cat /etc/default/grub
#
Written by org.deepin.dde.Grub2
GRUB_CMDLINE_LINUX_DEFAULT="splash quiet rootflags=subvol=@main"

EFI目录(如果是UEFI引导的话)

1、通过 lsblk 查看得知/ boot/efi 挂载点所在分区的 UUID 并挂载到 /mnt 中。

r
oot@zigg
y-PC:/boot/grub#mount /dev/sdb1 /mnt

2、进入 /mnt 目录,找到 boot 和 deepin 目录,修改 grub.cfg 文件.将"search.fs_uuid"修改为 Btrfs 母卷对应的 UUID 信息,"set prefix"中加入子卷对应的路径。

root@ziggy-PC:/boot/efi/EFI/deepin# cat grub.cfg 
search.fs_uuid 68e253cf-9282-47b3-b087-9c5910950c88 root hd0,gpt2
set prefix=($root)'/@main/boot/grub'
configfile $prefix/grub.cfg

快照部署

由于前文提及@main子卷用于根卷不打算作为常用系统子卷使用,因此在该基础上创建一个@sys快照子卷来作为日用环境。

root@ziggy-PC:/# btrfs subvolume snapshot /mnt/@main /mnt/@sys

快照创建完成后,由于子卷发生改变,因此需要重复"### 文件配置"步骤来调整新子卷的内容,但通用文件不需要改动。

/boot目录

修改@sys子卷中的grub.cfg文件,在Linux行内核启动参数中添加"rootflags=subvol=@sys"指示 GRUB 引导 Btrfs 母卷中的@sys子卷,并且该引导项中的 initrd 和 Linux 路径均需要修改为当前系统@sys子卷。

/etc目录

1、修改@sys子卷中的 fstab 文件,根据实际的子卷和需求情况来修改挂载信息,此处核心的为根目录挂载点设置,其他挂载点可以参考根目录挂载点来进行修改,仅需修改 subvol 指向子卷。

2、修改@sys子卷中的/etc/default/grub文件,在"GRUB_CMDLINE_LINUX_DEFAULT"字段中添加"rootflags=subvol=@sys",这样在 GRUB update 后才会自动在新的 GRUB 文件中自动添加该启动命令。

初始化部署

由于“初始化”环境本质上还是以快照子卷的形式存在,因此仅需要参考前面快照部署内容即可完成部署。即对@sys子卷做只读快照操作为同 Btrfs 母卷下的"@snaps/@restore子卷"(支持个人习惯的自定义)以及修改 /etc 对应文件即可完成 .snapshots 的"-r" 参数为只读快照。

root@ziggy-PC:/# btrfs subvolume snapshot -r /mnt/@sys /mnt/@snaps/@restore

由于通过安装器安装的系统一般还会附属“高级菜单”,个人建议直接利用高级菜单,将其描述修改为 Restore,initrd 和 Linux 路径修改为自己的初始化环境子卷。这样就可以在选 Restore 菜单引导时进入初始化环境了。

但值得注意的是,建议恢复时是以快照的形式先将"@restore子卷"恢复到一个新子卷中再进行用户配置环节操作,这样就可以极大程度避免初始化环境被破坏了。

对了!deepin 论坛正在开展优质内容有奖征集活动,欢迎大家踊跃投稿,每月会对优质内容进行奖励。详细内容请点击: https://bbs.deepin.org/post/261927