介绍
btrfs(通常念成 Butter FS、B-tree FS 或 Better FS),由 Oracle 于 2007 年宣布并进行中的 COW(copy-on-write,写时复制式)文件系统。目标是取代 Linux 目前的 ext3 文件系统,改善 ext3 的限制,特别是单一文件大小的限制,总文件系统大小限制以及加入文件校验和特性。加入目前 ext3/4 未支持的一些功能,例如可写的磁盘快照(snapshots),以及支持递归的快照(snapshots of snapshots),内建磁盘阵列(RAID)支持,支持子卷(Subvolumes)的概念,允许在线调整文件系统大小。
写时复制指的是在 btrfs 文件系统修改文件时,会先创建一个要修改文件的文件副本,然后在这个副本的基础上修改,修改完成后将文件的文件名指向这个修改完成的文件副本,所以原来的文件实际上还保留在文件系统中,在某些情况下是可恢复的。
所以 btrfs 中的更新操作实际上是复制、更新及替换指针,而非传统文件系统的”就地“更新。
使用
btrfs 文件系统相关的命令如下:
[root@localhost ~]# btrfs
btrfs btrfsck btrfs-convert btrfs-debug-tree btrfs-find-root btrfs-image btrfs-map-logical btrfs-select-super btrfstune btrfs-zero-log
而 btrfs 文件系统的管理实际上仅仅是使用 btrfs
命令来完成,先简单介绍一下其它的常用命令:
btrfs-convert <DEVICE>
:用来将 ext3/4 文件系统无损的转换为 btrfs 文件系统,也可降级回 ext3/4 文件系统(指定-r
选项);btrfsck <DEVICE>
:对 btrfs 文件系统进行检测;
btrfs
命令的具体使用信息可通过 --help
查看。
创建 btrfs 文件系统在之前文件系统管理的章节有提到过,使用 mkfs.btrfs
命令,常用选项如下:
-L
:指定卷标;-m
:指定元数据(metadata)是否在多个物理卷中存储,存储机制可选值有 raid0、raid1、raid5、raid6、raid10、single(默认)、dup;-d
:指定数据(data)是否在多个物理卷中存储,存储机制可选值有 raid0、raid1、raid5、raid6、raid10、single(默认)、dup;-O
:在格式化文件系统时指定文件系统相关特性选项(老版本内核未必支持所有特性),可使用的特性选项可通过执行mkfs.btrfs -O list-all
查看;
为模拟真实情况,使用 VMWare 给虚拟机添加 3 块 20G 的虚拟硬盘,如下:
执行fdisk -l
会发现新增了 /dev/sd{b,c,d}
三个硬盘,下面直接使用 mkfs.btrfs
来将 /dev/sd{b,c}
创建为一个 btrfs 文件系统,如下:
filesystem 子命令
btrfs filesystem
子命令用来管理 btrfs 文件系统的相关信息,具体使用说明可通过 man btrfs filesystem
查看。
如果创建成功,则可使用 btrfs filesystem show
来查看到创建完成的 btrfs 文件系统,如下:
通过 blkid
命令也能查看到:
/dev/sd{b,c}
组成了一个 btrfs 文件系统,所以它们有相同的 UUID,而/dev/sd{b,c}
时不同的物理卷,以示区分所以它们还有不同的UUID_SUB
属性。
接下来就可以直接挂载使用刚创建的文件系统,如下:
[root@localhost ~]# mount /dev/sdb /mydata/
上面有说过,该 btrfs 文件系统是由
/dev/sd{b,c}
组成的,通常情况下指定其中人一个设备都代表着它所属的全局文件系统,所以挂载时指定任意一个设备文件即可。
btrfs filesystem show --mounted
可显示已挂载的 btrfs 文件系统:
btrfs filesystem df <PATH>
可查看指定 btrfs 文件系统的空间使用情况:
btrfs filesystem label <DEVICE> [LABEL]
可查看或指定卷标:
btrfs filesystem resize [+|-]<SIZE> <MOUNT_POINT>
可动态修改 btrfs 文件系统的大小,比如将刚创建的文件系统大小缩减 10G:
[root@localhost /]# btrfs filesystem resize -10G /mydata/
Resize '/mydata/' of '-10G'
[root@localhost /]# df -lh | tail -1
/dev/sdb 30G 17M 18G 1% /mydata
可以看到,文件系统大小已由 40G 缩减到 30G,如果要再扩展该文件系统大小到 35G,则可将上述执行的命令中
-10G
替换为35G
或+5G
,而如果要扩展到最大可扩展大小,则可替换为max
。
btrfs 文件系统还支持透明压缩机制(存放文件时自动压缩,查看文件时自动解压缩),要使用它需要在挂载时通过 -o compress={lzo|zlib} <DEVICE> <MOUNT_POINT>
选项指定(lzo
和 zlib
是两种压缩算法)。
device 子命令
btrfs device
子命令可用来直接管理 btrfs 文件系统底层的设备,具体使用说明可通过 man btrfs device
查看。
btrfs device add <DEVICE> <MOUNT_POINT>
可用来添加设备到当前的 btrfs 文件系统中,使用该命令时要扩展的 btrfs 文件系统必须是已挂载的,以添加 /dev/sdd
设备到刚创建的文件系统中为例:
[root@localhost /]# btrfs device add /dev/sdd /mydata/
[root@localhost /]# df -lh | tail -1
/dev/sdb 50G 17M 46G 1% /mydata
可以看到,该文件系统直接由 30G 扩展到了 50G 大小。
如果要将已有的设备从文件系统中移除,可使用 btrfs device delete <DEVICE> <MOUNT_POINT>
,与 LVM 不同的是,btrfs 移除已有设备直接执行移除命令即可,不需要手动去将要移除的设备中的数据移动到其它保留设备。
以移除 /dev/sdb
设备为例:
[root@localhost /]# btrfs device delete /dev/sdb /mydata/
[root@localhost /]# btrfs filesystem show
Label: 'mydata' uuid: a454a7d5-e099-4af3-b1b0-81a23fc3dc65
Total devices 2 FS bytes used 704.00KiB
devid 2 size 20.00GiB used 1.28GiB path /dev/sdc
devid 3 size 20.00GiB used 1.28GiB path /dev/sdd
balance 子命令
多数情况下,在添加设备到文件系统之前文件系统中已经有数据存放在原来的设备中,如果需要重新分配这些数据让它们均衡存储在包括新添加的设备中,则可使用 btrfs balance
子命令,该命令的具体使用说明可通过 man btrfs balance
查看。
btrfs balance status <MOUNT_POINT>
可查看挂载的 btrfs 文件系统当前的均衡状态,如:
[root@localhost /]# btrfs balance status /mydata
No balance found on '/mydata'
btrfs balance start <MOUNT_POINT>
用来让数据均衡存储到各个设备,当数据量大的时候是一个较耗时操作,该操作还可通过 btrfs balance <pause|resume|cancel> <MOUNT_POINT>
来暂停、恢复以及取消。
除此之外,btrfs balance start -mconvert=<LEVEL> <MOUNT_POINT>
还可直接修改元数据的存储 RAID 级别,而 btrfs balance start -dconvert=<LEVEL> <MOUNT_POINT>
可直接修改数据的存储 RAID 级别。
要注意的是,修改 RAID 级别时设备数量要满足对应 RAID 级别的要求。
subvolume 子命令
btrfs 文件系统还支持使用子卷,子卷的管理使用 btrfs subvolume
子命令完成,该命令的具体使用说明可通过 man btrfs subvolume
查看。
以在 /mydata
目录下创建一个名为 logs
的子卷为例,使用 btrfs subvolume create <PATH>
命令,如下:
[root@localhost ~]# btrfs subvolume create /mydata/logs
Create subvolume '/mydata/logs'
接下来可以使用 btrfs subvolume list <ROOT_MOUNT_POINT>
查看已创建的子卷:
[root@localhost ~]# btrfs subvolume list /mydata/
ID 260 gen 31 top level 5 path logs
新创建的子卷可以直接通过父卷路径下子卷名称以目录的方式访问,也可以单独挂载子卷访问,挂载命令使用格式入下:
mount -o subvol=<SUBVALUME_NAME> <DEVICE> <MOUNT_POINT>
SUBVALUME_NAME:子卷名称;
DEVICE:父卷包含的任意设备;
MOUNT_POINT:挂载点,子卷要挂载到的目录;
例:将 logs
子卷挂载到 /subvol
目录:
[root@localhost /]# mount -o subvol=logs /dev/sdc /subvol/
[root@localhost /]# btrfs filesystem show
Label: 'mydata' uuid: a454a7d5-e099-4af3-b1b0-81a23fc3dc65
Total devices 3 FS bytes used 720.00KiB
devid 2 size 20.00GiB used 1.28GiB path /dev/sdc
devid 3 size 20.00GiB used 1.28GiB path /dev/sdd
devid 4 size 20.00GiB used 0.00B path /dev/sdb
上面使用的是子卷名称来挂载指定的子卷,还可以使用子卷的 id 挂载,命令格式如下:
mount -o subvolid=<SUBVALUME_ID> <DEVICE> <MOUNT_POINT>
SUBVALUME_NAME:子卷ID;
DEVICE:父卷包含的任意设备;
MOUNT_POINT:挂载点,子卷要挂载到的目录;
可使用
btrfs subvolume list
查看指定父卷所有子卷的 ID,也可使用下面btrfs subvolume show
来查看指定子卷的 ID。
btrfs subvolume show <MOUNT_POINT>
也可以查看子卷的详细信息,这里 MOUNT_POINT
指的是子卷的挂载点,如:
[root@localhost subvol]# btrfs subvolume show /subvol/
/subvol
Name: logs
UUID: 5d542154-7a2c-204b-96e1-2fd49c8d934a
Parent UUID: -
Received UUID: -
Creation time: 2019-10-22 11:53:04 +0800
Subvolume ID: 260
Generation: 36
Gen at creation: 31
Parent ID: 5
Top level ID: 5
Flags: -
Snapshot(s):
btrfs subvolume delete <SUB_VOLUME_PATH>
可以删除子卷,以删除 logs
子卷为例:
[root@localhost /]# btrfs subvolume delete /mydata/logs/
Delete subvolume (no-commit): '/mydata/logs'
子卷还支持创建快照卷,命令格式为 btrfs subvolume snapshot <ORIGINAL_VOLUME> <SNAPSHOT_VOLUME>
,以创建 /mydata/logs
的快照卷为例:
[root@localhost ~]# btrfs subvolume snapshot /mydata/logs /mydata/logs_snap
Create a snapshot of '/mydata/logs' in '/mydata/logs_snap'
使用 LVM 创建快照时,快照卷必须与原卷在同一个卷组中,而创建 btrfs 文件系统的子卷时,快照卷必须与子卷在同一个父卷中。
要删除快照卷同样是使用 btrfs subvolume delete <SUB_VOLUME_PATH>
。
更强大的是,btrfs 文件系统还支持给单个文件创建快照,这里就不做演示,命令格式为 cp --reflink <ORIGINAL_FILE> <SNAPSHOT_FILE>
。
评论区