字数 1438,阅读大约需 8 分钟
Btrfs 最有魔力的特性是 subvolume——一个文件系统里可以有多个"独立可挂载"的子树。本篇讲清创建、嵌套、独立挂载、扁平化、删除。
一、Subvolume 是什么?
Btrfs FS
├── subvolid=5(top-level,Btrfs 自动创建)
│ ├── subvolume: @ (id=256, 系统根)
│ │ ├── subvolume: @home (id=257)
│ │ └── subvolume: @var (id=258)
│ ├── subvolume: data (id=300)
│ └── subvolume: @snapshots (id=400)
subvolid=5 是 top-level subvolume(创建文件系统时自动生成),不能删除。
二、创建 subvolume
2.1 基本创建
# 创建
$ btrfs subvolume create /mnt/data
Create subvolume '/mnt/data'
# 看
$ btrfs subvolume list /mnt
ID 256 gen 8 top level 5 path data
2.2 嵌套 subvolume
# 在已有 subvolume 下创建
$ btrfs subvolume create /mnt/data/projects
Create subvolume '/mnt/data/projects'
# 看嵌套
$ btrfs subvolume list /mnt
ID 256 gen 8 top level 5 path data
ID 257 gen 8 top level 256 path data/projects
# ^^^^^^^ 父 subvolume ID
2.3 用 snapper 自动管理(推荐)
openSUSE 的 snapper 工具自动管理快照:
# 安装
$ zypper install snapper
# 创建 snapper 配置
$ snapper -c root create-config /
# 自动拍快照
$ snapper -c root create --description "before upgrade"
# 看快照
$ snapper -c root list
# | Type | Pre # | Date | User | Cleanup | Description | Userdata
---+--------+-------+--------------------------+------+---------+-----------------------+---------
0 | single | | | root | | current |
1 | single | | 2024-01-15 03:00:01 | root | | before upgrade |
三、查看 subvolume
3.1 列出所有
$ btrfs subvolume list /mnt
ID 256 gen 8 top level 5 path data
ID 257 gen 8 top level 5 path @home
ID 258 gen 8 top level 256 path data/projects
ID 300 gen 8 top level 5 path @snapshots
# 看快照
$ btrfs subvolume list -s /mnt
ID 350 gen 10 top level 257 path @home/2024-01-01
3.2 看特定 subvolume
$ btrfs subvolume show /mnt/data
Name: data
UUID: ...
Parent UUID: -
Received UUID: -
Creation time: 2024-01-15 03:00:01
Subvolume ID: 256
Generation: 8
Gen at creation: 8
Parent ID: 5
Top level ID: 5
Flags: -
Snapshot(s):
...
3.3 看父子关系
# 只看当前 subvolume
$ btrfs subvolume show /mnt/data/projects
Top level ID: 256
Parent ID: 256
# Parent ID = 256,说明父是 data
四、删除 subvolume
# 删除 subvolume
$ btrfs subvolume delete /mnt/data
Delete subvolume (no-commit): '/mnt/data'
# 看
$ btrfs subvolume list /mnt
# data 消失
重要:
- • 删除后,该 subvolume 及其快照立即释放空间(但被引用的 extent 不会马上回收,会被 balance 时清理)
五、独立挂载 subvolume
这是 Btrfs 的"魔法"——subvolume 可以独立挂载到不同挂载点。
5.1 标准用法
# 取消现有挂载
$ umount /mnt
# 单独挂载 data 子卷
$ mkdir -p /data
$ mount -o subvol=data /dev/sdb /data
# 单独挂载 @home
$ mkdir -p /home
$ mount -o subvol=@home /dev/sdb /home
# 两个挂载点互不干扰
$ ls /data
file1.txt
$ ls /home
user/ readme.txt
5.2 用 subvolid 挂载
更稳定(path 可能改,id 不会):
$ mount -o subvolid=256 /dev/sdb /data
5.3 挂载整个文件系统(top-level)
# 不指定 subvol,挂载 top-level
$ mount /dev/sdb /mnt
# 所有 subvolume 都能在 /mnt 下看到
5.4 fstab 持久化
# /etc/fstab
UUID=a1b2c3d4... / btrfs subvolid=5,defaults 0 0
UUID=a1b2c3d4... /home btrfs subvol=@home,compress=zstd 0 0
UUID=a1b2c3d4... /data btrfs subvol=data,compress=zstd 0 0
关键点:
- • 每个挂载点看到的是对应 subvolume 的内容
六、嵌套 vs 扁平化
6.1 嵌套
Btrfs FS
├── @home
│ └── alice/ (子目录)
└── snapshots/
└── @home@2024-01-01 (快照)
默认是嵌套:快照放在 snapshots 目录里。
6.2 扁平化
某些发行版(SUSE)喜欢扁平结构:
Btrfs FS
├── subvolid=5(top-level)
│ ├── @ (系统根)
│ ├── @home
│ ├── @snapshots
│ │ ├── @home/2024-01-01 ← 但这是 subvolume 里的子目录
│ │ ├── @home/2024-01-15
│ │ └── ...
通过 SUSE 的 snapper 配置实现。
6.3 实际影响
两种结构都可以,扁平更清晰,嵌套更简单。
七、Subvolume ID 管理
# 看 subvolume ID
$ btrfs subvolume list /mnt
ID 256 gen 8 top level 5 path data
# 用 ID 查路径
$ btrfs subvolume find-new 256 /mnt # 查 generation 256 后变更
# 改 ID(不能直接改,但可以创建新 + send/recv)
八、Quotas(qgroup)
8.1 启用配额
# 启用 quota
$ btrfs quota enable /mnt
# 看 quota 状态
$ btrfs quota show /mnt
# 还没有 qgroup
8.2 创建 qgroup
# qgroup 0/<subvolid> 是给 top-level 的
# 0/<id> 是给特定 subvolume 的
# 例:限制 data 子卷 5G
$ btrfs qgroup limit 5G /mnt/data
# 例:限制 home 5G
$ btrfs qgroup limit 5G /mnt/home
# 看所有 qgroup
$ btrfs qgroup show -reF /mnt
qgroupid rfer excl max_rfer max_excl
-------- ---- ---- --------- --------
0/5 16KiB 16KiB none none
0/256 1.5GiB 1.5GiB 5.00GiB 5.00GiB
0/257 800MiB 800MiB 5.00GiB 5.00GiB
8.3 qgroup 字段说明
8.4 qgroup 失效问题
Btrfs 的 qgroup 有已知的性能问题(Linux 5.10 之前),subvolume 多时性能断崖式下降。
最佳实践:
九、subvolume 与 send/recv 配合
# 1. 创建快照
$ btrfs subvolume snapshot -r /mnt/data /mnt/snapshots/data@base
# 2. 发送到远程
$ btrfs send /mnt/snapshots/data@base | ssh remote btrfs receive /backup
# 3. 增量
$ btrfs subvolume snapshot -r /mnt/data /mnt/snapshots/data@v2
$ btrfs send -p /mnt/snapshots/data@base /mnt/snapshots/data@v2 | ssh remote btrfs receive /backup
十、典型 subvolume 布局
openSUSE 推荐布局
/ (subvol @)
/home (subvol @home)
/opt (subvol @opt)
/srv (subvol @srv)
/var (subvol @var)
.snapshots (subvol @snapshots, 不可变快照)
通用服务器
/data (subvol data, 业务数据)
/backup (subvol backup, 备份)
/logs (subvol logs, 日志)
个人/家用
/ (subvol @)
/home (subvol @home)
media (subvol media, 媒体文件)
backup (subvol backup)
十一、本篇小结
| |
|---|
| btrfs subvolume create /mnt/data |
| btrfs subvolume list /mnt |
| btrfs subvolume show /mnt/data |
| btrfs subvolume delete /mnt/data |
| mount -o subvol=data /dev/sdX /data |
| subvol=path |
关键概念:
- • qgroup 有性能陷阱,Linux 5.10 前慎用
- • snapper 自动管理是 openSUSE 风格