Btrfs 是一个用于 Linux 的开源通用文件系统。
该名称源自使用 B 树来存储内部文件系统结构。
文件系统使用了不同的名称,包括“Butter F S”和“B-tree F S”。
Btrfs 的开发始于 2007 年的 Oracle,现在许多(包括 Red Hat、Fujitsu、Intel、SUSE 和许多其他)都在为开发工作做出贡献。
Btrfs 包含在主线 Linux 内核中。
Btrfs 快照
Btrfs 子卷可以进行快照和克隆,从而创建另外的 B 树。
快照作为在某个时间点拍摄的子卷的副本开始。
我们可以使快照可写,并将其用作原始子卷的演进克隆。
或者,我们可以将快照用作子卷的稳定镜像,用于备份目的或者迁移到其他系统。
快照可以快速创建,并且它们最初占用很少的磁盘空间。
使用 btrfs subvolume snapshot 命令创建子卷的可写/可读快照。
以下示例创建 SV1 子卷的快照:
# btrfs subvolume snapshot /btrfs/SV1 /btrfs/SV1/SV1-snap Create a snapshot of '/btrfs/SV1' in '/btrfs/SV1/SV1-snap'
使用 btrfs subvolume snapshot -r 选项创建只读快照:
# btrfs subvolume snapshot -r /btrfs/SV1 /btrfs/SV1-rosnap Create a readonly snapshot of '/btrfs/SV1' in '/btrfs/SV1-rosnap'
使用 ls 命令时,快照显示为常规目录。
快照也会出现在 btrfs subvolume list 命令的输出中。
# btrfs subvolume list /btrfs ID 257 gen 10 top level 5 path SV1 ID 258 gen 9 top level 257 path SV1/SV1-snap ID 259 gen 10 top level 5 path SV1-rosnap
挂载子卷或者快照
默认情况下,Linux 挂载 ID 为 0 的父 Btrfs 卷。
在此示例中,在创建任何子卷和快照之前发出以下挂载命令:
# mount /dev/sdb /btrfs
子卷 SV1 是在 /btrfs 中创建的。
ls 命令显示子卷:
# ls -l /btrfs total 0 drwxr-xr-x. 1 root root 84 Mar 29 11:01 SV1
以下示例将文件复制到 SV1,创建 SV1 的快照,并验证子卷和快照是否包含相同的文件:
# cp -p /boot/vmlinuz-3.10.0-693.17.1.el7.x86_64 /btrfs/SV1
# btrfs sub snapshot /btrfs/SV1 /btrfs/SV1-snap Create a snapshot of '/btrfs/SV1' in '/btrfs/SV1-snap'
# ls /btrfs/SV1* /btrfs/SV1: vmlinuz-3.10.0-693.17.1.el7.x86_64 /btrfs/SV1-snap: vmlinuz-3.10.0-693.17.1.el7.x86_64
如果卸载 /btrfs 并重新挂载,默认情况下会挂载父 Btrfs 卷:
# ls /btrfs/ SV1 SV1-snap # umount /btrfs # mount /dev/sda /btrfs/ # ls /btrfs/ SV1 SV1-snap
但是,我们可以将 btrfs 子卷或者快照挂载为磁盘设备。
如果我们挂载快照而不是其父子卷,则可以有效地将文件系统的状态回滚到拍摄快照时的状态。
以下示例将文件复制到 SV1,以便内容与 SV1-snap 不同:
# cp testfile /btrfs/SV1
# ls -l /btrfs/SV1* /btrfs/SV1: total 5760 -rw-r--r--. 1 root root 19 Mar 29 11:44 testfile -rwxr-xr-x. 1 root root 5890720 Jan 25 20:26 vmlinuz-3.10.0-693.17.1.el7.x86_64 /btrfs/SV1-snap: total 5756 -rwxr-xr-x. 1 root root 5890720 Jan 25 20:26 vmlinuz-3.10.0-693.17.1.el7.x86_64
要挂载子卷或者快照,我们必须首先确定要挂载的子卷的 ID 号。
使用 btrfs subvolume list 命令显示 ID 号。
在以下示例中,根子卷的 ID 为 257:
# btrfs sub list /btrfs ID 257 gen 12 top level 5 path SV1 ID 258 gen 9 top level 5 path SV1-snap
使用 btrfs "subvolume set-default" 命令设置文件系统的默认子卷。
例如,要挂载 ID 为 257 的 SV1 Btrfs 子卷:
# btrfs subvolume set-default 257 /btrfs
然后我们需要卸载并重新挂载 Btrfs 文件系统。
然后根级别包含 SV1 子卷的内容,并且根子卷不再可见:
# ls -l /btrfs total 5760 -rw-r--r--. 1 root root 19 Mar 29 11:44 testfile -rwxr-xr-x. 1 root root 5890720 Jan 25 20:26 vmlinuz-3.10.0-693.17.1.el7.x86_64
我们还可以使用 mount 命令的“-o subvolid”选项来挂载根子卷或者子卷或者快照。
例如,要挂载根子卷:
# umount /btrfs # mount -o subvolid=5 /dev/sda /btrfs
# ls -l /btrfs total 0 drwxr-xr-x. 1 root root 84 Mar 29 11:44 SV1 drwxr-xr-x. 1 root root 68 Mar 29 11:17 SV1-snap
创建文件快照
我们可以使用“cp -reflink”命令来拍摄文件的快照。
使用此选项,文件系统不会创建指向现有 inode 的新链接,而是创建一个与原始副本共享相同磁盘块的新 inode。
新文件看起来是原始文件的副本,但数据块没有重复。
这使得复制几乎是即时的,并且还节省了磁盘空间。
随着文件内容随着时间的推移而发生变化,其所需的存储量会增加。
一个限制是此操作只能在同一文件系统的边界内和同一子卷内工作。
以下示例使用 cp -reflink 命令复制文件。
使用的空间在复制操作之前和之后给出。
请注意,使用的空间不会增加。
# df -hP /btrfs Filesystem Size Used Avail Use% Mounted on /dev/sda 10G 23M 8.0G 1% /btrfs
# cp --reflink /btrfs/SV1/vmlinuz-3.10.0-693.17.1.el7.x86_64 /btrfs/SV1/copy_of_vmlinuz
# df -h /btrfs Filesystem Size Used Avail Use% Mounted on /dev/sda 10G 23M 8.0G 1% /btrfs