免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3637 | 回复: 0
打印 上一主题 下一主题

ZFS磁盘格式(1) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-22 15:54 |只看该作者 |倒序浏览

说明:计划对ZFS进行学习,文件系统的学习我一般从磁盘格式开始,所以对ZFS磁盘格式文档进行了翻译,仅供参考。由于图不方便上传,可以参见原文档:
http://www.opensolaris.org/os/community/zfs/docs/ondiskformat0822.pdf
第一章 虚设备(vdevs),Vdev标签以及boot块
1.1 虚设备
ZFS存储池(pool)由一组虚设备构成。有两种类型的虚设备:物理虚设备(有时称为叶vdev)和逻辑虚设备(有时称为内部vdev)。物理vdev是一个可写媒体块设备(例如,一个磁盘)。逻辑vdev是物理vdev的一个逻辑组合。
Vdev按树形组织,物理vdev是这个树的叶。所有的存储池都有一个特殊的逻辑vdev——根vdev,是这个树的根。所有根vdev的第一代孩子(物理或者逻辑)叫做顶层vdev。下图显示了一个包含两个镜像的pool配置的vdev树。第一个镜像(M1)包含两个磁盘,分别为vdev A和vdev B;第二个镜像M2包含两个磁盘vdev C和vdev D。vdev A,B,C,D都是物理vdev。M1和M2为逻辑vdev,他们也是顶层vdev。
图1 vdev树示例
1.2 vdev标签
Pool中的每个物理vdev包含一个256KB的结构,这就是vdev标签。标签中存放了描述这个物理vdev以及所有以同一个顶层vdev为祖先的其他vdev的信息。例如,上图的vdev C的标签结构包含C,D,M2的信息。下一节将详细描述Vdev的标签信息。
Vdev标签有两个作用:提供对pool内容的访问,以及用于pool完整性和可用性效验。为保证标签始终可用和有效,使用了冗余和阶段更新机制。每个Vdev中,有四个完全相同的标签的拷贝。在标签更新过程中,使用了两阶段事务,保证磁盘上至少有一个标签是有效的。
1.2.1 标签冗余
Pool中每个物理Vdev都有标签的四个拷贝。除标签更新过程的很小时间窗外,这四个标签内容是完全相同,可以使用其中任何一个。当设备添加到pool中时,ZFS将两个标签放在设备的头,两个标签放在设备的尾部。下图显示了设备上这些标签的分布。L0和L1代表前两个,L2和L3代表后两个标签。
图2 块设备上的vdev标签
典型的设备破坏一般发生在连续的物理位置,基于这个假设,将标签分为放在头部和尾部提高了在异常发生时的数据可用度。
1.2.2 标签更新的两个阶段事务
Vdev标签的位置在设备添加到pool时已经固定,这使得标签和ZFS其他对象不同,没有COW机制。所以,在vdev标签更新时,标签的内容被直接覆盖,这样覆盖可能发生错误。为保证ZFS始终有可用的标签,在更新时,使用了阶段提交。更新的第一个阶段,向磁盘写L0和L2,此时L1和L3依然有效。一旦L0和L2成功写入,第二阶段再将L1和L3写入。这个机制保证了所有时候,磁盘上都有有效的标签。
1.3 vdev技术细节
Vdev标签的内容分为4部分,8KB空白空间,8KB的boot头信息,112KB的name-value对,以及128个大小为1KB的uberblock结构。下图是L0的进一步扩展图示:
图3 vdev标签的组成
1.3.1 空白空间
ZFS支持VTOC(卷内容表,Volume Table of Content)和EFI磁盘标签两种方式进行磁盘格式描述。EFI标签有自己的保留空间,未作为切片部分写入,VTOC标签必须写入切片0的第一个8K。所以,为支持VTOC,vdev标签的第一个8K保留,防止VTOC磁盘标签的覆盖。
1.3.2 Boot块头
Boot块头是一个8KB结构,保留用于以后使用。块的内容以后作为本文未来的附录进行说明。
1.3.3 name-value对
标签的112KB空间存放一组name-value对,用于描述这个vdev和所有关联的vdev。和本vdev以同一个顶层vdev为祖先的所有其他vdev都是相关联的vdev。例如,下图中设备A的vdev标签包含了高亮显示的子树的信息:包括vdev A,B以及M1。
图4 高亮圈中显示了vdev树的相关联vdev
所有name-value对按XDR编码nvlist方式存储。更多关于XDR编码或者nvlist的信息,参见libnvpair(3LIB)和nvlist_free(3NVPAIR)手册。Vdev便签的这112KB中包含了如下name-value对:
Version:
名称: “version”
值: DATA_TYPE_UINT64
描述: 磁盘格式版本号,当前为 “1”.

Name:
名称: “name”
值: DATA_TYPE_STRING
描述: vdev所属的pool的名称

State:
名称: “state”
值: DATA_TYPE_UINT64
描述: Pool的状态,如下表
表1 POOL状态和值
状态

POOL_STATE_ACTIVE   
0
POOL_STATE_EXPORTED
1
POOL_STATE_DESTROYED
2
Transaction
名称: “txg”
值: DATA_TYPE_UINT64
描述: 标签写入磁盘的事务组编号

Pool Guid
名称: “pool_guid”
值: DATA_TYPE_UINT64
描述: pool的全部唯一标识(guid)

Top Guid
名称: “top_guid”
值: DATA_TYPE_UINT64
描述: 该子树对应的顶层vdev的全部唯一标识

Guid
名称: “guid”
值: DATA_TYPE_UINT64
描述: 该vdev的全部唯一标识

Vdev Tree
名称: “vdev_tree”
值: DATA_TYPE_NVLIST
描述: 用于描述如图1和图4中vdev树的等级特性的Nvlist结构。Vdev_tree递归的描述每一个子树中所有相关的vdev。下图展示图1和图4中vdev A中的vdev_tree结构
图5  图1的vdev A的vdev_tree
每个vdev_tree nvlist包含下述的元素,注意并非所有nvlist元素都适合所有的vdev类型,vdev_tree中可能值包含下述元素的一个子集。

名称: “type”
值: DATA_TYPE_STRING
描述:  表示vdev类型的字符串,如下表
类型
描述
“disk”
叶vdev:块存储
“file”
叶vdev:文件存储
“mirror”
内部vdev:镜像
“raidz”
内部vdev:raidz
“replacing”
内部vdev:镜像vdev的一个变种,磁盘替换时供ZFS使用
“root”
内部vdev:vdev树根

名称: “id”
值: DATA_TYPE_UINT64
描述: 这个vdev在其父节点的孩子数组中的下标

名称: “guid”
值: DATA_TYPE_UINT64
描述:  vdev_tree元素的全局唯一标识

名称: “path”
值: DATA_TYPE_STRING
描述:  设备路径,仅用于叶vdev

名称: “devid”
值: DATA_TYPE_STRING
描述: vdev_tree元素的设备ID,仅用于磁盘类型的vdev

名称: “metaslab_array”
值: DATA_TYPE_UINT64
描述: 这是一个对象编号,该对象包含了一个对象编号数组,数组的每一个元素是对应mataslab空间映射的对象编号

名称: “metaslab_shift”
值: DATA_TYPE_UINT64
描述: metaslab尺寸,以2为底的对数表示

名称: “ashift”
值: DATA_TYPE_UINT64
描述: 这个顶层vdev的最小可分配单元的大小,以2为底的对数表示。对于Raidz,当前取值10,其他类型取值为9。

名称: “asize”
值: DATA_TYPE_UINT64
描述: 这个顶层vdev中的可分配的空间大小。

名称: “children”
值: DATA_TYPE_NVLIST_ARRAY
描述: 包含该vdev_tree元素的所有孩子的Vdev_tree nvlist数组

1.3.4 UberBlock
Vdev标签中,name-value对列表之后就是一个uberblock数组。Uberblock包含访问pool内容需要的信息。某个时刻pool中只有一个uberblock是激活的。拥有最高事务组编号并且SHA-256效验和有效的uberblock是激活的uberblock。
为保证对激活uberblock的持续可访问,激活uberblock绝不进行覆盖。所有对uberblock的更新将向数组中除当前激活uberblock的另外一个元素写入。写入新的uberblock时,事务组编号和时间戳都进行更新,写入结束后,新的uberblock以一个原子动作的方式称为新的激活uberblock。在pool中的uberblock数组中,以一种循环方式进行写操作。下图对数组中的两个元素进行了扩展呈现:
图6 Uberblock数组
Uberblock技术细节
Uberblock以机器字节序方式存储,包含如下内容:
Ub_magic
用于标识包含ZFS数据的设备的64位魔数。Ub_magic的值为0x00bab10c (oo-ba-block)。下表是磁盘上看到的魔数。
表3   磁盘上的Uberblock魔数
机器字节序
Uberblock魔数值
大尾
0x00bab10c
小尾
0x0cb1ba00
Ub_version
用于标识该数据的格式的版本。当前版本号为0x1。这个域和1.3.3中描述的“version”值是相同的。

Ub_txg
ZFS的所有写都是以事务组方式进行的。每一个组和一个事务组编号关联。Ub_txg值就是该uberblock写入时的事务组编号,它必须大于或等于已存在的事务组编号。

Ub_guid_sum
标识pool中的vdev的可用性。当pool打开时,ZFS遍历pool中的所有叶vdev,计算经过的所有GUID的和(如1.3.3,vdev的guid存放在guid中)。将这个值和ub_guid_sum比较,来验证pool中所有的vdev是否可用。

Ub_timestamp
该uberblock写入的时间,从1970年1月1日开始的UTC。

Ub_rootbp
一个Blkptr结构,包含MOS位置信息。MOS在第四章说明,blkptr在第二章说明。
1.4 Boot块
L0和L1之后是3.5MB大小的空间预留做以后使用。
图7 vdev标签格式以及boot块预留空间


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/103238/showart_2057675.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP