jinyuliang 发表于 2009-08-06 11:34

btrfs 简史——中译、LaTeX源码


                                               
                                       
                                       
MARK一下留作纪念:
两天的成果:第一篇象样的 LaTeX 文档,学会了最基本的文档编辑和最基础的图文混排方法,顺便练习了拙劣的英语,还熟悉一下 btrfs 这个文件系统。
==============华丽丽的分割线===============
目录:
1、源代码
2、文档中的三幅图片
3、Makefile
4、生成的PDF文档
==============华丽丽的分割线===============
% 文件名:btrfs.tex
% btrfs简史中译,英文原文在:http://lwn.net/Articles/342892/
% 原作者:Valerie Aurora
% 译者:Yuliang
% 声明:翻译本文纯属自娱自乐,如有误导或帮助纯属巧合,请慧眼明辨。
% 2009-08-06
\documentclass{article}
\usepackage{CJKutf8}
\usepackage{wrapfig}
\usepackage{graphicx}
\usepackage{hyperref}
\hypersetup{
   colorlinks,
   citecolor=green,
   filecolor=magenta,
   linkcolor=red,
   urlcolor=blue
}
\usepackage{indentfirst}
\begin{document}
\begin{CJK}{UTF8}{gkai}
   
\title{btrfs 简史}
\author{作者:Valerie Aurora译者:Yuliang}
\maketitle
   
\begin{abstract}
这篇文章中,我们将要从技术、时事、个人等多个层次上,深入幕后对 btrfs 的设计和发展进行检视,跟踪它从一个实验室中的原型发展到目前
Linus 大神的根文件系统这个地位的脚步。了解每一步发展的背景和动机将使你更好的理解 btrfs 的产生、工作方式以及未来的发展前景。
\end{abstract}
   
\section*{\small译者的话:}
\small本人英语其实很差,六级尚不知通过与否,但优点是脸皮较厚,也曾斗胆翻译过\href{http://blog.chinaunix.net
/u2/68417/article.php?frmid=96790}{《RHCE5学习指导》的第13章}。这次翻这个短文,一是想了解一下
btrfs,二来可以熟悉一下英语,第三还可以练习一下 LaTeX 的用法,最后还能打发暑假的无聊时光。本人对于 btrfs 、 LaTeX
以及英语本身的认知均有限,而且是出于纯粹自娱自乐,信达雅三个原则均未曾认真参考,如果有任何不足甚至错误,还望见谅并不
吝\href{mailto:jyl198803@gmail.com}{批评指正}。
   
\section*{原文内容:}
\normalsize也许你听说过文件系统家族这个酷酷的新秀,\href{http://btrfs.wiki.kernel.org/}
{btrfs} (发音为:butter-eff-ess),毕竟 Linus Torvalds
就在他的一个笔记本中使用它,将它用作根文件系统。但是,下面这几个和它有关的高级关键词,你可能就知之甚少了,如写时拷贝、校验和、可写快照,以及另外
一些耸人听闻的谣言和传闻 --
\href{http://www.phoronix.com/scan.php?page=article&item=btrfs_benchmarks&num=1}{Phoronix
的基准评测},仿 ZFS 的假货,甲骨文公司为统治 Linux
世界制定的秘密计划等等。对于一个文件系统来说,很难将事实从谣言和恶意中伤中剥离出来:它的代码过分复杂,对它的批评过分夸大其词,丢了数据的用户通常
过分愤怒。你甚至无法从五花八门的评测大战中作出正确判断,因为文件系统工作量的差异是如此之大,无论是想证明一个评测是完全不着边际的还是想证明它是非
常有说服力的,你都可以轻易作出看似合理的论辩。
   
这篇文章中,我们将要从技术、时事、个人等多个层次上,深入幕后对
btrfs 的设计和发展进行检视,跟踪它从一个实验室中的原型发展到目前 Linus
大神的根文件系统这个地位的脚步。了解每一步发展的背景和动机将使你更好的理解 btrfs
的产生、工作方式以及未来的发展前景。最后,你应该能够通过这个对 brtfs 磁盘格式的描述得出你自己的结论。
   
\subsection*{免责声明:}
我有两点需要声明:第一,我在 Sun 公司为 ZFS 工作了许多年。第二,我已经多次因为 Sun/NetApp 各种各样的专利诉讼被传讯和免职,我希望避免再次给他们任何传讯我的理由。我将尽力保持公平、诚实以及严谨和公正。
   
\subsection*{btrfs:前传}
想象你是一个 Linux 文件系统的开发者,现在是 2007 年,你参与了
\href{http://www.usenix.org/event/lsf07/}{Linux 存储和文件系统工作组}。Linux
文件系统的前景看起来晦暗不明:被性能问题和不可靠资金模式困扰的 Reiserfs 在 Hans Reiser
身陷囹圄几个月至后几乎失掉了所有的信任;ext4
仍然在开发当中,事实上它现在甚至\href{http://lkml.org/lkml/2006/6/28/454}{称不上是
ext4},从根本上讲,ext4 只是一个30岁高龄文件系统的简单延伸而已,而且在许多特性的竞争中落后甚远。同时,许多公司也正在收缩对
Linux 开发的资金投入。IBM 的 Linux
部门也告别了他的鼎盛时代,到了需要展示他们收益能力的时候了。其他公司也受到即将到来的经济衰退影响,全面缩减研发开支。他们以月为单位衡量项目结束的
时间,而不是年。
   
然而尽管如此,始终充满希望的文件系统开发者们仍旧在不懈努力。自从工作组同
\href{http://www.usenix.org/event/fast07/}{USENIX FASR '07}
合作,许多来自学术界和工业界的研究者都向工作组呈送了他们的新理念。其中之一就是 Ohad
Rodeh,他发明了一种\href{http://www.cs.tau.ac.il/~ohadrode/papers
/btree_TOS.pdf}{能够友好实现写时拷贝的B树}。一开始,\href{http://en.wikipedia.org
/wiki/B-tree}{B树}的原生形式与写时拷贝技术十分不相容,树的叶子是链接在一起的,所以当一个叶子的位置改变(经由一个写动作,写动作将
使该簇进行一次拷贝),相邻叶子的链接就会改变,这又触发了另一个写时拷贝动作和位置改变,接着改变了下一个叶子的链接...最终的结果是,每一次一个叶
子改变,整个B树从头至尾都必须被重写。
   
Rodeh
的B树与之不同:首先,他除去了叶子之间的链接,但也保留了许多有用的B树的特性(这是一个文件系统中B树的十分标准的形式,有时也称作B+树),正如他
在他的
\href{http://www.cs.huji.ac.il/~orodeh/papers/LinuxFS_Workshop.pdf}
{slides}中所说的那样,这个举动扔掉了许多现存的B树文献。他为利用"引用计数"的B树遍历法添加了一些算法,限制了删除一个快照时必
须遍历的树的总数,同时,他也添加了一些其他特性,例如积极分割和合并内部结点,因而插入和删除并不需要任何回溯。结果他创造了一个简洁、健壮、通用的数
据结构,高效地追踪了一个写时拷贝文件系统中的"范围"(一组相关连的数据块)。几年后 Rodeh
成功地做出了这个系统的原型,但是他只在研究领域实现了系统,并且希望别人能够接管他这个适用于写时拷贝的B树并让它们更有用。
   
\subsection*{btrfs:开端}
Chris Mason 接管了这些B树,并且发展了它们。那时,Chris 从事于 Reiserfs
的研发,在那里他学到了在一个文件系统中,什么是需要做的,什么事不能做的。Reiserfs
包含了许多很酷的新特性,包括小文件包,能快速查找的B树,灵活部署等,但是它的实现却倾向于杂乱和专有,导致代码路径和潜在的漏洞都在激增。
   
Chris
很有洞察力地想到:如果文件系统中的任何东西,包括i结点、文件数据、目录项、位图以及结构等,都统一为写时拷贝B树中的一个项如何?这样所有的读写存储
动作都会通过相同的代码路径完成,你只需将这样的项填入B树的结点,而不必去理解也不必关心项的类型。因此你只需编写一次代码,就能够获得一个文件系统的
许多特性,如校验和、引用计数(做快照时)、压缩、信息分段等。
   
因此 Chris 提出了下面的
\href{http://btrfs.wiki.kernel.org/index.php/Btrfs_design}{btrfs
基础结构}(btrfs 一词表示 btree file system)。Btrfs 包含三种磁盘结构:簇首部(block
header)、键(keys)和项(items),目前的定义如下:
   
\begin{verbatim}
   struct btrfs_header {
         u8 csum;
         u8 fsid;
         __le64 blocknr;
         __le64 flags;
   
         u8 chunk_tree_uid;
         __le64 generation;
         __le64 owner;
         __le32 nritems;
         u8 level;
   }
\end{verbatim}
   
\begin{verbatim}
   struct btrfs_disk_key {
         __le64 objectid;
         u8 type;
         __le64 offset
   }
\end{verbatim}
   
\begin{verbatim}
   struct btrfs_item {
         struct btrfs_disk_key key;
         __le32 offset;
         __le32 size;
   }
\end{verbatim}
   
在B树的内部(就是说在树的枝上,与在树底部的叶上相反),结点只包含键(keys)和簇首部(block headers)两项。键告诉你需要到哪里去查找你需要的项,簇首部则告诉你树的下一个结点或叶子在磁盘上的位置。
   
\begin{wrapfigure}{r}{3.5cm}
\includegraphics{btrfs-block.png}
\end{wrapfigure}
\mbox{}树的叶子包含了项(items),这是键和簇首部的结合体。和 reiserfs
相同,项和数据以一种及其节省空间的方式组织起来:项首部(即上面描述的项结构)被打包起来从前至后向簇中存放,每个项相关的数据则打包起来从后向前存入
簇中。因此项首部和数据相向增长,如右图所示。
   
\mbox{}除了编码的高效性,这样的构成同样提高了空间和时间的效能。通常,文件系统在任何给定的文件系统簇中只放置一种数据,或者位图或者i结点或
者目录项。这样浪费了磁盘空间,因为一种类型的簇中未使用的空间就再也不能用做存储其他类型数据了,也加剧了时间消耗,因为获取一个特定文件的数据需要需
要读许多不同类型的元数据,而不同的元数据则存放在文件系统中不同的簇上。在 btrfs
中,项被打包在一起(或者外推到叶子上去),整理好的项优化了存取时间和磁盘空间的占用。你可以在下面这些直观简洁的图中看到这些不同点。
   
旧式风格的文件系统倾向于这样组织数据:
\begin{figure}[!htb]
\centering
\includegraphics{oldskool.png}
\end{figure}
   
Btrfs 则与之不同,它的磁盘规划类似下图所示:
\begin{figure}[!htb]
\centering
\includegraphics{newskool.png}
\end{figure}
   
在上面两个图中,红色块表示浪费了的磁盘空间,红色箭头表示查找的动作。
   
文件系统中的每种元数据和数据都作为一种特定类型的项存储着,包括目录项、i结点、扩展属性以及文件的数据本身。如果你回头去看一个项(item)的定义,你会发现它的第一个元素是一个键:
   
\begin{verbatim}
   struct btrfs_disk_key {
         __le64 objectid;
         u8 type;
         __le64 offset
   }
\end{verbatim}
   
让我们从 objectid 域开始吧。文件系统中的每一个对象(一般会是一个i结点)都有一个唯一的
objectid。这是一个非常标准的作法,它也和 inode 编号是等价的。令人感兴趣的是,objectid
设置了一个项目的主键中最重要的位,就是我们用来在B树中查找该项的位,并且objectid 的最低几位就是与该 objectid
相关的类型。这样就将与特定 objectid 相关的所有信息组合到了一起。如果你分配相邻的几个 objectid,那么所有这些
objectid 中的项目都将被分配。和普通的文件系统中处理方法不同,对会自动地把距离近的相关数据组合到一起,而不关心数据的实际内容,普通的文件系统则分别为每种类型的数据写入优化的分配符。
   
type 域描述了这个项中存储的是什么类型的数据。它是i结点吗?还是目录项或者是一个描述数据在磁盘上位置的扩充?还是它就是数据本身?无论如何,通过它和 objectid 的组合,你就可以找到这个B树中任何你需要的文件系统数据。
   
我们首先应该对B树的结点和叶子的结构做一个快速的浏览。每一个结点或者叶子都是B树的一个扩充,结点是包含整个对的扩充,叶子则包含了项。大文件的数据和描述其对应扩充的数据项都被存储在B树之外,这些扩充描述的就是B树内的叶子。(大文件的
构成很优美地基于文件系统的工作量。)每个描述了一部分B树的扩充都有一个校验和和引用计数,这使得可写快照成为可能。每一个扩充也都清晰的包含了涉及到
它的所有其他扩充的反向引用。
   
反向引用给 btrfs
带来了一个重要的可以使它凌驾于其他文件系统之上的优良特性。我们现在可以快速高效地移动数据,可以增量地校验和修复文件系统,可以通过普通的操作检查引
用计数的正确性。事实上,btrfs
目前已经支持了快速有效存储设备的移除和压缩。许多其他的文件系统都将"可压缩文件系统"作为特性列出来,但是它们通常都走入没有应用效率、慢速或者落后
许多年的结局,甚至最终销声匿迹。例如,通过遍历整个文件系统寻找已被删除设备中的的数据,ext3/4
可以压缩文件系统,但这是一个缓慢、困难重重并且容易滋生漏洞的过程。ZFS
则尚\href{http://bugs.opensolaris.org/view_bug.do?bug_id=4852783}{不能压缩文件系
统}。
   
结论是非常优美和雅致的:磁盘上的任何事物都是一棵B树,包含引用计数、有校验和的扩充项,而这些扩充项则由键组成。大量 btrfs
的代码丝毫不关心项目中存储的是什么,它只知道如何将它们添加一个B树上或者将他们从树上删掉。优化磁盘布局也非常简单:键相似的东西放在一起就行了。
   
\subsection*{btrfs:时事}
当 Chris 钻研 btrfs 的技术设计时,他同时也在考虑如何为这个文件系统短期和长期发展筹备所需的资金。Chris 那时刚刚从 SUSE
转移到甲骨文公司的一个 Linux 精英小组,这个小组中汇聚了许多高水平的 Linux 存储技术开发者,其中就包括了 Martin K.
Petersen,Zach Brown和Jens Axboe。甲骨文资助了许多 Linux
项目的开发,其中一些明显地和甲骨文的数据库业务相关(OCFS2,
DIF/DIX),另一些则关系不大(通用簇分配机制,通用非同步系统调用支持syslets)。下面的对话是最近 Chris 与
\href{http://www.linux-foundation.org/weblogs/amanda/}{Linux 基金会的
Amanda McPherson}
一次\href{http://www.linux-foundation.org/weblogs/amanda/2009/06/22/a-
conversation-with-chris-mason-on-btrfs-the-next-generation-file-system-
for-linux/}{会晤}的内容:
   
\begin{tabular}{cl}
\\
Amanda:&\parbox{8cm}{你是出于什么原因启动这个项目的呢?为什么甲骨文公司如此支持这个项目?\\}
\\
Chris:&\parbox{8cm}{我加入甲骨文公司以后很快就投入了 btrfs 的开发。我有一个无与伦比的机会去深入窥探
Linux 遗漏的特性,并且感到 Btrfs 是最佳的解决办法。\\Linux
对甲骨文公司来说是一个非常重要的平台。我们在公司内部操作中频繁使用它,而且对我们而言它拥有一个广泛的用户基础。我们希望能够将 Linux
存储作为一个数据为中心的操作系统保留下来,而且数据存储的革新是甲骨文公司应该贡献的分内之事。\\}
\\
\end{tabular}
   
换句话说,甲骨文公司希望将 Linux
作为一个平台,并且愿意为它的开发活动投资,尽管它与甲骨文的数据库工作并无直接关系。这样来分析:有多少操作系统大部分是被你的竞争对手编写和控制的?
这时拥有一个完全在自己控制之中的操作系统该是多么的诱人,就像 Solaris
一样。当然这也意味着你必须为这个平台的大部分开发埋单。最终,甲骨文相信,使用他们自己的专门技术来帮助 Linux
存储技术的发展是符合自己的兴趣的。
   
经过几个月和 Zach Brown 等人的深入分析和设计,Chris
\href{http://lkml.org/lkml/2007/6/12/242}{释出了 btrfs
的评估版}。从那时起,你就可以向跟踪其他开源项目一样,通过邮件列表和代码演变追踪 btrfs 的发展了。Btrfs
现在已经在内核代码主线中了,而且来自Red Hat、SUSE、Intel、IBM、HP、Fujitsu等许多地方的开发者也在研究它。Btrfs
是一个真正的开源项目,不仅指它的授权许可,也指它的开发社区。
   
\subsection*{btrfs:和 ZFS 的简单对比}
人们经常问及有关 btrfs 和 ZFS
关系的问题。从某些方面讲,这两个文件系统非常的相似:它们都是写时拷贝有校验和的文件系统,支持多种设备,并且都支持可写快照。从另外一些方面讲,它们
又十分不同:如文件系统结构、开发模式、成熟度、授权许可、宿主操作系统以及其他许多方面。与其单独回答每个问题,我宁愿在这里给出一个 ZFS
开发简史,并且在几个关键的地方对比一下 btrfs 和 ZFS 两者。
   
当 ZFS 项目开始的时候,Solaris
中文件系统的前景也是晦暗不明的。按照文件系统的大小和性能来讲,带日志功能的 UFS 已经接近寿命的尽头。UFS 的极度落后导致 Solaris
的用户为 Veritas 公司支付大量的金钱来运行 VxFS。Solaris 需要一个新的文件系统,十分迫切的需要。
   
Jeff Bonwick 决定来解决这个问题,他在 Sun 公司启动了 ZFS
项目。它的灵感来自于虚拟内存子系统,为什么磁盘不能像内存那样管理和使用呢?核心的磁盘数据结构是slab,一大块磁盘分割成两个相同的块,就像同样是
他创造的 \href{http://en.wikipedia.org/wiki/Slab_allocation}{SLAB
内核存储分配}中所作的那样。ZFS 使用每一簇一个簇指针来替代 btrfs
使用的扩充,但是每一个对象都可以根据对象的大小来使用不同的簇大小,例如 512 字节或者 128K
字节。簇地址通过一个类似于虚拟内存的机构进行转换,因此簇不需要了解上层的细节就能被重定位。所有的文件系统数据和元数据都可以保存在对象之中,所有对
文件系统的改变都可以用一系列对象的改变来描述,而对象则可以使用写时拷贝的风格进行写动作。
   
简单来说,btrfs
将磁盘上所有东西都组织到包含项和数据的扩充组成的一个B树上去;ZFS
则将磁盘上所有东西都组织到一个包含簇指针的树上,并且簇大小取决于对象的大小。btrfs 对扩充计算校验和并且引用计数;ZFS
则对大小动态变化的簇计算校验和并且引用计数。两个文件系统都使用写时拷贝技术进行数据改变的回写,无论是正在使用的扩充还是正在使用的簇都从不会被覆
写,它们永远会先被拷贝到别的地方。
   
所以,尽管这两个文件系统的特性列表看起来非常相似,它们的实现却完全的不同。这和\href{http://txtwriter.com
/Backgrounders/Evolution/EVpage14.html}{有袋动物与胎盘哺乳动物的趋近进化}(有袋的老鼠和胎盘的老鼠外表看
起来十分相近,但是它们的内部构造却相去甚远)有些相似之处。
   
我认为,btrfs 的基础架构比 ZFS
更适合于数据存储。ZFS
途径,就是特定大小簇构成大块这种方法,存在的一个主要的问题就是碎片问题。每一个对象只可以包含一种大小的簇,每一个大块只能包含一种大小的簇。你很容
易遇到诸如下面的问题,由 64K 的簇构成的文件需要增加一个簇时,恰好没有 64K 的簇可以用了,尽管文件系统中有的是空的大块,但它们只包含
512 字节的簇、4K 的簇或者 128K 的簇等等。为了解决这个问题,ZFS 的开发者们发明了许多类似于小块聚合成大块("gang
blocks")这样另人感到不舒服的权宜之计。当然,我们还要看到,在B树和扩充看起来还和写时拷贝技术非常不和的时候,这个来自虚拟内存的灵感在许多
方面工作得很好。
   
相比而言,B树中包含项这个解决方案空间有效性和灵活性都非常好。它的碎片整理是一个持续进行的过程,高效地将项目重新打包的代码仅仅是平时准备磁盘写动
作的普通代码的一部分;基于每个扩充的校验和、引用计数以及其他各种各样的元数据操作减少的开支,并且使得添加新的特性(例如扩充到所有与它相关的事物的
快速反向映射)成为可能。
   
接下来是一些个人的预测(纯粹基于公开的信息,我并没有任何的内幕消息)。Btrfs
将在两年内成为 Linux 的默认文件系统。Btrfs
项目不会(也不能)被甲骨文公司叫停。如果所有的智力资源被用光(一个很飘渺的如果),ZFS 将被移植到 Linux
系统中去,但是它也不会侵占已大下根基的 btrfs 很多份额。两年后再回头看吧,看我是否预言得准确。
   
\subsection*{btrfs:未来}
Btrfs 当前头衔为 1.0
版,仅仅比两年前刚刚发布时高了一点。但这已经比许多文件系统开发的老兵,包括我自己,预期的要快的多了,特别是考虑到绝大多数的时候,btrfs
只有一个全职的开发者。Btrfs
还不适用于生产用途,就是说它还不适合于存储和服务于重要的数据,但是它已经可以做普遍的测试了,例如在你每晚都会备份的膝上电脑中,或者在你试验性的上
网本中,你无论如何都会每几周就重装系统的那种机器。
   
注意到最近一个关于 btrfs 磁盘格式的重要事件:2.6.30
释出以后不久,一个决议以一种不兼容旧内核的方式改变了磁盘格式。如果你使用旧的内核和相关工具创建了 btrfs 文件系统,例如 2.6.30
或者更早的版本,并且使用新的磁盘格式启动到了一个新的内核下,那么你将不能再在旧的内核下使用这个文件系统了。Linus Torvalds
也是\href{http://www.mail-archive.com/linux-btrfs@vger.kernel.org
/msg02500.html}{很艰难地发现了这一点}。但是如果这种事的确在你身上发生了,不要惊慌,你可以在 btrfs 的 wiki
上找到\href{http://btrfs.wiki.kernel.org/index.php/Rescue_me}{恢复镜像和其他有用的信
息}。
   
\end{CJK}
\end{document}
==============华丽丽的分割线===============
编译源码需要的三个图片:
btrfs-block.png
http://blog.chinaunix.net/photo/68417_090806112631.png
oldskool.png
http://blog.chinaunix.net/photo/68417_090806112642.png
newskool.png
http://blog.chinaunix.net/photo/68417_090806112733.png
=============华丽丽的分割线===============
Makefile——到处都能用得到make这个命令:
PDFC = pdflatex
READER = xpdf
   
TARGET = btrfs.pdf
OUTGROWTH = *.out *.log *.aux
SOURCE = btrfs.tex
FILES = btrfs-block.png oldskool.png newskool.png
   
$(TARGET): $(SOURCE) $(FILES)
   $(PDFC)    $(SOURCE)
   
read:
   $(READER) $(TARGET)
   
clean:
   -rm $(TARGET) $(OUTGROWTH)
   
.PHONY:clean read
==============华丽丽的分割线===============
需要源代码文件btrfs.tex和上面三个图片:btrfs-block.png、oldskool.png和newskool.png。
命令:
make
生成btrfs.pdf
make read
阅读,效果还不错:
http://blog.chinaunix.net/photo/68417_090806112900.png
                               
               
               
               
               
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/68417/showart_2019561.html
页: [1]
查看完整版本: btrfs 简史——中译、LaTeX源码