新一代 Linux 文件系统 btrfs 简介

来源:developerWorks 中国 作者:刘 明
  
Btrfs 被称为是下一代 Linux 文件系统。近年来 ext2/3 遇到越来越多的扩展性问题,在期待 ext4 的同时,人们发现了 btrfs,据说它采用了很多先进的文件系统设计,不仅解决了 ext2/3 的扩展性问题,还让人们看到了下一代文件系统所具有的许多其他特性。这一切都让人不禁心生好奇,btrfs 究竟提供了哪些特性?它是如何实现的?本文便围绕这些问题展开探讨,首先研究了 btrfs 所提供的新特性,并简要介绍了 btrfs 内部实现这些特性的原理;然后演示了 btrfs 的常用命令。

Btrfs 简介

文件系统似乎是内核中比较稳定的部分,多年来,人们一直使用 ext2/3,ext 文件系统以其卓越的稳定性成为了事实上的 Linux 标准文件系统。近年来 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 如此受人瞩目呢。这便是本文首先想探讨的问题。

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

如果您比较 btrfs 的特性,将会发现 btrfs 和 ZFS 非常类似。也许我们可以认为 btrfs 就是 Linux 社区对 ZFS 所作出的回应。从此往后在 Linux 中也终于有了一个可以和 ZFS 相媲美的文件系统。





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-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 的根。如图 1-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

图 1-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
时间:2009-08-20 16:43 来源:developerWorks 中国 作者:刘 明 原文链接

好文,顶一下
(9)
100%
文章真差,踩一下
(0)
0%
------分隔线----------------------------


把开源带在你的身边-精美linux小纪念品
无觅相关文章插件,快速提升流量