XFS文件系统概述
2013-08-28 13:51:57 阿炯

XFSSGI公司贡献给Linux的综合性能最高的文件系统,没有之一。

XFS: A high-performance journaling filesystem

XFS combines advanced journaling technology with full 64-bit addressing and scalable structures and algorithms. This combination delivers the most scalable high-performance filesystem ever conceived.

XFS是一种开发于1993年的高性能日志文件系统,由Silicon Graphics为其IRIX操作系统而开发,是IRIX 5.3版的默认文件系统。2000年5月,Silicon Graphics以GNU通用公共许可证发布这套系统的源代码,之后被移植到Linux内核上。XFS特别擅长处理大文件,同时提供平滑的数据传输。

在1994年其被首次部署在IRIX 5.3上。2000年5月,XFS在GNU通用公共许可证下发布,并被移植到Linux上。2001年XFS首次被Linux发行版所支持,现在所有的Linux发行版上都可以使用XFS。最初被合并到Linux 2.4主线中,这使得XFS几乎可以被用在任何一个Linux系统上。Arch, Debian, Fedora, openSUSE, Gentoo, Kate OS, Mandriva, Slackware, Ubuntu, VectorLinux和Zenwalk的安装程序中都可选择XFS作为文件系统,但由于默认的启动管理器GRUB中存在bug,以上发行版中只有少数几个允许用户在 /boot 挂载点(引导目录)上使用XFS文件系统。

FreeBSD在2005年12月获得了对XFS的只读支持,并在次年6月引入了试验性的写入支持。不过这些只是为了方便用户从Linux上迁移到FreeBSD上,并不是为了把XFS作为主打文件系统使用。Red Hat Enterprise Linux 5.4 64位版的内核完整支持XFS,但未包含创建和使用XFS的命令行工具。Red Hat Enterprise Linux 7/CentOS默认使用XFS文件系统。

XFS文件系统是作为一个日志文件系统,采用B-树平衡树算法来尽快地分配数据,主要的设计目的之一是支持大型文件和大型文件系统。XFS 最初是由 Silicon Graphics,Inc. 于 90 年代初开发的。那时 SGI 发现他们的现有文件系统(existing filesystem,EFS)正在迅速变得不适应当时激烈的计算竞争。为解决这个问题,SGI 决定设计一种全新的高性能 64 位文件系统,而不是试图调整 EFS在先天设计上的某些缺陷。因此XFS 诞生了,并于 1994 年随 IRIX 5.3 的发布而应用于计算。它至今仍作为 SGI 基于 IRIX 的产品(从工作站到超级计算机)的底层文件系统来使用。现在XFS也可以用于 Linux,XFS 的 Linux 版的到来是激动人心的,首先因为它为 Linux 社区提供了一种健壮的、优秀的以及功能丰富的文件系统,并且这种文件系统所具有的可伸缩性能够满足最苛刻的存储需求。

主要特性
数据完全性

采用XFS文件系统,当意想不到的宕机发生后,首先,由于文件系统开启了日志功能,所以你磁盘上的文件不再会意外宕机而遭到破坏了。不论目前文件系统上存储的文件与数据有多少,文件系统都可以根据所记录的日志在很短的时间内迅速恢复磁盘文件内容。

传输特性
XFS文件系统采用优化算法,日志记录对整体文件操作影响非常小。XFS查询与分配存储空间非常快,xfs文件系统能连续提供快速的反应时间。这里有一篇测试文章,可以看出XFS文件文件系统的性能表现相当出众。

可扩展性
XFS是一个全64-bit的文件系统,它可以支持上百万T字节的存储空间。对特大文件及小尺寸文件的支持都表现出众,支持特大数量的目录。最大可支持的文件大小为263 = 9 x 1018 = 9 exabytes,最大文件系统尺寸为18 exabytes。

XFS使用高的表结构(B+树),保证了文件系统可以快速搜索与快速空间分配。XFS能够持续提供高速操作,文件系统的性能不受目录中目录及文件数量的限制。

传输带宽
XFS 能以接近裸设备I/O的性能存储数据。在单个文件系统的测试中,其吞吐量最高可达7GB每秒,对单个文件的读写操作,其吞吐量可达4GB每秒。

Red Hat不提供XFS支持,Red Hat认为XFS不够稳定。而Debian很早就提供了xfs支持。

在XFS上,很多任务的工作方式不同,包括设置配额,修复系统文件,甚至仅仅复制一个文件。这些不同的出现是因为XFS所带的功能。

分配组与可伸缩性
分配组是个重要功能,这让XFS成了可高度扩展的文件系统,它允许你存储大量文件和很大的文件。通过创建分配组,每个分配组管理自己的节点和自由空间,你可以确保多个进程和线程能够同时服务文件系统,这可以提高工作性能。

为了有效地处理文件,XFS选择了Ext4已经采用的盘区技术。一个区是可以当作一个单一实体的一组分程序来定址。好处是,与通过一个文件单独定址所有使用中的分程序相反,XFS只定址有限数量的区,这在定址大文件时更高效。

当创建 XFS 文件系统时,底层块设备被分割成八个或更多个大小相等的线性区域(region)。您可以将它们想象成“块”(chunk)或者“线性范围(range)”,但是在 XFS 术语中,每个区域称为一个“分配组”。分配组是唯一的,因为每个分配组管理自己的索引节点(inode)和空闲空间,实际上,是将这些分配组转化为一种文件子系统,这些子系统正确地透明存在于 XFS 文件系统内。

延迟分配
延迟分配是XFS的另一种实用功能。当文件初次创建时,其内容通常写入缓存区,然后它通常会刷新到磁盘。XFS会尽量等到最久才这样做,因为新文件创建后常会有很多修改。通过最大限度地延迟刷新文件到磁盘,文件系统优化了文件编写的方式,分配了尽可能多的连续块或区,防止过后文件系统破碎。

当延迟分配不是最优方案时,XFS有几个关于时间的选项。直接I/O选项保证一个文件不会在缓存区缓存,而是一确定就立刻写入磁盘。XFS专门提供一个保证速度的I/O,这保证了某些文件有一个最小I/O带宽。

XFS 通过将分配过程分成两个步骤来处理。首先,当 XFS 接收到要写入的新数据时,它在 RAM 中记录暂挂事务,并只在底层文件系统上 保留适当空间。然而,尽管 XFS 为新数据保留了空间,但 它却没有决定将什么文件系统块用于存储数据,至少现在还没决定。XFS 进行拖延,将这个决定延迟到最后可能的时刻,即直到该数据真正写到磁盘之前作出。

通过延迟分配,XFS 赢得了许多机会来优化写性能。到了要将数据写到磁盘的时候,XFS 能够以这种优化文件系统性能的方式,智能地分配空闲空间。尤其是,如果要将一批新数据添加到单一文件,XFS 可以在磁盘上分配一个 单一、相邻区域来储存这些数据。如果 XFS 没有延迟它的分配决定,那么,它也许已经不知不觉地将数据写到了多个非相邻块中,从而显著地降低了写性能。但是,因为 XFS 延迟了它的分配决定,所以,它能够一下子写完数据,从而提高了写性能,并减少了整个文件系统的碎片。

在性能上,延迟分配还有另一个优点。在要创建许多“短命的”临时文件的情况下,XFS 可能根本不需要将这些文件全部写到磁盘。因为从未给这些文件分配任何块,所以,也就不必释放任何块,甚至根本没有触及底层文件系统元数据。

日志记录
XFS 也是一种日志记录文件系统,它允许意外重新引导后的快速恢复。象 ReiserFS 一样,XFS 使用逻辑日志;即,它不象 ext3 那样将文字文件系统块记录到日志,而是使用一种高效的磁盘格式来记录元数据的变动。就 XFS 而言,逻辑日志记录是很适合的;在高端硬件上,日志经常是整个文件系统中争用最多的资源。通过使用节省空间的逻辑日志记录,可以将对日志的争用降至最小。另外,XFS 允许将日志存储在另一个块设备上,例如,另一个磁盘上的一个分区。这个特性很有用,它进一步改进了 XFS 文件系统的性能。

无处不在的B+树

分配组在内部使用高效的 B+ 树来跟踪主要数据,譬如空闲空间的范围和索引节点。实际上,每个分配组使用 两棵 B+ 树来跟踪空闲空间;一棵树按空闲空间的大小排序来存储空闲空间的范围,另一棵树按块设备上起始物理位置的排序来存储这些区域。XFS 擅长于迅速发现空闲空间区域,这种能力对于最大化写性能很关键。

当对索引节点进行管理时,XFS 也是很有效的。每个分配组在需要时以 64 个索引节点为一组来分配它们。每个分配组通过使用 B+ 树来跟踪自己的索引节点,该 B+ 树记录着特定索引节点号在磁盘上的位置。您会发现 XFS 之所以尽可能多地使用 B+ 树,原因在于 B+ 树的优越性能和极大的可扩展性。

规范详述

容量
XFS是一个64位文件系统,最大支持8exbibytes减1字节的单个文件系统,实际部署时取决于宿主操作系统的最大块限制。对于一个32位Linux系统,文件和文件系统的大小会被限制在16tebibytes。目录内容与文件分配均采用B+树。
最大文件尺寸    8 exabytes(减1字节)
最长文件名    255 bytes
最大卷容量    16 exabytes
文件名字符集    除NUL('\0')和 '/'以外的字节

日志
日志文件系统是一种即使在断电或者是操作系统崩溃的情况下保证文件系统一致性的途径。XFS对文件系统元数据提供了日志支持。当文件系统更新时,元数据会在实际的磁盘块被更新之前顺序写入日志。XFS的日志被保存在磁盘块的循环缓冲区上,不会被正常的文件系统操作影响。XFS日志大小的上限是64k个块和128MB中的较大值,下限取决于已存在的文件系统和目录的块的大小。在外置设备上部署日志会浪费超过最大日志大小的空间。XFS日志也可以被存在文件系统的数据区(称为内置日志),或者一个额外的设备上(以减少磁盘操作)。

XFS的日志所保存的是“逻辑”条目,以人类更加容易理解的方式来描述当前正在进行的操作(“物理”日志与其相反,保存的是每次操作中被修改的块)。日志的更新以异步的方式进行,避免影响整体性能。如果发生系统崩溃,可以根据日志中的记录来重做并完成崩溃的前一时刻发生的系统操作。崩溃之后首次挂载文件系统时,会自动进行恢复。恢复的速度不受文件系统大小的影响,取决于需要重做的系统操作的数量。对于最近被修改但未完全写入磁盘的数据,XFS保证在重启时清零所有未被写入的数据块,以防止任何有可能的、由剩余数据导致的安全隐患(因为虽然从文件系统接口无法访问这些数据,但不排除裸设备或裸硬件被直接读取的可能性)。

分配组
XFS文件系统内部被分为多个“分配组”,它们是文件系统中的等长线性存储区。每个分配组各自管理自己的inode和剩余空间。文件和文件夹可以跨越分配组。这一机制为XFS提供了可伸缩性和并行特性——多个线程和进程可以同时在同一个文件系统上执行I/O操作。这种由分配组带来的内部分区机制在一个文件系统跨越多个物理设备时特别有用,使得优化对底层存储部件的吞吐量利用率成为可能。

条带化分配
在条带化RAID阵列上创建XFS文件系统时,可以指定一个“条带化数据单元”。这可以保证数据分配、inode分配、以及内部日志被对齐到该条带单元上,以此最大化吞吐量。

基于Extent的分配方式
XFS文件系统中的文件用到的块由变长Extent管理,每一个Extent描述了一个或多个连续的块。与那些把文件所有块都单独列出来的文件系统相比,extent大幅缩短了列表。有些文件系统用一个或多个面向块的位图管理空间分配——在XFS中这种结构被由一对B+树组成的、面向Extent的结构替代了;每个文件系统分配组(AG)包含这样的一个结构。其中,一个B+树用于索引未被使用的Extent的长度,另一个索引这些Extent的起始块。这种双索引策略使得文件系统在定位剩余空间中的Extent时十分高效。

可变块尺寸
块是文件系统中的最小可分配单元。XFS允许在创建文件系统时指定块的大小,从512字节到64KB,以适应专门的用途。比如,对于有很多小文件的应用,较小的块尺寸可以最大化磁盘利用率;但对于一个主要处理大文件的系统,较大的块尺寸能提供更好的性能。

延迟分配
XFS在文件分配上使用了惰性计算技术。当一个文件被写入缓存时,XFS仅在内存中对该文件保留适当数量的块,并不立即给数据分配Extent。实际的块分配仅在这段数据被冲刷到磁盘时才发生。这一机制提高了将该文件写入一组连续块中的机会,减少碎片的同时提升了性能。

稀疏文件
XFS对每个文件提供了一个64位的稀疏地址空间,使得大文件中的“洞”(空白数据区)不被实际分配到磁盘上。因为文件系统对每个文件使用一个Extent表,文件分配表就可以保持一个较小的体积。对于太大以至于无法存储在inode中的分配表,这张表会被移动到B+树中,继续保持对该目标文件在64位地址空间中任意位置的数据的高效访问。

扩展属性
XFS通过实现扩展文件属性给文件提供了多个数据流,使文件可以被附加多个名/值对。文件名是一个最大长度为256字节的、以NULL字符结尾的可打印字符串,其它的关联值则可包含多达64KB的二进制数据。这些数据被进一步分入两个命名空间中,root和user。保存在root命名空间中的扩展属性只能被超级用户修改,user命名空间中的可以被任何对该文件拥有写权限的用户修改。扩展属性可以被添加到任意一种 XFS inode上,包括符号链接、设备节点、目录,等等。可以使用attr这个命令行程序操作这些扩展属性。xfsdump和xfsrestore工具在进行备份和恢复时会一同操作扩展属性,而其它的大多数备份系统则会忽略扩展属性。

Direct I/O
对于需要高吞吐量的应用,XFS实现了直接的I/O,允许未缓存的I/O操作直接应用到用户空间。数据在应用程序的缓冲区和磁盘间利用DMA进行传输,以此提供底层磁盘设备全部的I/O带宽。

确定速率I/O
XFS确定速率I/O系统给应用程序提供了预留文件系统带宽的API。XFS会动态计算底层存储设备能提供的性能,并在给定的时间内预留足够的带宽以满足所要求的性能。此项特性是XFS所独有的。确定方式可以是硬性的或软性的,前者提供了更高性能,而后者相对更加可靠。不过只要底层存储设备支持硬性速率确定,XFS就只允许硬性模式。这一机制最常被用在实时应用中,比如视频流。

DMAPI
XFS实现了数据管理应用程序接口(DMAPI)以支持高阶存储管理(HSM)。到2010年10月为止,Linux上的XFS实现已经支持DMAPI所要求的的磁盘元数据规范,但有报告称内核支持仍处于不稳定状态。此前SGI曾提供了一个包含DMAPI钩子的内核源码树,但这个支持未被合并进主代码树。不过现在内核开发者们已经注意到了它并对其做了更新。

快照
XFS并不直接提供对文件系统快照的支持,因为XFS认为快照可在卷管理器中实现。对一个XFS文件系统做快照需要调用xfs_freeze工具冻结文件系统的I/O,然后等待卷管理器完成实际的快照创建,再解冻I/O,继续正常的操作。之后这个快照可以被当作备份,以只读方式挂载。在IRIX上发布的XFS包含了一个集成的卷管理器,叫XLV。这个卷管理器无法被移植到Linux上,不过XFS可以和Linux上标准的LVM正常工作。在新近发布的Linux内核中,xfs_freeze的功能被实现在了VFS层,当卷管理器的快照功能被唤醒时将自动启动xfs_freeze。相对于无法挂起,卷管理器也无法对其创建“热”快照的ext3文件系统,XFS的快照功能具有很大优势。幸运的是,现在这种情况已经改观。从Linux 2.6.29内核开始,ext3, ext4, gfs2和jfs文件系统也获得了冻结文件系统的特性。

在线碎片整理
虽然XFS基于Extent的特征和延迟分配策略显著提高了文件系统对碎片问题的抵抗力,XFS还是提供了一个文件系统碎片整理工具,xfs_fsr(XFS filesystem reorganizer的简称)。这个工具可以对一个已被挂载、正在使用中的XFS文件系统进行碎片整理。

在线尺寸调整
XFS提供了xfs_growfs工具,可以在线调整XFS文件系统的大小。XFS文件系统可以向保存当前文件系统的设备上的未分配空间延伸。这个特性常与卷管理功能结合使用,因为后者可以把多个设备合并进一个逻辑卷组,而使用硬盘分区保存XFS文件系统时,每个分区需要分别扩容。到2010年8月为止,XFS分区不可以原位收缩,不过有一些方法可以变相处理这个问题。

原生备份/恢复工具
XFS提供了xfsdump和xfsrestore工具协助备份XFS文件系统中的数据。xfsdump按inode顺序备份一个XFS文件系统。与传统的UNIX文件系统不同,XFS不需要在dump前被卸载;对使用中的XFS文件系统做dump就可以保证镜像的一致性。这与XFS对快照的实现不同,XFS的dump和restore的过程是可以被中断然后继续的,无须冻结文件系统。xfsdump甚至提供了高性能的多线程备份操作——它把一次dump拆分成多个数据流,每个数据流可以被发往不同的目的地。不过到目前为止,Linux尚未完成对多数据流dump功能的完整移植。

原子磁盘配额
XFS的磁盘配额在文件系统被初次挂载时启用。这解决了一个在其它大多数文件系统中存在的一个竞争问题:要求先挂载文件系统,但直到调用quotaon(8)之前配额不会生效。

性能考量

写入屏障
XFS文件系统默认在挂载时启用“写入屏障”的支持。该特性会一个合适的时间冲刷底层存储设备的回写缓存,特别是在XFS做日志写入操作的时候。这个特性的初衷是保证文件系统的一致性,具体实现却因设备而异——不是所有的底层硬件都支持缓存冲刷请求。在带有电池供电缓存的硬件RAID控制器提供的逻辑设备上部署XFS文件系统时,这项特性可能导致明显的性能退化,因为文件系统的代码无法得知这种缓存是非易失性的。如果该控制器又实现了冲刷请求,数据将被不必要地频繁写入物理磁盘。为了防止这种问题,对于能够在断电或发生其它主机故障时保护缓存中数据的设备,应该以nobarrier选项挂载XFS文件系统。

日志的放置
XFS文件系统创建时默认使用内置日志,把日志和文件系统数据放置在同一个块设备上。由于在所有的文件系统写入发生前都要更新日志中的元数据,内置日志可能导致磁盘竞争。在大多数负载下,这种等级的竞争非常低以至于对性能没有影响。但对于沉重的随机写入负载,比如在忙碌的数据块服务器上,XFS可能因为这种I/O竞争无法获得最优性能。另一个可能提高这个问题的严重性的因素是,日志写入被要求以同步方式提交——它们必须被完全写入,之后对应实际数据的写入操作才能开始。如果确实需要最优的文件系统性能,XFS提供了一个选项,允许把日志放置在一个分离的物理设备上。这只需要很小的物理空间。分离的设备有自己的I/O路径,如果该设备能对同步写入提供低延迟的路径,那么它将给整个文件系统的操作带来显著的性能提升。SSD,或带有写回缓存的RAID系统是日志设备的合适候选,它们能满足这种性能要求。不过后者在遭遇断电时可能降低数据的安全性。要启用外部日志,只须以logdev选项挂载文件系统,并指定一个合适的日志设备即可。

缺点

XFS文件系统的卷无法被直接收缩,只能通过“备份->重灌->还原”的方式间接进行容量缩减(这也是云端主机供应商会告知存储空间只能增加不能缩减的其中一个原因),在准备多一组存储卷的情况下,有工具可对XFS卷进行上述操作:xfsdump和xfsrestore。历史上XFS上的元数据操作曾比其它文件系统都慢,表现为在删除大量小文件时性能糟糕。该性能问题是被Red Hat的XFS开发者Dave Chinner在代码中定位到的。使用一个叫“延迟记录”的挂载选项可以成数量级地提升元数据操作的性能。该选项几乎把日志整个存在内存中。Linux内核主线版本2.6.35中作为一个试验性特性引入了这个补丁,在2.6.37中使它成为了一个稳定的特性,并在2.6.39中把它作为默认的日志记录方法。早期测试显示在有少量线程的环境中其性能接近EXT4,在大量线程的环境下超过了EXT4。

缺少透明压缩的支持与校验保护,校验保护在对付静态型资料损毁方面有帮助。


XFS文件系统在数据的分布上主要划分为三部分:数据区(data section)、文件系统活动登录区(log section)、实时运行区(realtime section)。

1、数据区(data section)
数据区和我们之前的EXT系列文件系统一样,包含inode、block、超级块等。并且数据区和EXT文件系统中的block group概念类似,也是分为多个多个存储区组。此外,inode和block都是系统需要用到的时候才动态配置产生的,所以格式化的过程比EXT系列文件系统要快很多。

2、文件系统活动登录区(log section)
登录区域主要被用来记录文件系统的变化(和日志区域有些相像)。文件的变化会在这里记录下来,直到该变化完整的写入数据区后,该条记录才会被结束。如果文件系统因为特殊原因损坏时(断电等原因),系统会用登录区来进行检验,查看系统在意外关闭之前文件系统正在运行哪些操作。以快速的修复文件系统。

3、实时运行区(realtime section)
当有文件被建立时,XFS会在这个区段里找到一个或数个extent区块,将文件放置到这个区块内,等到分配inode和block完毕后,在写入到date section(数据区)的inode和block中。

XFS项目主页

XFS_FAQ