原文地址:http://www.programmer.com.cn/13200/
HFS+和UFS文件系统同时被引入早期的Mac OS X,随着若干年的发展,HFS+提供的功能已超越UFS,使其在Mac OS X 10.5之后成为成为唯一正式的Mac OS X系统,但因为其背负许多的历史包袱,为考虑兼容性,这些陈旧的设计并不能被推翻重来,所以苹果开始秘密研发下一代的文件系统。
UFS:经典的Unix文件系统
在Unix系统刚诞生的远古时期,文件系统被简单地称为FS。FS只包括启动块、超级块(处于硬盘分区开头用来保存文件系统信息)、inodes(索引节点)及数据。FS文件系统在Unix系统刚诞生时还能满足新老客户的需求,但随着科学技术的进步,FS已不能符合现代文件系统的需求,且会导致抖动等一系列问题。当时还是加州大学伯克利分校研究生,后成为著名BSD开发者Marshall Kirk McKusick在BSD 4.1b上承接传统的FS文件系统实现了FFS(Fast File System),妥善地解决了这一难题,把先前整块的磁盘文件系统分为小块,每块包含自已的索引节点和数据,因而增加了文件的局部性,减少了寻道时间。由于Marshall Kirk McKusick的FFS文件系统很好很强大,所以立即被各大Unix系统所使用。SunOS/Solaris、System V Release 4、HP-UX及Tru64 UNIX都使用它,也成为当今各BSD分支(FreeBSD、OpenBSD、NetBSD及DragonFlyBSD)的标准文件系统。每个不同的系统,无论开源与否,又会在FFS文件系统上增加各种扩展,这些扩展往往不互相兼容,但神奇的是,大家又都使用和原版同样的块大小和数据块宽度。因此在很大程度上,这些山寨版FFS文件系统又相互兼容,至少在一个操作系统上能对另一操作系统的文件系统执行只读操作。因此,FFS事实上已经成为Unix系统的标准文件系统,故它有了一个更广泛的称谓——UFS(Unix File System,即Unix文件系统)。
UFS在后来的若干年又取得了长足的发展。Sun公司在Solaris 7系统中,给UFS提供了简单的日志功能。日志文件系统指在档案系统发生变化时,先把相关的信息写入一个被称为日志的区域,然后再把变化写入主文件系统的文件系统。在文件系统发生故障(如内核崩溃或突然停电)时,日志文件系统更容易保持一致性,并且可以较快恢复。Marshall Kirk McKusick又实现了BSD一度引以为豪的Soft Update功能,来保证计算机掉电或系统崩溃时,通过使元数据按依赖顺序更新来确保磁盘上总的文件系统保持一致的实现机制。Soft Update的目标和日志类似,但实现代价比日志轻量许多。不过这项功能有所代价,主要是需要引入一个后台FSCK检查。
2009年,Jeff Roberson正式发表了对UFS的一项改进,为Soft Update加入了日志功能,并消除了对FSCK的依赖,这项改进最终集成进了FreeBSD 9中。TrustedBSD项目又为BSD分支的文件系统设计了ACL访问控制表功能(Access Control Lists)。先前,Unix文件系统的访问控制是非常简单的,其权限管理分为三个不同的类别:用户、同组用户以及其他用户,对每个类别,Unix文件系统提供读、写、执行三种权限的管理。这样的许可管理过于粗糙,无法指定某一用户访问的权限,也无法指定更为细致的权限内容(例如准许对一文件实行删除操作)。为解决这个问题,访问控制表被增加到文件系统中,使用以存取控制矩阵为基础的存取控制方法。存取控制串列描述每一个文件对象各自的存取控制,并记录可对此物件进行存取的所有主体对对象的权限。总之,UFS与时俱进,不断增加新的功能。
HFS+:更现代的HFS
作为Mac OS X的老祖宗NeXTSTEP,因为基于BSD,所以自然也使用UFS。而老版的Mac OS则使用一个叫做HFS的文件系统。HFS是一个比较古老且不思进取的文件系统,因此,在20世纪90年代末已不能满足当时的需要。在《Mac OS X背后的故事(一)》中我们提到,为了实现Mac OS的现代化,Copland项目被提出。Copland项目的子项目Sequoia旨在HFS的基础上,加入现代文件系统所必需的新功能,如大文件支持、Unicode文件名支持、长文件名支持、32位文件映射表支持等。Sequoia项目即成为后来熟知的HFS+,由Don Brady领导,这个团队先花了6个月时间把HFS项目原本的Mac使用的68K处理器汇编码改写成C代码,然后逐渐加入新功能。
后来由于Copland被力挽狂澜的Ellen Hancock给废了,所以一些有用的更新,如HFS+即被集成到Mac OS 8.1中。在Mac OS X诞生初期,HFS+和UFS文件系统同时被引入早期的Mac OS X中。不过由于HFS+根植Mac OS,缺乏Unix文件系统所必需的功能,如符号链接、硬链接及其他各种POSIX兼容性,所以HFS+开发组又花了一些工夫在不影响和Mac OS兼容性的情况下引入了这些功能。由于HFS+是对HFS的扩展,故HFS+支持Mac OS至Mac OS X的平滑过渡,所以Mac OS X一直默认使用HFS+。但当时的UFS提供比HFS+更先进的功能,因此Mac OS X 10.0至10.4,也都支持把系统安装在UFS系统上。
Mac OS X 10.0发布后,苹果不遗余力地对HFS+进行大规模的扩展和维护,增加了很多UFS独有的功能。这些新功能使得文件系统更加安全稳定可靠。例如Mac OS X 10.2.2中,HFS+支持日志。日志功能在Mac OS X 10.2服务器版中可以简单地设定,但在普通桌面版中需要使用命令行进行操作。在Mac OS X 10.3中,带日志功能的HFS+(被称为HFSJ,即HFS+ volume with journal)成为默认设置。Mac OS X 10.3亦增加名件名、目录名区分大小写及Unicode 3.2的支持。Mac OS X 10.4中,HFS+更是增加了ACL访问控制表功能,提供更复杂的对传统Unix文件系统权限的扩展。
文件系统除了让用户供稳定地存放文件这一目标以外,还是各项操作系统功能的基础。Mac OS X每个大发行版都要增加数百项新功能,许多新功能严重依赖于文件系统的实现。Mac OS X 10.3提供了FileVault来加密用户文件,因此用户主目录被保存在一个HFS+文件系统加密镜像中。Mac OS X 10.4提供了系统内置的Spotlight桌面搜寻搜索功能,能让用户对整个磁盘系统进行快速搜寻、随打即显。这项功能要求文件系统提供任意长度文件元数据(metadata)的支持。Mac OS X 10.4转向了对Intel处理器的支持,因此苹果发布了一个测试版本的BootCamp来让用户安装Mac OS X、Windows双系统,并在Mac OS X 10.5正式集成进系统。
哪怕在Mac OS X系统运行,BootCamp也可以在时调整系统主分区的大小,来空出磁盘空间给Windows,因此,HFS+又需要支持动态分区大小调整。在Mac OS X 10.5中集成了Time Machine,它是苹果公司所推出备份的工具程序,于2006年8月7日在苹果计算机全球研发者大会(WWDC)中首次公开,成为当天观众欢呼声最高的功能。Time Machine对于修改过的文件会在备份盘上保存一个新拷贝,而对于不变的内容,仅在备份盘上存一个指向先前文件的硬链接。因此每一次快照只保存改动的文件,而别的文件只保存占用空间很少的硬链接。但Unix一般只支持文件的硬链接而不支持目录的硬链接。因此HFS+在这点上走得比Unix文件系统更远,提供了对于目录的硬链接支持。在Mac OS X 10.6中,HFS+甚至支持文件系统压缩,使得安装后占用比Mac OS X 10.5少得多的空间。Mac OS X 10.7提出了FileVault2,能加密整个磁盘而不是一个用户目录。这些功能我们在为读者介绍每个发行版时亦会提到,但总之读者看到,HFS+的功能随着Mac OS X的商业需求不断被扩展。“我在做了这么多工作后回想才发现,我们为HFS+增加了那么多新功能,”苹果前文件系统开发者Don Brady如是说。
由于HFS+经过后来若干年的发展,提供的功能已不逊于UFS,甚至更多更好,故至Mac OS X 10.5砍掉了安装至UFS的支持。HFS+成为唯一正式的Mac OS X系统。
HFS+并不完美
HFS+自发布以来,几乎每个发行版都有令人欣喜的改动。它也逐渐成为一个非常完善的文件系统。但HFS+立足于HFS设计,HFS已有27年的历史,HFS+亦有14年历史。这个文件系统有大多的历史包袱,为考虑兼容性,这些陈旧的设计并不能被推翻重来。
HFS+基于B-树实现,当查找B-树中未使用的节点时,HFS+只能每次处理16位,原因是老Mac使用的Motorola的68K芯片原生支持16位的数据操作。但不管是PowerPC还是Intel,寄存器都支持256位宽的寄存器。
HFS+的元数据(metadata)都以大字节序保存,原因是Motorola的68k和后来Mac使用的PowerPC都使用大字节序。但经过Intel迁移后,当今的Mac都使用Intel芯片,而Intel芯片是使用小字节序的。因此每当数据读取或存入时,还要经过小字节序和大字节序的转换。远古时期磁盘很慢,计算机处理器的速度也很低,因此进行一次磁盘操作会占用较多的时间,HFS+的时间分辨率为一秒,但当今的磁盘、处理器处理一次文件系统操作的时间远小于一秒,因此所有主流磁盘文件系统的时间分辨率都是一至数百纳秒级别的。
HFS+的元数据有全局锁,同一时间只有一个进程可以访问更新文件系统。在单核处理器连手机平板都较少见到的当今,这种设计显得很幼稚。
HFS+亦没有稀疏文件的支持。例如我们在SQL中建立了一个数据库,SQL分配了10GB的文件给这个数据库,并且在文件头和文件尾写上一些字节的数据。而由于我们还没有给这个数据库添加新的数据,所以这10GB的文件除了头尾外其他字节都为0。现代的文件系统基本都支持稀疏文件,也就是说,当处理这个数据库操作时,事实上往磁盘写入的数据只有那文件头和文件尾的若干字节。而HFS+则需要把那些0也写上,因此会完整写入10GB的数据,耗费长得多的时间。
此外,HFS+不具备元数据校验功能、快照功能、写入时复制功能、就地执行功能、逻辑卷管理功能等很多现代磁盘系统所具备的功能,也不能动态调整文件块大小。这些功能的加入并不容易。
其中最要命的是,HFS+不像一些先进的文件系统,支持写入时复制事务模型,也没有快照和克隆。这使得用户数据时时处于风险之中。例如由于因为断电、内核崩溃等原因,文件系统上写到一半的数据,小则导致个别文件损坏,大则导致整个文件系统崩溃。在生产领域,这样不可靠的文件系统,很有可能带来致命的灾难。
正是由于上述这些原因,连我们介绍过的短视的Linus Torvalds都认为HFS+是个垃圾文件系统。苹果自然受不了这种侮辱,因此,干掉HFS+势在必行。用什么取代HFS+呢?苹果开始秘密研发下一代的文件系统。
由于各种缺点,干掉HFS+势在必行,然而用什么取代HFS+呢?苹果开始秘密移植下一代的文件系统—ZFS,然而在诸多因素的干扰下,Mac OS X的ZFS支持却只是昙花一现,未来文件系统之路将走向何方?
文件系统的新时代——ZFS
为了代替HFS+,苹果开始为研发下一代文件系统招兵买马,准备大干一场。但这时Sun公司的工作让苹果的员工们为之一振。
2004年,Sun公司发表了其杰出的文件系统ZFS。这是一个128位的文件系统,本为Solaris操作系统开发,于2005年10月31日并入了Solaris开发的主干原始码。后成为一个使用CDDL协议条款授权的开源项目。
ZFS是一个具有高存储容量、文件系统与卷管理概念整合、崭新的磁碟逻辑结构的轻量级文件系统,同时也是一个便捷的存储池管理系统。
ZFS的一个重大特点就是拥有大容量。ZFS是一个128位的文件系统,这意味着它能存储1800亿亿(18.4×1018)倍于当前64位文件系统的数据。ZFS的设计如此超前以至于这个极限就当前现实而言可能永远无法遇到。项目领导Bonwick曾说:“要填满一个128位的文件系统,将耗尽地球上所有存储设备,除非你拥有煮沸整个海洋的能量。”假设每秒钟创建1000个新文件,达到ZFS文件数的极限需要约9000年。
此外,ZFS的一个重要指导思想是不单单去做一个文件系统,而是实现一套完整的卷管理方案。不同于传统文件系统需要驻留于单独设备或者需要一个卷管理系统去使用一个以上的设备,ZFS建立在虚拟的被称为“zpools”的存储池之上。每个存储池由若干虚拟设备组成。这些虚拟设备可以是原始磁碟,也可能是一RAID1镜像设备,或是非标准RAID等级的多磁碟组。于是zpool上的文件系统可以使用这些虚拟设备的总存储容量。
有了卷管理方案后,ZFS走得更远,加入了快照和克隆等实用的文件系统功能。当ZFS写新数据时,包含旧数据的块被保留,磁盘只写入修改过的那部分数据块。所以快照的建立非常快,只存储两个快照间的数据差异,因此快照也是空间优化的。克隆指两个独立的文件系统共享一些列的块。当任何一个克隆版本的文件系统被改变时,只创建改动的数据块,因此非常快速,也占用少得多的空间。
而ZFS最大的贡献在于它是第一个支持写入时复制功能(COW,copy on write)的文件系统。所有文件系统中的块都包括256位的校验值。含有活动数据的块从来不被覆盖;而是分配一个新块,并把修改过的数据写在新块上。所有与该块相关的元数据块都被重新读、分配和重写。因此,当一个数据写入时发生了任何意外错误,原先的数据依然可以被访问,且文件系统知道哪个操作出了错误而没有完成。ZFS的快照和克隆正是因此项技术而得以实现。
ZFS对于用户而言,界面友好。先前Unix的卷管理非常烦琐,FreeBSD因此还建了一套宏伟的框架,给逻辑卷管理做深层次的抽象。而ZFS文件系统自带卷管理方案,几乎所有烦琐复杂的操作都能在一两条命令内完成,我用传统的卷管理工具已有近十个年头,第一次使用ZFS时,完全被其易用性震撼,所以我毫不犹豫地把手头所有的服务器迁移到了ZFS。
由于ZFS各种美好,加上其开源性质,所有的操作系统都想支持它。Solaris、OpenSolaris项目一直作为标准实现供其他系统参考。Pawe Jakub Dawidek把ZFS移到FreeBSD,并在2009年进入了FreeBSD 7,作为FreeBSD第七版最耀眼的三项功能之一(另一项功能是我们先前提到的ULE,以及Sun DTrace的移植工作)。NetBSD在2009年正式收纳ZFS。Linux则麻烦得多,因为Linux内核的协议GPL是个和很多协议都水火不容的奇葩协议,ZFS分发所采用的CDDL和GPL会产生冲突,所以一方面FUSE提供了用户空间层面的支持;另一方面,由Oracle牵头,专为Linux开发Btrfs,事实上就是一个ZFS的山寨版,可惜折腾了几年,Oracle自己又把Sun收购了,且到我撰写此文时Btrfs依然没有正式的稳定版本发布。
昙花一现的ZFS梦
刚才提到,苹果在招兵买马,雇员工开发新一代的文件系统,而Chris Emura(Apple CoreOS 的文件系统开发经理)及Don Brady(先前提到,此人领导HFS+的开发)两个富有经验的文件系统开发者却被衣服一样晾在了一边无所事事。2006年,刚刚提到的Pawe Jakub Dawidek正在往FreeBSD迁移Sun的ZFS,这项工作立刻引起了Chris Emura及Don Brady的高度兴趣。由于ZFS在Unix系统高度的可移植性,加上Mac OS X本就是FreeBSD的近亲,闲得发慌的两人立即打算往Mac OS X移植ZFS。在2007年4月6日,FreeBSD的移植宣告完成,等待合并进主干。一周后,两位苹果员工亦成功地完成了Mac OS X的移植。
苹果一看两人的ZFS的移植工作大有前途,立即跟进。2007年的苹果全球开发者大会上,苹果让Chris Emura及Don Brady举办了一场小型讲话,介绍Mac OS X对ZFS的支持。这场讲话先前并没有在官方声明中告示,但讲话的报告厅依然挤满了听众。随后ZFS移植的源码在Mac OS Forge公布。在最终版的Mac OS X 10.5带有试验性的ZFS只读支持,以命令行方式提供。用户可以挂载ZFS的存储池,并对池中的文件系统进行读取操作。
苹果一直使移植并使用Sun的关键技术,除了Java以外,Mac OS X 10.5的Xcode套件也加入了DTrace的支持,并提供了一个好用的图形界面Instruments让开发者更方便地调用DTrace。ZFS除了解决HFS+的所有问题,提供安全可靠的文件系统基础外,还可以简化苹果许多软件的实现。例如前文提到的Mac OS X 10.5的Time Machine,实现颇为烦琐,依赖于给HFS+提供新功能,功能层也需要增加很多的和备份相关的代码。而ZFS默认就支持快照,将大大简化Time Machine的实现,并使该功能更稳定可靠。事实上在2008年11月25日,Sun发布了OpenSolaris 2008.11版,其中给GNOME的Nautilus增加了一个使用ZFS的快照功能的图形界面插件名为Time Slider,和苹果的Time Machine提供了非常相近的功能,我在使用后感觉不错。
因此在WWDC 2008上,Snow Leopard被提出,其中一项很重要的卖点就是对ZFS的完整的读写支持。在Mac OS X的服务器版,苹果也将提供一套图形界面工具来方便维护人员管理ZFS存储池。在当时的Snow Leopard Server主页上,苹果声明ZFS将作为一项主推功能。
但好景不长,一年后的苹果开发者大会时,ZFS相关的内容被悄悄从任何公开的文档、网站、发布会中撤下,没有给出任何的理由。Mac OS Forge上的ZFS代码和页面也被苹果移除。外界有很多对此的猜测,但没有任何猜测得到苹果官方的或是哪怕离职员工的证实。
猜测之一是当时Sun刚被Oracle收购,而Oracle长期投资ZFS的竞争产品Btrfs。因此苹果觉得ZFS的前途不甚明朗。
猜测之二是ZFS的关键技术Copy On Write有专利问题,NetApp声称他们拥有COW的专利因此在起诉Sun,苹果不想在当中冒风险。
猜测之三是ZFS和苹果的XNU内核有协议冲突。我虽然不学法律,但我认为这个说法不完全对,因为ZFS和DTrace一样,是以CDDL发布的开源软件,既然DTrace可以无后顾之忧地加入到XNU中,ZFS也没有理由不可以。事实上,除了Linux这种少数使用GPL这类奇葩协议的内核,大多数系统的协议都不和CDDL冲突。FreeBSD也好,Mac OS X 10.5也罢,都把ZFS加入内核发布。
但事实上,如果把三种猜测并在一起,我们可以看到一个更全局的可能性:对于猜测之二,苹果可能并非想使用CDDL,而是想从Sun买下一个私有的协议,这样一来,Sun不但提供更好的技术支持,出了问题(比如猜测二中的专利问题)也可以让Sun为自己背黑锅。结果Sun可能和苹果价格谈不拢,加上猜测之一提到的Sun大势已去,让苹果觉得还不如自己造个*来得方便。Sun公司开发ZFS的主力Jeff Bonwick虽不能提供详细的信息,但他基本证实了这种说法。
无论如何,Mac OS X的ZFS支持,如昙花一现般消失了。
未来文件系统之路走向何方
虽然Mac OS X的ZFS支持被砍了,开源社区依然想继续开发Mac OS Forge先前版本的移植。如MacZFS项目不遗余力地给Mac OS X 10.5~10.7提供ZFS读写支持。Don Brady在苹果将对ZFS的支持砍掉之后从工作了20多年的苹果离职,开了一家名为Ten’s Complement的公司,该公司提供Z-410,较MacZFS提供更新更稳定的移植。
不过,砍了ZFS后的苹果目标也变得更清晰—和Sun的谈判让苹果觉得与其支付高额的协议费,还不如雇人自己做个新的,再说了,作为比Sun大得多的IT公司,苹果可以轻而易举地搞个更强大的东西灭了它,因为ZFS其实也不如传说中的那样好。
首先,时代在进步。ZFS之后,又有很多新的和文件系统相关的研究,如Ohad Rodeh的论文,即成为后来BtrFS实现的基础,可能比ZFS做得更好。
其次,ZFS是十年前开始设计的文件系统,但十年中,存储工具已发生了重大的变化。ZFS为传统磁盘设计,但传统磁盘的市场空间已不断被SSD、闪存的吞食。尤其是MacBook Air中使用的Flash存储器便宜好用又小巧,可能将来会在MacBook Pro甚至iMac中得到更大的推广。采用为传统磁盘优化的ZFS就不显得那么有吸引力。
最后,ZFS和苹果有不同的用户群。ZFS目标用户是大企业的工作站和服务器。在那里,大容量的存储空间、高级的卷管理显得非常重要,但苹果面对的基本都是个人用户—先前苹果还卖服务器,但后来Xserve都被苹果砍了。有几个个人用户需要使用到ZFS这些高级的功能呢?更重要的,苹果的主要利润将移到iPhone、iPod、iPad、Apple TV这些小设备上,ZFS需要占用大量的内存来实现文件系统操作,在这些小设备上,内存很少,ZFS根本跑不起来。
苹果非常清楚这些问题,工程师们现在一定在紧锣密鼓地开发下一代文件系统。在10.7及10.8中,这套文件系统并未浮出水面,但一些细节值得留意。在10.7中,苹果发布了Core Storage,但并未声张。这是一套逻辑卷管理工具,类似于前文提到的FreeBSD的GEOM。这个版本的File Vault 2亦使用Core Storage重写。可以看到虽然苹果在上层不断地淡化文件系统的概念,例如iCloud的发布和iOS中对于文件这一概念的故意忽略,但苹果在底层文件系统上的动作越来越大,想必在将来,苹果定会让我们感到重大的惊喜。
作者王越,美国宾夕法尼亚大学计算机系研究生,中国著名TeX开发者,非著名OpenFOAM开发者。