BTRFS - A Forest,extent分配树,同步与并发

简介: 介绍Btrfs如何由树木森林构成。

一、A Forest

文件系统由树木森林构造(a forest of trees),超级块定位在一个固定的磁盘位置。它指向一个树的根树节点,该节点索引构成文件系统的b树。The trees are:

Sub-volumns:存储用户可见文件和目录。每个子卷有一个单独的tree实现。子卷可以被快照和克隆,创建额外的b-trees。The roots of all sub-volumes are indexed by the tree of tree roots.

Extent allocation tree: 跟踪在extent items中已分配的extents,且为磁盘上的free-space映射服务。 所有的extent的back-reference被记录在extent item中。需要的话,这个允许移动一个extent,或者从一个损坏的磁盘块中恢复。back-reference将磁盘引用指针的数目乘以2。对每个向前的指针,就确信的有一个向后的指针。

Checksum tree: 对每个已分配的extent维护一个checksum。在extent的每个page中item包含一系列的checksums。

Chunk and device tree:处理物理设备的间接层。允许镜像/条带化和RAID。

Reloc tree: 涉及移动extents的特殊的操作。

举个例子:下图展示了一个特殊文件系统的高级的结构。为了简单reloc和chunk trees被忽略。

image.png

下图展示了用户写文件系统之后发生的改变。

image.png

绿色的是被修改的页。

修改用户可见的文件和目录会引起pages和extents的更新。这会波及到子卷树知道它的根。 改变也会发生在extent 分配, ref-counts 和 back-pointers。这会波及extent 树。数据和元数据校验改变,这些更新修改了校验树叶子,引起修改产生涟漪效果。

所有这些树的修改都将作为树根树中的新根在最顶层在顶层被捕获(at the top most level as a new root in the tree of tree roots),修改在内存中是加速的,且在一个超时之后,或者充足的paes改变,以块的形式写道磁盘的新。位置,构成一个checkpoint检查点。默认的超时时间是30秒。一旦检查点被写,超级块被修改指向新的检查点;这是唯一一种修改磁盘块的情况。如果发生了crash,文件系统通过读取超级块恢复,且follow指针到上一个有效的磁盘检查点。当一个检查点被初始化,所有的脏的内存数据都被标记位不可变的。检查点运行是收到的用户更新会导致不可变的pages被重新COWed。这个允许用户可见文件系统操作去执行而不需要损坏检查点的完整。

子卷树可以被快照和克隆,他们因此也是ref-counted的。其他的树在每个磁盘范围内保留元数据,他们从不会快照。参考计数对他们来说是没必要的。

文件系统更新影响许多磁盘结构。举个例子,写一个4KB数据到文件会改变文件i-node,file-extents,checksums and back-references.这些改变导致在它们各自的书里的一整个路径的改变。  如果用户执行整个随机更新,这个对文件系统而言是很昂贵的。 幸运的是,用户行为在很多地方都是正常的。如果一个文件被更新,可能会用新数据去更新;相同目录下的文件有一个很高的co-access的可能性(大概是互相可以访问的意思吧)这就允许在树中合并的修改路径。尽管如此,错误情况文件系统代码中也有考虑。 树结构被阻止以至于文件操作通常是单个路径的修改。 大范围的操作会被打断分成多个部分,因此检查点不会增长的太大。 最后,特殊的块被预留使用,因此一个检查点将总是在磁盘上有一个home,保证进步。

使用写时复制作为为一个更新策略又有点也有缺点。优势就是保证操作原子是比较简单的,并且数据结构是完整的。 掠食就是性能依赖维护空闲连续磁盘空间的large extents的能力。额外的,随即更新一个文件趋向于碎片化它,顺序摧毁。一个好的碎片整理算法是需要的。

校验在块写到磁盘的时刻被计算。在checkpoint的结尾,所有的checksum匹配,root block的checksum反映了整棵树。 元数据节点在他们被创建的时候计略generation point。这个是他们的checkpoint的serial number。B-tree 指针存储期望的target eneration number,这个允许在媒体上探测幻影和写错的位置。Generation number 和校验服务一起去验证磁盘块内容

二、Extent allocation tree

   Extent 分配树持有extent-items,每个描述一个特别的连续的磁盘区域。对于一个extent而言可能有许多的引用,每个引用只涉及其中一部分。举个例子,考虑文件foo有一个cipanextent 100KB-120KB。文件 foo被克隆去创建文件bar。 稍后,一个10KB大小范围在bar文件中被重写。 这个会导致下面的情景:

image.png

Foo和他的克隆文件共享extent100-128KB部分的数据。Bar在中间有一个extent被重写,现在位于磁盘更远的地方。

有三个指针指向extent 100-128KB, 覆盖不同部分。extent-item 持续追踪所有这样的引用,在后续的时间里允许移动整个extent。 一个extent可以可能有大量的back reference(难道叫作向后引用?),在这种情况下extent-items 不适用于单个的b-tree叶子节点。这种情况下,item泄露并占用超过一个叶子。

一个back reference是逻辑的而不是物理上的。它由root_object_id,generation_id, tree level, and 在指向块中的最低级object_id组成。这允许找到指针,在一个在从root_object_id开始的查找遍历之后找到指针。

三、Fsync

 fsync是一个操作会将一个特殊的文件的所有的脏的数据flush到磁盘。 一个重要的使用例子是在提交事务之前通过数据库去保证数据库日记在磁盘上。延迟是很重要的;一个事务直到日志都在磁盘上才会提交。一个天真的fsync实现是去校验整个文件系统。但是,这得忍受高延迟。取而代之的,修改设计特殊文件的数据和元数据被写到一个特殊的log-tree。如果系统崩溃了,log-tree将会作为恢复序列的一部分被读取。 这个保证只有最小的相应的修改会成为fsync代码路径的一部分。

四、Concurrency

现代系统有多个CPU,多核。通过并行性充分利用计算能力是一个重要考虑因素。

老一辈在磁盘上是一成不变的,并且他们的访问不需要锁。 在内存中修改的页面需要保护。因为数据被组织成树,策略是使用一个read/write 锁表。 树遍历在read 模式下被初始化。 当一个节点需要更新时, 锁被转换成模式。 如果一个块B需要COW, 遍历会被重启。 新的遍历在parent(B)停止, COWs B,修改父指针,并且继续向下。

树遍历是自顶向下的。他们在顶部开始,且走在树下,没必要走回去。


————————————————

                           版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

                     

原文链接:https://blog.csdn.net/PANGHAIFEI/article/details/99848825

目录
相关文章
|
存储 关系型数据库 MySQL
空闲空间管理和文件系统结构的优化策略
对于有科班背景的读者,可以跳过本系列文章。这些文章的主要目的是通过简单易懂的汇总,帮助非科班出身的读者理解底层知识,进一步了解为什么在面试中会涉及这些底层问题。否则,某些概念将始终无法理解。这些计算机基础文章将为你打通知识的任督二脉,祝你在编程领域中取得成功!
空闲空间管理和文件系统结构的优化策略
|
6月前
|
存储 芯片
xv6(8) 磁盘及分区理论
磁盘及分区理论
94 0
|
存储
磁盘满的本质分析——磁盘空间满与inode节点满
磁盘满的本质分析——磁盘空间满与inode节点满
223 1
磁盘满的本质分析——磁盘空间满与inode节点满
|
存储 算法 数据中心
带你读《存储漫谈:Ceph原理与实践》——2.2.2 CRUSH 算法因子
带你读《存储漫谈:Ceph原理与实践》——2.2.2 CRUSH 算法因子
|
存储 算法 Python
带你读《存储漫谈:Ceph原理与实践》——2.2.3 Bucket 随机选择算法
带你读《存储漫谈:Ceph原理与实践》——2.2.3 Bucket 随机选择算法
|
存储 算法 关系型数据库
带你读《存储漫谈:Ceph原理与实践》——2.3.1 PG 数量的选择
带你读《存储漫谈:Ceph原理与实践》——2.3.1 PG 数量的选择
|
存储 缓存 固态存储
【Linux】基础IO --- 内核级和用户级缓冲区、磁盘结构、磁盘的分治管理、block group块组剖析…
【Linux】基础IO --- 内核级和用户级缓冲区、磁盘结构、磁盘的分治管理、block group块组剖析…
|
存储 程序员 编译器
C++内存分区模型
C++内存分区模型
154 0
C++内存分区模型
|
存储 关系型数据库 MySQL
Xdes&Inode&Seg Header(6) 独立表空间结构(三十二)
Xdes&Inode&Seg Header(6) 独立表空间结构(三十二)