# btrfs btrfs是一个现代的COW(copy on write)文件系统,该文件系统旨在实现高级功能的同时还注重容错、修复和易于管理。 ## 文件系统特性 ### 在单个设备上的文件系统 想要在分区`/dev/partition`上创建文件系统,可以通过如下命令: ```bash # mkfs.btrfs -L mylabel /dev/partition ``` btrfs元数据的默认节点大小为16KB,而数据默认的扇区大小等于page size并自动检测。如果想要自定义元数据的nodesize,可以通过`-n`属性来指定(必须是扇区大小的整数倍): ```bash # mkfs.btrfs -L mylabel -n 32k /dev/partition ``` ### 在多个设备上创建文件系统 可以在多个磁盘设备上创建btrfs文件系统,并且在创建文件系统后,可以向文件系统中添加更多磁盘。 默认情况下,metadata将会被镜像到两个设备上,而data则是会被分散到所有的设备上。其等价于`mkfs.btrfs -m raid1 -d raid0`。 > 默认情况下,metadata将会使用raid1,存在两个copy,而data则是使用raid0,只存在一个copy(single)。 如果只存在一个磁盘设备,那么metadata将会在一个设备上被重复存储,`mkfs.btrfs -m dup -d single`。但如果存在多个磁盘设备,那么不应该对metadata使用dup,而是指定raid1,`mkfs.btrfs -m raid1 -d single`. #### 新增和删除设备 btrfs支持在创建文件系统后,实时的新增和移除设备,并且支持在raid level之间进行切换。 btrfs支持raid0, raid1, raid5, raid10, raid6。当btrfs针对block进行读取时,会校验checksum。如果checksum校验失败,会尝试从备份copy处进行读取,如果备份copy读取成功,则会修复前面损坏的block。 raid1 profile允许2,3,4个copies,分别叫做RAID1, RAIDC3, RAIDC4。 > 对于RAID5和RAID6,raid5需要的最小设备数量为3个,而raid6需要的最小设备数量为4个。 ## 文件系统创建 `mkfs.btrfs`可以用于创建btrfs文件系统,通过-d来指定data的raid模式,通过-m来指定metadata的raid模式。 指定raid时,有效的值如下: - raid0 - raid1 - raid10 - raid5 - raid6 - single - dup raid 10 至少需要4块设备: ```bash # Create a filesystem across four drives (metadata mirrored, linear data allocation) mkfs.btrfs -d single /dev/sdb /dev/sdc /dev/sdd /dev/sde # Stripe the data without mirroring, metadata are mirrored mkfs.btrfs -d raid0 /dev/sdb /dev/sdc # Use raid10 for both data and metadata mkfs.btrfs -m raid10 -d raid10 /dev/sdb /dev/sdc /dev/sdd /dev/sde # Don't duplicate metadata on a single drive (default on single SSDs) mkfs.btrfs -m single /dev/sdb ``` 如果想要使用不同大小的device,那么striped raid级别(raid0,raid10,raid5,raid6)可能不会使用所有的磁盘空间,而non-striped的等效替代则是会更有效的使用空间(single替换raid0, raid1替换raid10)。 ```bash # Use full capacity of multiple drives with different sizes (metadata mirrored, data not mirrored and not striped) mkfs.btrfs -d single /dev/sdb /dev/sdc ``` 一旦创建文件系统后,可以对文件系统中的任何设备执行挂载操作: ```shell mkfs.btrfs /dev/sdb /dev/sdc /dev/sde mount /dev/sde /mnt ``` 当重启或重新导入了btrfs模块后,需要通过`btrfs device scan`来扫描文件系统中所有的设备。 ### device scan `btrfs device scan`用于扫描/dev下所有的块设备,并用于探测btrfs volume。在导入btrfs模块后,如果文件系统中存在多个磁盘设备,需要执行`btrfs device scan`命令。 ```shell # Scan all devices btrfs device scan # Scan a single device btrfs device scan /dev/sdb ``` ### 添加新设备 `btrfs filesystem show`命令将会展示系统中所有的btrfs文件系统和文件系统所包含的磁盘设备。 `btrfs device add`用于添加新的磁盘设备到已经挂载的文件系统中。 `btrfs balance`可以在已经存在的设备间重新分配负载(restrip) 对于一个已经挂载在`/mnt`的文件系统,调用如下命令可以将`/dev/sdc`设备添加到该文件系统中: ```shell btrfs device add /dev/sdc /mnt ``` 在已经将磁盘设备添加到文件系统后,所有的metadata和data仍然存储在原来的磁盘中,从而可以通过`restrip`来将数据重新负载到各个设备上: ```shell btrfs balance start /mnt ``` `btrfs balance`命令会读取原来所有的metadata和data,并且将其重写到所有可获取的设备中。 ### 非raid文件系统转化为raid文件系统 可以通过向文件系统中新增设备,并运行balance filter来将非raid文件系统转化为raid文件系统,其会改变chunk allocate profile。 例如,可以通过如下方式将一个已经存在的single device转化为RAID1: ```bash mount /dev/sdb1 /mnt btrfs device add /dev/sdc1 /mnt btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt ``` ### 移除设备 `btrfs device delete`用于实时丛文件系统中移除设备,其会将待移除设备上所有的内容重新分配到文件系统中的其他设备上。 移除设备示例如下: ```bash mkfs.btrfs /dev/sdb /dev/sdc /dev/sdd /dev/sde mount /dev/sdb /mnt # Put some data on the filesystem here btrfs device delete /dev/sdc /mnt ``` `btrfs device delete missing`会删除`出现在文件系统元数据描述中但是当前没有被挂载的设备`。 ### 替换失败的设备 当文件系统中的设备正在发生故障或是已经发生故障时,应该使用`btrfs replace`而不是添加新设备后移除故障设备。 示例如下所示: ```bash user@host:~$ sudo btrfs filesystem show Label: none uuid: 67b4821f-16e0-436d-b521-e4ab2c7d3ab7 Total devices 6 FS bytes used 5.47TiB devid 1 size 1.81TiB used 1.71TiB path /dev/sda3 devid 3 size 1.81TiB used 1.71TiB path /dev/sdb3 devid 4 size 1.82TiB used 1.72TiB path /dev/sdc1 devid 6 size 1.82TiB used 1.72TiB path /dev/sdd1 devid 8 size 2.73TiB used 2.62TiB path /dev/sde1 *** Some devices missing ``` 挂载文件系统: ```bash sudo mount -o degraded /dev/sda3 /mnt ``` 将缺失的设备替换为新设备: ```bash sudo btrfs replace start 7 /dev/sdf1 /mnt ``` 替换操作将会在后台进行,可以通过`btrfs replace status`来查看任务执行状态。 ```bash user@host:~$ sudo btrfs replace status /mnt Started on 27.Mar 22:34:20, finished on 28.Mar 06:36:15, 0 write errs, 0 uncorr. read errs ``` - 当用一个更小的设备来替换已经存在的设备时,需要先调用`btrfs fi resize` - 而如果使用一个更大的设备来替换已经存在的设备,可以在替换之后调用`btrfs fi resize`