Linux上的新一代文件系统-Btrfs简介

Linux上的新一代文件系统-Btrfs简介

文件系统彷佛是内核中比较稳定的部分,多年来,人们一直使用 ext2/3,ext 文件系统以其卓越的稳定性成为了事实上的 Linux 标准文件系统。php

近年来 ext2/3 暴露出了一些扩展性问题,因而便催生了 ext4。在2008年发布的 Linux2.6.19 内核中集成了 ext4 的 dev 版本。2.6.28内核发布时,ext4 结束了开发版,开始接受用户的使用。彷佛 ext 就将成为 Linux 文件系统的代名词。然而当您阅读不少有关 ext4 的文章时,会发现都不约而同地提到了 btrfs,并认为 ext4 将是一个过渡的文件系统。 ext4 的做者 Theodore Tso 也盛赞 btrfs 并认为 btrfs 将成为下一代 Linux 标准文件系统。 Oracle,IBM, Intel 等厂商也对 btrfs 表现出了极大的关注,投入了资金和人力。为何 btrfs 如此受人瞩目呢。这即是本文首先想探讨的问题。html

Kevin Bowling[1] 有一篇介绍各类文件系统的文章,在他看来,ext2/3 等文件系统属于“古典时期”。文件系统的新时代是 2005 年由 Sun 公司的 ZFS 开创的。 ZFS 表明” last word in file system ”,意思是此后不再须要开发其余的文件系统了。 ZFS 的确带来了不少崭新的观念,对文件系统来说是一个划时代的做品。node

若是您比较 btrfs 的特性,将会发现 btrfs 和 ZFS 很是相似。也许咱们能够认为 btrfs 就是 Linux 社区对 ZFS 所做出的回应。今后日后在 Linux 中也终于有了一个能够和 ZFS 相媲美的文件系统。linux

btrfs 的特性

您能够在 btrfs 的主页上 [2] 看到 btrfs 的特性列表。我自做主张,将那张列表分红了四大部分。算法

首先是扩展性 (scalability) 相关的特性,btrfs 最重要的设计目标是应对大型机器对文件系统的扩展性要求。 Extent,B-Tree 和动态 inode 建立等特性保证了 btrfs 在大型机器上仍有卓越的表现,其总体性能而不会随着系统容量的增长而下降。数据库

其次是数据一致性 (data integrity) 相关的特性。系统面临不可预料的硬件故障,Btrfs 采用 COW 事务技术来保证文件系统的一致性。 btrfs 还支持 checksum,避免了 silent corrupt 的出现。而传统文件系统则没法作到这一点。安全

第三是和多设备管理相关的特性。 Btrfs 支持建立快照 (snapshot),和克隆 (clone) 。 btrfs 还可以方便的管理多个物理设备,使得传统的卷管理软件变得多余。网络

最后是其余难以归类的特性。这些特性都是比较先进的技术,可以显著提升文件系统的时间 / 空间性能,包括延迟分配,小文件的存储优化,目录索引等。数据结构

扩展性相关的特性

B-Tree异步

btrfs 文件系统中全部的 metadata 都由 BTree 管理。使用 BTree 的主要好处在于查找,插入和删除操做都很高效。能够说 BTree 是 btrfs 的核心。

一味地夸耀 BTree 很好很高效也许并不能让人信服,但假如稍微花费一点儿时间看看 ext2/3 中元数据管理的实现方式,即可以反衬出 BTree 的优势。

妨碍 ext2/3 扩展性的一个问题来自其目录的组织方式。目录是一种特殊的文件,在 ext2/3 中其内容是一张线性表格。如图 1-1 所示 [6]:

图 1. ext2 directory [6]

ext2 directory

图 1 展现了一个 ext2 目录文件的内容,该目录中包含四个文件。分别是 "home1","usr","oldfile" 和 "sbin" 。若是须要在该目录中查找目录 sbin,ext2 将遍历前三项,直至找到 sbin 这个字符串为止。

这种结构在文件个数有限的状况下是比较直观的设计,但随着目录下文件数的增长,查找文件的时间将线性增加。 2003 年,ext3 设计者开发了目录索引技术,解决了这个问题。目录索引使用的数据结构就是 BTree 。若是同一目录下的文件数超过 2K,inode 中的 i_data 域指向一个特殊的 block 。在该 block 中存储着目录索引 BTree 。 BTree 的查找效率高于线性表,

但为同一个元数据设计两种数据结构老是不太优雅。在文件系统中还有不少其余的元数据,用统一的 BTree 管理是很是简单而优美的设计。

Btrfs 内部全部的元数据都采用 BTree 管理,拥有良好的可扩展性。 btrfs 内部不一样的元数据由不一样的 Tree 管理。在 superblock 中,有指针指向这些 BTree 的根。如图 2 所示:

图 2. btrfs btree

btrfs btree

FS Tree 管理文件相关的元数据,如 inode,dir 等; Chunk tree 管理设备,每个磁盘设备都在 Chunk Tree 中有一个 item ; Extent Tree 管理磁盘空间分配,btrfs 每分配一段磁盘空间,便将该磁盘空间的信息插入到 Extent tree 。查询 Extent Tree 将获得空闲的磁盘空间信息; Tree of tree root 保存不少 BTree 的根节点。好比用户每创建一个快照,btrfs 便会建立一个 FS Tree 。为了管理全部的树,btrfs 采用 Tree of tree root 来保存全部树的根节点; checksum Tree 保存数据块的校验和。

基于 Extent 的文件存储

现代不少文件系统都采用了 extent 替代 block 来管理磁盘。 Extent 就是一些连续的 block,一个 extent 由起始的 block 加上长度进行定义。

Extent 能有效地减小元数据开销。为了进一步理解这个问题,咱们仍是看看 ext2 中的反面例子。

ext2/3 以 block 为基本单位,将磁盘划分为多个 block 。为了管理磁盘空间,文件系统须要知道哪些 block 是空闲的。 Ext 使用 bitmap 来达到这个目的。 Bitmap 中的每个 bit 对应磁盘上的一个 block,当相应 block 被分配后,bitmap 中的相应 bit 被设置为 1 。这是很经典也很清晰的一个设计,但不幸的是当磁盘容量变大时,bitmap 自身所占用的空间也将变大。这就致使了扩展性问题,随着存储设备容量的增长,bitmap 这个元数据所占用的空间也随之增长。而人们但愿不管磁盘容量如何增长,元数据不该该随之线形增长,这样的设计才具备可扩展性。

下图比较了 block 和 extent 的区别:

图 3. 采用 extent 的 btrfs 和采用 bitmap 的 ext2/3

采用extent的btrfs和采用bitmap的ext2/3

在 ext2/3 中,10 个 block 须要 10 个 bit 来表示;在 btrfs 中则只须要一个元数据。对于大文件,extent 表现出了更加优异的管理性能。

Extent 是 btrfs 管理磁盘空间的最小单位,由 extent tree 管理。 Btrfs 分配 data 或 metadata 都须要查询 extent tree 以便得到空闲空间的信息。

动态 inode 分配

为了理解动态 inode 分配,仍是须要借助 ext2/3 。下表列举了 ext2 文件系统的限制:

表 1. ext2 限制

  限制
最大文件数量 文件系统空间大小 V / 8192
好比 100G 大小的文件系统中,能建立的文件个数最大为 131072

图 4 显示了 ext2 的磁盘布局:

图 4. ext2 layout

ext2 layout

在 ext2 中 inode 区是被预先固定分配的,且大小固定,好比一个 100G 的分区中,inode table 区中只能存放 131072 个 inode,这就意味着不可能建立超过 131072 个文件,由于每个文件都必须有一个惟一的 inode 。

为了解决这个问题,必须动态分配 inode 。每个 inode 只是 BTree 中的一个节点,用户能够无限制地任意插入新的 inode,其物理存储位置是动态分配的。因此 btrfs 没有对文件个数的限制。

针对 SSD 的优化支持

SSD 是固态存储 Solid State Disk 的简称。在过去的几十年中,CPU/RAM 等器件的发展始终遵循着摩尔定律,但硬盘 HDD 的读写速率却始终没有飞跃式的发展。磁盘 IO 始终是系统性能的瓶颈。

SSD 采用 flash memory 技术,内部没有磁盘磁头等机械装置,读写速率大幅度提高。 flash memory 有一些不一样于 HDD 的特性。 flash 在写数据以前必须先执行擦除操做;其次,flash 对擦除操做的次数有必定的限制,在目前的技术水平下,对同一个数据单元最多能进行约 100 万次擦除操做,所以,为了延长 flash 的寿命,应该将写操做平均到整个 flash 上。

SSD 在硬件内部的微代码中实现了 wear leveling 等分布写操做的技术,所以系统无须再使用特殊的 MTD 驱动和 FTL 层。虽然 SSD 在硬件层面作了不少努力,但毕竟仍是有限。文件系统针对 SSD 的特性作优化不只能提升 SSD 的使用寿命,并且能提升读写性能。 Btrfs 是少数专门对 SSD 进行优化的文件系统。 btrfs 用户可使用 mount 参数打开对 SSD 的特殊优化处理。

Btrfs 的 COW 技术从根本上避免了对同一个物理单元的反复写操做。若是用户打开了 SSD 优化选项,btrfs 将在底层的块空间分配策略上进行优化:将屡次磁盘空间分配请求聚合成一个大小为 2M 的连续的块。大块连续地址的 IO 可以让固化在 SSD 内部的微代码更好的进行读写优化,从而提升 IO 性能。

数据一致性相关的特性

COW 事务

理解 COW 事务,必须首先理解 COW 和事务这两个术语。

什么是 COW?

所谓 COW,即每次写磁盘数据时,先将更新数据写入一个新的 block,当新数据写入成功以后,再更新相关的数据结构指向新 block 。

什么是事务?

COW 只能保证单一数据更新的原子性。但文件系统中不少操做须要更新多个不一样的元数据,好比建立文件须要修改如下这些元数据:

  1. 修改 extent tree,分配一段磁盘空间
  2. 建立一个新的 inode,并插入 FS Tree 中
  3. 增长一个目录项,插入到 FS Tree 中

任何一个步骤出错,文件便不能建立成功,所以能够定义为一个事务。

下面将演示一个 COW 事务。

A 是 FS Tree 的根节点,新的 inode 的信息将被插入节点 C 。首先,btrfs 将 inode 插入一个新分配的 block C ’中,并修改上层节点 B,使其指向新的 block C ’;修改 B 也将引起 COW,以此类推,引起一个连锁反应,直到最顶层的 Root A 。当整个过程结束后,新节点 A ’变成了 FS Tree 的根。但此时事务并未结束,superblock 依然指向 A 。

图 5. COW transaction 1

COW transaction 1

接下来,修改目录项(E 节点),一样引起这一过程,从而生成新的根节点 A ’’。

图 6. COW transaction 2

COW transaction 2

此时,inode 和目录项都已经写入磁盘,能够认为事务已经结束。 btrfs 修改 superblock,使其指向 A ’’,以下图所示:

图 7. COW transaction 3

COW transaction 3

COW 事务可以保证文件系统的一致性,而且系统 Reboot 以后不须要执行 fsck 。由于 superblock 要么指向新的 A ’’,要么指向 A,不管哪一个都是一致的数据。

Checksum

Checksum 技术保证了数据的可靠性,避免 silent corruption 现象。因为硬件缘由,从磁盘上读出的数据会出错。好比 block A 中存放的数据为 0x55,但读取出来的数据变是 0x54,由于读取操做并未报错,因此这种错误不能被上层软件所察觉。

解决这个问题的方法是保存数据的校验和,在读取数据后检查校验和。若是不符合,便知道数据出现了错误。

ext2/3 没有校验和,对磁盘彻底信任。而不幸的是,磁盘的错误始终存在,不只发生在廉价的 IDE 硬盘上,昂贵的 RAID 也存在 silent corruption 问题。并且随着存储网络的发展,即便数据从磁盘读出正确,也很难确保可以安全地穿越网络设备。

btrfs 在读取数据的同时会读取其相应的 checksum 。若是最终从磁盘读取出来的数据和 checksum 不相同,btrfs 会首先尝试读取数据的镜像备份,若是数据没有镜像备份,btrfs 将返回错误。写入磁盘数据以前,btrfs 计算数据的 checksum 。而后将 checksum 和数据同时写入磁盘。

Btrfs 采用单独的 checksum Tree 来管理数据块的校验和,把 checksum 和 checksum 所保护的数据块分离开,从而提供了更严格的保护。假如在每一个数据 block 的 header 中加入一个域保存 checksum,那么这个数据 block 就成为一个本身保护本身的结构。这种结构下有一种错误没法检测出来,好比原本文件系统打算从磁盘上读 block A,但返回了 block B,因为 checksum 在 block 内部,所以 checksum 依旧是正确的。 btrfs 采用 checksum tree 来保存数据块的 checksum,避免了上述问题。

Btrfs 采用 crc32 算法计算 checksum,在未来的开发中会支持其余类型的校验算法。为了提升效率,btrfs 将写数据和 checksum 的工做分别用不一样的内核线程并行执行。

多设备管理相关的特性

每一个 Unix 管理员都曾面临为用户和各类应用分配磁盘空间的任务。多数状况下,人们没法事先准确地估计一个用户或者应用在将来究竟须要多少磁盘空间。磁盘空间被用尽的状况常常发生,此时人们不得不试图增长文件系统空间。传统的 ext2/3 没法应付这种需求。

不少卷管理软件被设计出来知足用户对多设备管理的需求,好比 LVM 。 Btrfs 集成了卷管理软件的功能,一方面简化了用户命令;另外一方面提升了效率。

多设备管理

Btrfs 支持动态添加设备。用户在系统中增长新的磁盘以后,可使用 btrfs 的命令将该设备添加到文件系统中。

为了灵活利用设备空间,Btrfs 将磁盘空间划分为多个 chunk 。每一个 chunk 可使用不一样的磁盘空间分配策略。好比某些 chunk 只存放 metadata,某些 chunk 只存放数据。一些 chunk 能够配置为 mirror,而另外一些 chunk 则能够配置为 stripe 。这为用户提供了很是灵活的配置可能性。

Subvolume

Subvolume 是很优雅的一个概念。即把文件系统的一部分配置为一个完整的子文件系统,称之为 subvolume 。

采用 subvolume,一个大的文件系统能够被划分为多个子文件系统,这些子文件系统共享底层的设备空间,在须要磁盘空间时便从底层设备中分配,相似应用程序调用 malloc() 分配内存同样。能够称之为存储池。这种模型有不少优势,好比能够充分利用 disk 的带宽,能够简化磁盘空间的管理等。

所谓充分利用 disk 的带宽,指文件系统能够并行读写底层的多个 disk,这是由于每一个文件系统均可以访问全部的 disk 。传统的文件系统不能共享底层的 disk 设备,不管是物理的仍是逻辑的,所以没法作到并行读写。

所谓简化管理,是相对于 LVM 等卷管理软件而言。采用存储池模型,每一个文件系统的大小均可以自动调节。而使用 LVM,若是一个文件系统的空间不够了,该文件系统并不能自动使用其余磁盘设备上的空闲空间,而必须使用 LVM 的管理命令手动调节。

Subvolume 能够做为根目录挂载到任意 mount 点。 subvolume 是很是有趣的一个特性,有不少应用。

假如管理员只但愿某些用户访问文件系统的一部分,好比但愿用户只能访问 /var/test/ 下面的全部内容,而不能访问 /var/ 下面其余的内容。那么即可以将 /var/test 作成一个 subvolume 。 /var/test 这个 subvolume 即是一个完整的文件系统,能够用 mount 命令挂载。好比挂载到 /test 目录下,给用户访问 /test 的权限,那么用户便只能访问 /var/test 下面的内容了。

快照和克隆

快照是对文件系统某一时刻的彻底备份。创建快照以后,对文件系统的修改不会影响快照中的内容。这是很是有用的一种技术。

好比数据库备份。假如在时间点 T1,管理员决定对数据库进行备份,那么他必须先中止数据库。备份文件是很是耗时的操做,假如在备份过程当中某个应用程序修改了数据库的内容,那么将没法获得一个一致性的备份。所以在备份过程当中数据库服务必须中止,对于某些关键应用这是不能容许的。

利用快照,管理员能够在时间点 T1 将数据库中止,对系统创建一个快照。这个过程通常只须要几秒钟,而后就能够当即从新恢复数据库服务。此后在任什么时候候,管理员均可以对快照的内容进行备份操做,而此时用户对数据库的修改不会影响快照中的内容。当备份完成,管理员即可以删除快照,释放磁盘空间。

快照通常是只读的,当系统支持可写快照,那么这种可写快照便被称为克隆。克隆技术也有不少应用。好比在一个系统中安装好基本的软件,而后为不一样的用户作不一样的克隆,每一个用户使用本身的克隆而不会影响其余用户的磁盘空间。很是相似于虚拟机。

Btrfs 支持 snapshot 和 clone 。这个特性极大地增长了 btrfs 的使用范围,用户不须要购买和安装昂贵而且使用复杂的卷管理软件。下面简要介绍一下 btrfs 实现快照的基本原理。

如前所述 Btrfs 采用 COW 事务技术,从图 1-10 能够看到,COW 事务结束后,若是不删除原来的节点 A,C,E,那么 A,C,E,D,F 依然完整的表示着事务开始以前的文件系统。这就是 snapshot 实现的基本原理。

Btrfs 采用引用计数决定是否在事务 commit 以后删除原有节点。对每个节点,btrfs 维护一个引用计数。当该节点被别的节点引用时,该计数加一,当该节点再也不被别的节点引用时,该计数减一。当引用计数归零时,该节点被删除。对于普通的 Tree Root, 引用计数在建立时被加一,由于 Superblock 会引用这个 Root block 。很明显,初始状况下这棵树中的全部其余节点的引用计数都为一。当 COW 事务 commit 时,superblock 被修改指向新的 Root A ’’,原来 Root block A 的引用计数被减一,变为零,所以 A 节点被删除。 A 节点的删除会引起其子孙节点的引用计数也减一,图 1-10 中的 B,C 节点的引用计数所以也变成了 0,从而被删除。 D,E 节点在 COW 时,由于被 A ’’所引用,计数器加一,所以计数器这时并未归零,从而没有被删除。

建立 Snapshot 时,btrfs 将的 Root A 节点复制到 sA,并将 sA 的引用计数设置为 2 。在事务 commit 的时候,sA 节点的引用计数不会归零,从而不会被删除,所以用户能够继续经过 Root sA 访问 snapshot 中的文件。

图 8. Snapshot

Snapshot

软件 RAID

RAID 技术有不少很是吸引人的特性,好比用户能够将多个廉价的 IDE 磁盘组合为 RAID0 阵列,从而变成了一个大容量的磁盘; RAID1 和更高级的 RAID 配置还提供了数据冗余保护,从而使得存储在磁盘中的数据更加安全。

Btrfs 很好的支持了软件 RAID,RAID 种类包括 RAID0,RAID1 和 RAID10.

Btrfs 缺省状况下对 metadata 进行 RAID1 保护。前面已经说起 btrfs 将设备空间划分为 chunk,一些 chunk 被配置为 metadata,即只存储 metadata 。对于这类 chunk,btrfs 将 chunk 分红两个条带,写 metadata 的时候,会同时写入两个条带内,从而实现对 metadata 的保护。

其余特性

Btrfs 主页上罗列的其余特性不容易分类,这些特性都是现代文件系统中比较先进的技术,可以提升文件系统的时间或空间效率。

Delay allocation

延迟分配技术可以减小磁盘碎片。在 Linux 内核中,为了提升效率,不少操做都会延迟。

在文件系统中,小块空间频繁的分配和释放会形成碎片。延迟分配是这样一种技术,当用户须要磁盘空间时,先将数据保存在内存中。并将磁盘分配需求发送给磁盘空间分配器,磁盘空间分配器并不当即分配真正的磁盘空间。只是记录下这个请求便返回。

磁盘空间分配请求可能很频繁,因此在延迟分配的一段时间内,磁盘分配器能够收到不少的分配请求,一些请求也许能够合并,一些请求在这段延迟期间甚至可能被取消。经过这样的“等待”,每每可以减小没必要要的分配,也有可能将多个小的分配请求合并为一个大的请求,从而提升 IO 效率。

Inline file

系统中每每存在大量的小文件,好比几百个字节或者更小。若是为其分配单独的数据 block,便会引发内部碎片,浪费磁盘空间。 btrfs 将小文件的内容保存在元数据中,再也不额外分配存放文件数据的磁盘块。改善了内部碎片问题,也增长了文件的访问效率。

图 9. inline file

inline file

上图显示了一个 BTree 的叶子节点。叶子中有两个 extent data item 元数据,分别用来表示文件 file1 和 file2 所使用的磁盘空间。

假设 file1 的大小仅为 15 个字节; file2 的大小为 1M 。如图所示,file2 采用普通的 extent 表示方法:extent2 元数据指向一段 extent,大小为 1M,其内容即是 file2 文件的内容。

而对于 file1, btrfs 会把其文件内容内嵌到元数据 extent1 中。若是不采用 inline file 技术。如虚线所示,extent1 指向一个最小的 extent,即一个 block,但 file1 有 15 个字节,其他的空间便成为了碎片空间。

采用 inline 技术,读取 file1 时只须要读取元数据 block,而无需先读取 extent1 这个元数据,再读取真正存放文件内容的 block,从而减小了磁盘 IO 。

得益于 inline file 技术,btrfs 处理小文件的效率很是高,也避免了磁盘碎片问题。

目录索引 Directory index

当一个目录下的文件数目巨大时,目录索引能够显著提升文件搜索时间。 Btrfs 自己采用 BTree 存储目录项,因此在给定目录下搜索文件的效率是很是高的。

然而,btrfs 使用 BTree 管理目录项的方式没法同时知足 readdir 的需求。 readdir 是 POSIX 标准 API,它要求返回指定目录下的全部文件,而且特别的,这些文件要按照 inode number 排序。而 btrfs 目录项插入 BTree 时的 Key 并非 Inode number,而是根据文件名计算的一个 hash 值。这种方式在查找一个特定文件时很是高效,但却不适于 readdir 。为此,btrfs 在每次建立新的文件时,除了插入以 hash 值为 Key 的目录项外,还同时插入另一种目录项索引,该目录项索引的 KEY 以 sequence number 做为 BTree 的键值。这个 sequence number 在每次建立新文件时线性增长。由于 Inode number 也是每次建立新文件时增长的,因此 sequence number 和 inode number 的顺序相同。以这种 sequence number 做为 KEY 在 BTree 中查找即可以方便的获得一个以 inode number 排序的文件列表。

另外以 sequence number 排序的文件每每在磁盘上的位置也是相邻的,因此以 sequence number 为序访问大量文件会得到更好的 IO 效率。

压缩

你们都曾使用过 zip,winrar 等压缩软件,将一个大文件进行压缩能够有效节约磁盘空间。 Btrfs 内置了压缩功能。

一般人们认为将数据写入磁盘以前进行压缩会占用不少的 CPU 计算时间,必然下降文件系统的读写效率。但随着硬件技术的发展,CPU 处理时间和磁盘 IO 时间的差距不断加大。在某些状况下,花费必定的 CPU 时间和一些内存,但却能大大节约磁盘 IO 的数量,这反而可以增长总体的效率。

好比一个文件不通过压缩的状况下须要 100 次磁盘 IO 。但花费少许 CPU 时间进行压缩后,只须要 10 次磁盘 IO 就能够将压缩后的文件写入磁盘。在这种状况下,IO 效率反而提升了。固然,这取决于压缩率。目前 btrfs 采用 zlib 提供的 DEFALTE/INFLATE 算法进行压缩和解压。在未来,btrfs 应该能够支持更多的压缩算法,知足不一样用户的不一样需求。

目前 btrfs 的压缩特性还存在一些不足,当压缩使能后,整个文件系统下的全部文件都将被压缩,但用户可能须要更细粒度的控制,好比针对不一样的目录采用不一样的压缩算法,或者禁止压缩。我相信,btrfs 开发团队将在从此的版本中解决这个问题。

对于某些类型的文件,好比 jpeg 文件,已经没法再进行压缩。尝试对其压缩将纯粹浪费 CPU 。为此,当对某文件的若干个 block 压缩后发现压缩率不佳,btrfs 将不会再对文件的其他部分进行压缩操做。这个特性在某种程度上提升了文件系统的 IO 效率。

预分配

不少应用程序有预先分配磁盘空间的须要。他们能够经过 posix_fallocate 接口告诉文件系统在磁盘上预留一部分空间,但暂时并不写入数据。若是底层文件系统不支持 fallocate,那么应用程序只有使用 write 预先写一些无用信息以便为本身预留足够的磁盘空间。

由文件系统来支持预留空间更加有效,并且可以减小磁盘碎片,由于全部的空间都是一次分配,于是更有可能使用连续的空间。 Btrfs 支持 posix_fallocate 。

总结

至此,咱们对 btrfs 的不少特性进行了较为详细的探讨,但 btrfs 能提供的特性却并不止这些。 btrfs 正处于试验开发阶段,还将有更多的特性。

Btrfs 也有一个重要的缺点,当 BTree 中某个节点出现错误时,文件系统将失去该节点之下的全部的文件信息。而 ext2/3 却避免了这种被称为”错误扩散”的问题。

但不管怎样,但愿您和我同样,开始认同 btrfs 将是 Linux 将来最有但愿的文件系统。

BTRFS 使用简介

了解了 btrfs 的特性,想必您必定想亲身体验一下 btrfs 的使用。本章将简要介绍如何使用 btrfs 。

建立文件系统

mkfs.btrfs 命令创建一个 btrfs 格式的文件系统。能够用以下命令在设备 sda5 上创建一个 btrfs 文件系统,并将其挂载到 /btrfsdisk 目录下:

1
2
3
#mkfs.btrfs /dev/sda5
  #mkdir /btrfsdisk
  #mount – t btrfs /dev/sda5 /btrfsdisk

这样一个 Btrfs 就在设备 sda5 上创建好了。值得一提的是在这种缺省状况下,即便只有一个设备,Btrfs 也会对 metadata 进行冗余保护。若是有多个设备,那么您能够在建立文件系统的时候进行 RAID 设置。详细信息请参见后续的介绍。

这里介绍其余几个 mkfs.btrfs 的参数。

Nodesize 和 leafsize 用来设定 btrfs 内部 BTree 节点的大小,缺省为一个 page 大小。但用户也可使用更大的节点,以便增长 fanout,减少树的高度,固然这只适合很是大的文件系统。

Alloc-start 参数用来指定文件系统在磁盘设备上的起始地址。这使得用户能够方便的预留磁盘前面的一些特殊空间。

Byte-count 参数设定文件系统的大小,用户能够只使用设备的一部分空间,当空间不足时再增长文件系统大小。

修改文件系统的大小

当文件系统创建好以后,您能够修改文件系统的大小。 /dev/sda5 挂载到了 /btrfsdisk 下,大小为 800M 。假如您但愿只使用其中的 500M,则须要减少当前文件系统的大小,这能够经过以下命令实现:

1
2
3
4
5
6
7
8
9
#df
  Filesystem   1K-blocks     Used      Available   Use%   Mounted on
  /dev/sda1    101086        19000       76867         20%     /boot
  /dev/sda5    811248         32       811216         1%     /btrfsdisk
  #btrfsctl – r -300M /btrfsdisk
  #df
  Filesystem  1K-blocks      Used      Available   Use%   Mounted on
  /dev/sda1    101086        19000       76867         20%     /boot
  /dev/sda5    504148         32       504106         1%     /btrfsdisk

一样的,您可使用 btrfsctl 命令增长文件系统的大小。

建立 Snapshot

下面的例子中,建立快照 snap1 时系统存在 2 个文件。建立快照以后,对 test1 的内容进行修改。再回到 snap1,打开 test1 文件,能够看到 test1 的内容依旧是以前的内容。

1
2
3
4
5
6
7
8
9
10
#ls /btrfsdisk
  test1 test2
  #vi test1
  This is a test
  #btrfsctl – s snap1 /btrfsdisk
  #vi test1
  Test1 is modified
  #cd /btrfsdisk/snap1
  #cat test1
  This is a test

能够从上面的例子看到,快照 snap1 保存的内容不会被后续的写操做所改变。

建立 subvolume

使用 btrfs 命令,用户能够方便的创建 subvolume 。假设 /btrfsdisk 已经挂载到了 btrfs 文件系统,则用户能够在这个文件系统内建立新的 subvolume 。好比创建一个 /sub1 的 subvolume,并将 sub1 挂载到 /mnt/test 下:

1
2
3
#mkdir /mnt/test
  #btrfsctl – S sub1 /btrfsdisk
  #mount – t btrfs – o subvol=sub1 /dev/sda5 /mnt/test

Subvolme 能够方便管理员在文件系统上建立不一样用途的子文件系统,并对其进行一些特殊的配置,好比有些目录下的文件关注节约磁盘空间,所以须要打开压缩,或者配置不一样的 RAID 策略等。目前 btrfs 尚处于开发阶段,建立的 subvolme 和 snapshot 还没法删除。此外针对 subvolume 的磁盘 quota 功能也未能实现。但随着 btrfs 的不断成熟,这些功能必然将会进一步完善

建立 RAID

mkfs 的时候,能够指定多个设备,并配置 RAID 。下面的命令演示了如何使用 mkfs.btrfs 配置 RAID1 。 Sda6 和 sda7 能够配置为 RAID1,即 mirror 。用户能够选择将数据配置为 RAID1,也能够选择将元数据配置为 RAID1 。

将数据配置为 RAID1,可使用 mkfs.btrfs 的 -d 参数。以下所示:

1
2
#mkfs.btrfs – d raid1 /dev/sda6 /dev/sda7
 #mount – t btrfs /dev/sda6 /btrfsdisk

添加新设备

当设备的空间快被使用完的时候,用户可使用 btrfs-vol 命令为文件系统添加新的磁盘设备,从而增长存储空间。下面的命令向 /btrfsdisk 文件系统增长一个设备 /sda8

1
#btrfs-vol – a /dev/sda8 /btrfsdisk

SSD 支持

用户可使用 mount 参数打开 btrfs 针对 SSD 的优化。命令以下:

1
#mount – t btrfs – o SSD /dev/sda5 /btrfsdisk

开启压缩功能

用户可使用 mount 参数打开压缩功能。命令以下

1
#mount – t btrfs – o compress /dev/sda5 /btrfsdisk

同步文件系统

为了提升效率,btrfs 的 IO 操做由一些内核线程异步处理。这使得用户对文件的操做并不会当即反应到磁盘上。您能够作一个实验,在 btrfs 上建立一个文件后,稍等 5 到 10 秒将系统电源切断,再次重启后,新建的文件并无出现。

对于多数应用这并非问题,但有些时候用户但愿 IO 操做当即执行,此时就须要对文件系统进行同步。下面的 btrfs 命令用来同步文件系统:

1
#btrfsctl – c /btrfsdisk

Debug 功能

Btrfs 提供了必定的 debug 功能,对于想了解 Btrfs 内部实现原理的读者,debug 将是您最喜欢的工具。这里简单介绍一下 debug 功能的命令使用。

下面的命令将设备 sda5 上的 btrfs 文件系统中的元数据打印到屏幕上。

1
#btrfs-debug-tree /dev/sda5

经过对打印信息的分析,您将能了解 btrfs 内部各个 BTree 的变化状况,从而进一步理解每个文件系统功能的内部实现细节。

好比您能够在建立一个文件以前将 BTree 的内容打印出来,建立文件后再次打印。经过比较两次的不一样来了解 btrfs 建立一个文件须要修改哪些元数据。进而理解 btrfs 内部的工做原理。

结束语

我想,在将来的日子里,EXT 等传统文件系统确定不会消失。古典文件系统成熟,稳定,经受了历史的考验,必然将在很长一段时间内被继续普遍使用。古典文件系统和新一代文件系统同时并存是很是合理的事情。正如咱们在被陈亦迅的歌声触动和感伤以后,还能够在莫扎特的奏鸣曲中获得慰藉和平静。

本人水平有限,对文件系统的了解也并不深刻,所以文中必然有不少错误的地方,但愿能获得你们的指正。

相关主题

相关文章
相关标签/搜索