了解和使用 Linux 中的 BtrFS 文件系统
这篇博文旨在帮助您开始使用B 树文件系统 (BtrFS)。 Linux 内核树中基于内核的文件系统目前超过 55 个,每个文件系统都有其优点和缺点。在这里,我们将广泛介绍如何在 Linux 中管理 BtrFS 文件系统。
一些文件系统的用途有限或非常具体,被认为真正通用的文件系统是 extN 系统,如 ext2、ext3、ext4 – 它们稳定且功能强大,但仍然有一定的局限性。
B-tree 文件系统 (BtrFS) 发音为Better FS,现在已经在 Linux 中取得了相当长的一段时间。截至撰写本文时,稳定的可用版本是 4.9。现在让我们了解 Linux 管理中 BtrFS 文件系统的基础知识。
什么是 BtrFS?
BtrFS 是下一代通用 Linux 文件系统,提供先进的集成设备管理、可扩展性和可靠性等独特功能。 BtrFS 可扩展到 16 艾字节 (EB),并专注于其他 Linux 文件系统所没有的功能,有些人甚至认为 Btrfs 是 Sun/Oracle ZFS 的 Linux 版本,但其架构比 Sun/Oracle ZFS 更具可扩展性ZFS。事实上,Linux 中的 BtrFS 文件系统目前受到了极大的关注。
BtrFS 为 Ceph 分布式文件系统及其“云”技术的 RADOS 对象存储层奠定了基础。它包含来自 ext4、XFS、HP aufs 和 Reiser 文件系统的思想。 BtrFS 的开发非常活跃,新功能正在以惊人的速度添加。
为什么选择 BtrFS
Linux 中的 BtrFS 文件系统提供以下特性和功能
- 内置写入时复制
- 强大的快照功能
- 带有子卷的内置卷管理
- 高达16 艾字节的大规模可扩展性
- 内置数据完整性(校验和)
- SSD优化
- 压缩能力
- 云就绪
- BtrFS 内置 RAID
- 手动碎片整理
- 在线文件系统管理
- 数据和元数据完整性
- 从 ext2/3/4 和 ReiserFS 就地转换
- 配额组
- 在线扩展和减少文件系统大小
- 对象级 RAID
- 播种装置
- 支持多种设备
Btrfs 规格
- 最大卷大小:16 EB(2^64 字节)
- 最大文件大小:16 EB
- 最大文件名大小:255 字节
- 文件系统检查:在线和离线
- 目录查找算法:B-Tree
- 文件名中的字符:任意,除了 0x00
兼容性
- 硬链接和符号链接
- 访问控制列表 (ACL)
- 扩展属性 (xattrs)
- POSIX 文件所有者/权限
- 异步和直接 I/O
- 稀疏文件
BtrFS 真正支持最大文件大小为 16 Exabytes。如果“艾字节”这个术语让您有点困惑,请参考下图,它可以帮助您直观地了解这一点。
要检查您的内核当前支持哪些文件系统,您可以在文件 /proc/filesystems 中找到。下面显示了我的本地系统的示例。
# cat /proc/filesystems
nodev sysfs
nodev rootfs
..............
btrfs
ext3
ext2
ext4
vfat
xfs
fuseblk
nodev fuse
nodev fusectl
对于BtrFS支持,输出应包含关键字btrfs。
在 Linux 发行版上安装 BtrFS
在基于 Debian 的系统上:
sudo apt update
sudo apt -y install btrfs-progs
基于 RHEL 的系统:
sudo yum -y install btrfs-progs
架构Linux
sudo pacman -S btrfs-progs
根图
sudo emerge --ask sys-fs/btrfs-progs
BtrFS 有用的挂载选项
有关可用选项的更多详细信息,请阅读 btrfs 手册页
$ man 5 btrfs
使用 BtrFS – 使用示例
我的实验室机器当前有两个辅助硬盘驱动器,每个硬盘驱动器由 1 GB
组成,用于稍后的演示。为了顺利进行,您可以启动虚拟机,安装 btrfs-progs 软件包并添加两个辅助硬盘驱动器。
创建并挂载 BtrFS 分区
为了开始演示,我们首先在单个 1 GB
分区上创建 BtrFS 文件系统,并将其挂载到 /data
目录。我们将在 /dev/vdb
上创建一个分区,覆盖块设备的 30%
。要制作基本的 BtrFS 文件系统并挂载它,请使用以下命令:
sudo parted --script /dev/vdb "mklabel gpt"
sudo parted --script /dev/vdb "mkpart primary 1 30%"
sudo parted /dev/vdb print
sudo mkdir /data
sudo mkfs.btrfs /dev/vdb1
sudo mount /dev/vdb1 /data
为了确认已安装的分区按照我们想要的方式工作,让我们将一些数据复制到其中,如下所示:
sudo find /usr/share/doc -name '*[a,b].html' -exec cp {} /data \;
ls -l /data
还可以使用 btrfs
命令检查文件系统:
btrfs filesystem show /dev/vdb1
btrfs filesystem df -h /data/
btrfs filesystem usage /data/
从这些命令中,您会看到我们复制了一些现有的 html 文件,为我们提供一些用于演示的真实数据。最后一个命令确认大小接近 300MB(1 GB 的 30%)
。
列出根卷的子卷
$ btrfs subvolume list /data/
查看磁盘空间利用率:
$ btrfs filesystem df -h /data
$ btrfs filesystem show /dev/vdb1
扩大 btrfs 文件系统
从之前对 dev/vdb
的分区来看,我们还有大约 700MB 未分区。我们将用它来扩大 btrfs 文件系统。
sudo parted /dev/vdb mkpart primary 30% 60%
sudo btrfs device add /dev/vdb2 /data/
btrfs filesystem show /data
df -h /data/
删除 btrfs 设备
使用btrfs device delete
命令删除在线设备。它将把正在使用的任何盘区重新分配到文件系统中的其他设备,以便安全地删除。
例子 :
sudo btrfs device delete /dev/vdb2 /data
这就是我们扩展 BtrFS 文件系统所需要做的全部工作。这从下面所示的输出中得到了证实:
扩展 BtrFS 文件系统
您还可以通过指定预期大小直接调整大小,语法为:
sudo btrfs filesystem resize amount /mount-point
该数量可以是设定的大小,例如“+3g”表示增加3 GiB,也可以是“max”以增加文件系统以填满整个块设备。使用“-3g”减少 3 GiB。请考虑下面的示例,将新分区 /dev/sda4
添加到 /home
并对其进行扩展。
$ sudo btrfs device add /dev/sda4 /home -f
$ sudo btrfs filesystem resize max /home
$ sudo btrfs filesystem show /home
Label: 'home' uuid: b40ffd9b-c09d-403e-a5f3-b79b5c314505
Total devices 2 FS bytes used 79.71GiB
devid 1 size 88.81GiB used 88.81GiB path /dev/mapper/arch-home
devid 2 size 8.89GiB used 1.00GiB path /dev/sda4
请注意,新设备已成功添加。
平衡文件系统
如果原始卷中的磁盘空间不足,我们可以添加额外的分区。这些设备上的元数据和数据仍然仅存储在 /dev/vdb1 上。现在必须使用以下命令平衡它以分布在所有分区上:
$ sudo btrfs balance start -d -m /data
论据:
-d:代表数据
-m:代表元数据
这将确保磁盘得到同等使用。
测试:
是时候在 Linux 中对 BtrFS 文件系统进行一些测试了。为了测试平衡是否有效,我将生成两个大小分别为 100MB 的随机数据。
sudo dd if=/dev/urandom of=/data/hugefile1 bs=1M count=100
sudo dd if=/dev/urandom of=/data/hugefile2 bs=1M count=100
sudo btrfs balance start -d -m /data
sudo btrfs filesystem show /data
您应该注意到,两卷中的数据非常平衡。
如果您希望在启动时安装 /data
目录,请将以下条目附加到 /etc/fstab
文件中:
/dev/vdb1 /data btrfs device=/dev/vdb1,device=/dev/vdb2 0 0
多设备文件系统创建
使用 Linux 中的 BtrFS 文件系统。可以进行多设备管理。这将 -d 和 -m 选项与 mkfs.btrfs 命令结合使用。有效规格为:
- 单身的
- raid0:无冗余的条带化
- raid1:磁盘镜像
- raid10:条纹镜子
-m 单个选项指示不重复元数据。使用硬件 raid 时可能需要这样做。
要将新设备添加到已创建的多设备文件系统,请使用:
sudo mkfs.btrfs /dev/device1 /dev/device2 /dev/device3
sudo mount /dev/device3 /mount-point
重新加载 btrfs 模块然后运行:
sudo btrfs device scan
发现所有多设备文件系统。
让我们考虑下面的示例来创建 raid10
和 raid1
btrfs 文件系统。请注意,raid 10 至少需要四个设备才能正常运行。
具有元数据镜像、数据条带化的四个设备
sudo mkfs.btrfs /dev/device1 /dev/device2 /dev/device3 /dev/device4
两个设备,元数据条带化但无镜像
sudo mkfs.btrfs -m raid0 /dev/device1 /dev/device2
raid10
用于数据和元数据
sudo mkfs.btrfs -m raid10 -d raid10 /dev/device1 /dev/device2 /dev/device3 /dev/device4
当驱动器大小不同时,每个设备使用的全部容量:
sudo mkfs.btrfs /dev/device1 /dev/device2 /dev/device3
sudo mount /dev/device1 /mount-point
不要在单个驱动器上复制元数据。
sudo mkfs.btrfs -m single /dev/device
BtrFS 设备扫描
扫描 /dev 下的所有块设备并使用以下命令探测 BtrFS 卷:
sudo btrfs device scan
sudo btrfs device scan /dev/device
创建 BtrFS 子卷
子卷允许 BtrFS 文件系统内的离散管理身份。在本部分中,我们将创建两个子卷:subvolume1 和 subvolume2。为此,我们首先在 /dev/vdb3 设备上创建一个新的 BtrFS,创建一个挂载点并挂载它:
sudo parted /dev/vdb mkpart primary 60% 100%
sudo mkfs.btrfs /dev/vdb3
sudo mkdir /subvol_btrfs
sudo mount /dev/vdb3 /subvol_btrfs
现在让我们在 /subvol_btrfs 上创建两个子卷。
sudo btrfs subvolume create /subvol_btrfs/subvolume1
sudo btrfs subvolume create /subvol_btrfs/subvolume2
当我们定义子卷时,目录和 BtrFS 子卷实体都将在文件系统中创建。
在 /subvol_btrfs
和子卷中创建一些文件:
sudo touch /subvol_btrfs/btrfsmainfile.txt
sudo touch /subvol_btrfs/subvolume1/subvolume1file.txt
sudo touch /subvol_btrfs/subvolume2/subvolume2file.txt
列出 /subvol_btrfs
中当前可用的子卷:
$ sudo btrfs subvolume list /subvol_btrfs
ID 256 gen 9 top level 5 path subvolume1
ID 257 gen 9 top level 5 path subvolume2
sudo umount /subvol_btrfs
安装子卷
您可以将子卷安装到安装点。让我们这样做并使用 ls -l 命令比较结果:
$ sudo mount /dev/vdb3 /subvol_btrfs/
$ ls -l /subvol_btrfs/
$ sudo umount /subvol_btrfs/
$ sudo mount -o subvol=subvolume1 /dev/vdb3 /subvol_btrfs/
$ ls -l /subvol_btrfs/
$ sudo mount -o subvol=subvolume2 /dev/vdb3 /subvol_btrfs/
$ ls -l /subvol_btrfs/
使子卷成为默认子卷而不是当前根卷:
让我们将 subvolume1
设置为默认子卷。我们需要的是它的 ID:
$ sudo umount /subvol_btrfs/ 2>/dev/null
$ sudo mount /dev/vdb3 /subvol_btrfs/
$ ID=`btrfs subvolume list /subvol_btrfs/ | grep subvolume1 | awk '{print $2}'`
$ btrfs subvolume set-default ${ID} /subvol_btrfs
通过重新挂载 /dev/vdb3
进行测试:
$ sudoumount /subvol_btrfs/
$ sudo mount /dev/vdb3 /subvol_btrfs/
$ ls -l /subvol_btrfs/
total 0
-rw-r--r--. 1 root root 0 Jan 10 11:22 subvolume1file.txt
从上面的输出中请注意,我们在 subvolume1
上创建的数据是挂载 /dev/vdb3
时默认可用的数据。
要将默认值设置回根卷,请使用 ID 0 或 5:
$ sudo btrfs subvolume set-default 0 /subvol_btrfs
$ sudo umount /subvol_btrfs
$ sudo mount /dev/vdb3 /subvol_btrfs/
$ ls -l /subvol_btrfs/
total 0
-rw-r--r--. 1 root root 0 Jan 10 11:22 btrfsmainfile.txt
drwxr-xr-x. 1 root root 36 Jan 10 11:22 subvolume1
drwxr-xr-x. 1 root root 36 Jan 10 11:22 subvolume2
使用 BtrFS 快照
Linux 快照功能中的 BtrFS 文件系统可用作数据的只读或读/写副本。可以通过以下方式使用快照:
1.
创建只读快照,然后执行快照备份。这样,备份将是创建快照的时间点的主机文件系统。
2.
在修改许多文件时使用它作为还原点。如果修改导致负面结果,您可以轻松恢复到快照副本。
快照必须在与目标数据相同的文件系统上创建,因为快照的快速创建受到文件系统内某种形式的内部链接的影响。
注意:您无法创建整个文件系统的快照。这是因为对快照的更改需要写回到其自身,从而导致无限递归。
为了演示的目的,我们将使用之前创建的两个子卷。我们的场景是创建工作子卷 subvoume1
的只读快照。
$ sudo btrfs subvolume snapshot -r /subvol_btrfs/subvolume1 /subvol_btrfs/subvolume2/backup/
Create a readonly snapshot of '/subvol_btrfs/subvolume1' in '/subvol_btrfs/subvolume2/backup'
我们可以使用以下命令列出可用的子卷:
$ sudo btrfs subvolume list /subvol_btrfs/
ID 256 gen 24 top level 5 path subvolume1
ID 257 gen 24 top level 5 path subvolume2
ID 258 gen 24 top level 257 path subvolume2/backup
从输出中,我们可以看到快照显示为新的子卷。列出两个目录的内容应该表明内容是相同的:
$ ls /subvol_btrfs/subvolume2/backup/
subvolume1file.txt
$ ls /subvol_btrfs/subvolume1/
subvolume1file.txt
如果我们删除 /subvol_btrfs/subvolume1/
中的所有文件,BtrFS 中的写时复制 (COW) 技术将在 /subvol_btrfs 中创建文件/subvolume2/备份
。如果发生灾难,我们可以简单地将文件复制回原始位置,因为即使原始文件发生更改,它们也不会被修改。
BtrFS 就地迁移;将 ext4 文件系统转换为 BtrFS
在此示例中,我将向您展示如何将 ext4 文件系统转换为 BtrFS。由于我在 KVM 上运行 CentOS 服务器,因此我将添加辅助硬盘,创建一个 ext4 分区,然后将其转换为 BtrFS,以便您可以全面了解它是如何完成的。
添加1GB
辅助块设备,这是在主机上完成的:
syudo virsh vol-create-as default --name btrfs-sec.qcow2 1G
sudo virsh vol-list --pool default
sudo virsh attach-disk --domain cs1 --source /var/lib/libvirt/images/btrfs-sec.qcow2 --persistent --target vdc
确认它已添加到虚拟机上:
$ lsblk /dev/vdc
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vdc 252:32 0 1G 0 disk
创建ext4分区:
sudo parted --script /dev/vdc "mklabel gpt mkpart primary 0% 100%"
sudo parted --script /dev/vdc print
sudo lsblk -f /dev/vdc
挂载新创建的文件系统,创建一些文件和目录,然后卸载文件系统:
sudo mkdir /ext4tobtrfs
sudo mount /dev/vdc1 /ext4tobtrfs/
sudo mkdir /ext4tobtrfs/test-{1-4}-dir
sudo touch /ext4tobtrfs/test-file{1..10}.txt
sudo ls -l /ext4tobtrfs/
sudo umount /ext4tobtrfs/
将文件系统转换为 Btrfs:
# btrfs-convert -l convertedfs /dev/vdc1
create btrfs filesystem:
blocksize: 4096
nodesize: 16384
features: extref, skinny-metadata (default)
creating btrfs metadata.
copy inodes [o] [ 0/ 22]
creating ext2 image file.
set label to 'convertedfs'
cleaning up system chunk.
conversion complete.
再次挂载文件系统并查看文件系统类型:
# mount /dev/vdc1 /ext4tobtrfs/
# df -hT /ext4tobtrfs/
Filesystem Type Size Used Avail Use% Mounted on
/dev/vdc1 btrfs 1022M 51M 643M 8% /ext4tobtrfs
请注意,/ext4tobtrfs
的文件系统是 btrfs 类型。
要查看子卷、BtrFS 信息和内容,请使用:
# btrfs filesystem show /ext4tobtrfs/
Label: 'convertedfs' uuid: 3e985770-66a0-4b85-810e-2e93182696f3
Total devices 1 FS bytes used 34.78MiB
devid 1 size 1022.00MiB used 616.25MiB path /dev/vdc1
# btrfs subvolume list /ext4tobtrfs/
ID 256 gen 6 top level 5 path ext2_saved
# ls -l /ext4tobtrfs/
total 16
drwxr-xr-x. 1 root root 10 Jan 10 13:22 ext2_saved
drwx------. 1 root root 0 Jan 10 13:14 lost+found
drwxr-xr-x. 1 root root 0 Jan 10 13:19 test-{1-4}-dir
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file10.txt
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file1.txt
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file2.txt
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file3.txt
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file4.txt
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file5.txt
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file6.txt
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file7.txt
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file8.txt
-rw-r--r--. 1 root root 0 Jan 10 13:19 test-file9.txt
# file /ext4tobtrfs/ext2_saved/image
/ext4tobtrfs/ext2_saved/image: Linux rev 1.0 ext4 filesystem data, UUID=7e6849f2-8560-4b9d-add8-d344ef577650 (extents) (64bit) (large files) (huge files)
> To mount subvolume or the image in ext2_saved subvolume, use:
# mount -o subvol=ext2_saved /dev/vdc1 /mnt/
# ls -l /mnt
# umount /mnt
# mount -o loop /ext4tobtrfs/ext2_saved/image /mnt/
# ls -la /mnt/
回滚到 ext4 文件系统:
# umount /ext4tobtrfs/
# btrfs-convert -r /dev/vdc1
rollback complete.
# mount /dev/vdc1 /ext4tobtrfs/
# df -hT /ext4tobtrfs/
Filesystem Type Size Used Avail Use% Mounted on
/dev/vdc1 ext4 990M 2.6M 921M 1% /ext4tobtrfs
如果您查看 /ext4tobtrfs/ 中的文件,您会注意到您在 BtrFS 上创建的目录已经消失,只有最初在 ext4 文件系统上创建的目录还在。
转换现有的单一设备系统
将现有的单设备系统(本例中为 /dev/vdb1
)转换为双设备 raid1
系统,以防止单磁盘故障,请使用以下命令:
# umount /subvol_btrfs/
# mount /dev/vdb1 /subvol_btrfs/
# btrfs device add /dev/vdb2 /subvol_btrfs/ -f
# btrfs balance start -dconvert=raid1 -mconvert=raid1 /subvol_btrfs/
BtrFS 维护任务
Linux 中的 BtrFS 文件系统始终需要管理员了解如何执行以下维护任务。
1.
使用scrub 验证校验和:
打开终端窗口并运行:
# watch btrfs scrub status /subvol_btrfs/
打开另一个终端窗口并运行:
# btrfs scrub start /subvol_btrfs/
第一个提示时的watch
将显示清理进度。
2.
手表余额:
在一个终端上运行:
# watch btrfs balance status /subvol_btrfs/
在另一个终端上,运行:
# btrfs balance start /subvol_btrfs/
3.
递归地对文件系统进行碎片整理,
# btrfs filesystem defragment -r /subvol_btrfs/
替换 btrfs 文件系统上的故障设备
如果设备丢失或超级块损坏,则在排除故障之前需要以降级模式挂载文件系统。示例如下所示:
# mkfs.btrfs -m raid1 /dev/vdb /dev/vdc /dev/vdd
# mount -o degraded /dev/vdb /mnt
# btrfs device delete missing /mnt
结论
在本有关 Linux 中的 BtrFS 文件系统的指南中,我全面介绍了 Linux 中的 BtrFS 文件系统,从基础知识开始到实际配置。 BtrFS 确实是现在就开始使用的东西,因为它将成为未来几年的默认企业文件系统。我们了解了 Linux 中的 BtrFS 文件系统如何通过将文件系统和卷管理捆绑在单任务工作模型中来简化两者。希望您与 BtrFS 合作愉快。
参考
1.
手册页 btrfs(8)
是一个很好的起点。它涵盖了所有重要的管理命令,其中包括:
- 子卷和快照管理
- 使用
scrub、balance和defragment
命令 - 使用
manage
命令管理文件系统 - 用于管理设备的
device
命令。
其他手册页包括:
要了解有关 Linux 管理中的 BtrFS 文件系统的更多信息,请参阅以下手册页。
# man mkfs.btrfs
# man 5 btrfs
# man 8 fsck.btrfs