Ubuntu 22.04下如何在同一BTRFS分区挂载两个顶级子卷(已将/home部署在该分区)
嘿,最近在Ubuntu 22.04上折腾BTRFS挂载的时候踩了个坑,折腾好一会儿才解决,正好分享给遇到同样问题的朋友。
先说说我的情况:我把一块36TB的RAID 6卷格式化成BTRFS,整个磁盘就是/dev/sda1,挂载成了/home分区。后来想在同一个分区上创建另一个顶级子卷@images存虚拟机镜像——原因有两个:一是系统里只有这个RAID卷空间够大,我的/boot和/都在256GB的SATADOM上;二是备份的时候想分开,不想备份/home时把占空间的虚拟机镜像也带上,而且我也不想提前分区(谁知道以后要加多少镜像呢)。
一开始我直接在fstab里加了两条挂载条目,同一个UUID分别对应/home和/var/lib/libvirt/images,指定不同子卷,结果系统启动直接挂了!后来才想明白问题:当系统先挂载@home到/home时,这个挂载点只能看到@home子卷的内容,之后再尝试挂载@images时,系统会在已经挂载的@home里找@images,自然找不到,就卡住了。
那怎么解决在同一个BTRFS分区上挂载多个顶级子卷的问题呢?有两种靠谱的方法:
方法一:使用子卷ID(subvolid)挂载
这种方法最直接,不用额外挂载整个卷,只要知道每个子卷的ID就行:
- 先通过安装介质启动,把整个BTRFS分区挂载到临时目录(比如
/media/ubuntu/btrfs-raid),然后执行命令查看所有子卷的ID:
btrfs subvolume list /media/ubuntu/btrfs-raid
输出会类似这样,每个子卷前面的数字就是ID:
ID 5 gen 142 top level 5 path @home ID 6 gen 145 top level 5 path @images
- 修改
/etc/fstab,把原来的subvol参数换成subvolid,比如:
UUID=4d0792cb-339f-4266-8cef-03afc51a3ce9 / ext4 errors=remount-ro 0 1 #ROOT DIRECTORY UUID=6462-E921 /boot/efi vfat umask=0077 0 1 # BOOT DIRECTORY UUID=7779a2d8-23e2-4c81-8db8-677f57a2bacc /home btrfs defaults,subvolid=5 0 2 #HOME DIRECTORY UUID=7779a2d8-23e2-4c81-8db8-677f57a2bacc /var/lib/libvirt/images btrfs defaults,subvolid=6 0 2 #IMAGES DIRECTORY
这样不管挂载顺序如何,系统都会直接通过ID定位到对应的顶级子卷,不会受之前挂载的子卷影响。
方法二:先挂载整个BTRFS卷到隐藏目录
这种方法更直观,先把整个卷挂载到一个不常用的隐藏目录,再从这里挂载各个子卷:
- 创建一个隐藏目录用来挂载整个BTRFS卷:
sudo mkdir /.btrfs-raid-root
- 修改
/etc/fstab,先添加整个卷的挂载条目(不要加subvol参数,这样挂载的是卷的根,能看到所有顶级子卷):
UUID=7779a2d8-23e2-4c81-8db8-677f57a2bacc /.btrfs-raid-root btrfs defaults 0 2
- 然后保持原来的/home和/images挂载条目不变(用
subvol指定子卷名):
UUID=7779a2d8-23e2-4c81-8db8-677f57a2bacc /home btrfs defaults,subvol=@home 0 2 #HOME DIRECTORY UUID=7779a2d8-23e2-4c81-8db8-677f57a2bacc /var/lib/libvirt/images btrfs defaults,subvol=@images 0 2 #IMAGES DIRECTORY
这样系统会先挂载整个卷到隐藏目录,之后挂载子卷时,就会从卷的根去找对应的子卷,不会再出错。
两种方法都能解决问题,我个人更倾向于用subvolid的方式,少一个额外的挂载点,更简洁。
备注:内容来源于stack exchange,提问作者P. Gupta




