Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1253033
  • 博文数量: 185
  • 博客积分: 495
  • 博客等级: 下士
  • 技术积分: 1418
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-02 15:12
个人简介

治肾虚不含糖,专注内核性能优化二十年。 https://github.com/KnightKu

文章分类

全部博文(185)

文章存档

2019年(1)

2018年(12)

2017年(5)

2016年(23)

2015年(1)

2014年(22)

2013年(82)

2012年(39)

分类:

2018-08-28 15:28:40

原文地址:ZFS磁盘格式(1) 作者:qincp-

说明:计划对ZFS进行学习,文件系统的学习我一般从磁盘格式开始,所以对ZFS磁盘格式文档进行了翻译,仅供参考。由于图不方便上传,可以参见原文档:

第一章 虚设备(vdevs),Vdev标签以及boot

1.1 虚设备

ZFS存储池(pool)由一组虚设备构成。有两种类型的虚设备:物理虚设备(有时称为叶vdev)和逻辑虚设备(有时称为内部vdev)。物理vdev是一个可写媒体块设备(例如,一个磁盘)。逻辑vdev是物理vdev的一个逻辑组合。

Vdev按树形组织,物理vdev是这个树的叶。所有的存储池都有一个特殊的逻辑vdev——根vdev,是这个树的根。所有根vdev的第一代孩子(物理或者逻辑)叫做顶层vdev。下图显示了一个包含两个镜像的pool配置的vdev树。第一个镜像(M1)包含两个磁盘,分别为vdev Avdev B;第二个镜像M2包含两个磁盘vdev Cvdev Dvdev ABCD都是物理vdevM1M2为逻辑vdev,他们也是顶层vdev

1 vdev树示例

1.2 vdev标签

Pool中的每个物理vdev包含一个256KB的结构,这就是vdev标签。标签中存放了描述这个物理vdev以及所有以同一个顶层vdev为祖先的其他vdev的信息。例如,上图的vdev C的标签结构包含CDM2的信息。下一节将详细描述Vdev的标签信息。

Vdev标签有两个作用:提供对pool内容的访问,以及用于pool完整性和可用性效验。为保证标签始终可用和有效,使用了冗余和阶段更新机制。每个Vdev中,有四个完全相同的标签的拷贝。在标签更新过程中,使用了两阶段事务,保证磁盘上至少有一个标签是有效的。

1.2.1 标签冗余

Pool中每个物理Vdev都有标签的四个拷贝。除标签更新过程的很小时间窗外,这四个标签内容是完全相同,可以使用其中任何一个。当设备添加到pool中时,ZFS将两个标签放在设备的头,两个标签放在设备的尾部。下图显示了设备上这些标签的分布。L0L1代表前两个,L2L3代表后两个标签。

2 块设备上的vdev标签

典型的设备破坏一般发生在连续的物理位置,基于这个假设,将标签分为放在头部和尾部提高了在异常发生时的数据可用度。

1.2.2 标签更新的两个阶段事务

Vdev标签的位置在设备添加到pool时已经固定,这使得标签和ZFS其他对象不同,没有COW机制。所以,在vdev标签更新时,标签的内容被直接覆盖,这样覆盖可能发生错误。为保证ZFS始终有可用的标签,在更新时,使用了阶段提交。更新的第一个阶段,向磁盘写L0L2,此时L1L3依然有效。一旦L0L2成功写入,第二阶段再将L1L3写入。这个机制保证了所有时候,磁盘上都有有效的标签。

1.3 vdev技术细节

Vdev标签的内容分为4部分,8KB空白空间,8KBboot头信息,112KBname-value对,以及128个大小为1KBuberblock结构。下图是L0的进一步扩展图示:

3 vdev标签的组成

1.3.1 空白空间

ZFS支持VTOC(卷内容表,Volume Table of Content)和EFI磁盘标签两种方式进行磁盘格式描述。EFI标签有自己的保留空间,未作为切片部分写入,VTOC标签必须写入切片0的第一个8K。所以,为支持VTOCvdev标签的第一个8K保留,防止VTOC磁盘标签的覆盖。

1.3.2 Boot块头

Boot块头是一个8KB结构,保留用于以后使用。块的内容以后作为本文未来的附录进行说明。

1.3.3 name-value

标签的112KB空间存放一组name-value对,用于描述这个vdev和所有关联的vdev。和本vdev以同一个顶层vdev为祖先的所有其他vdev都是相关联的vdev。例如,下图中设备Avdev标签包含了高亮显示的子树的信息:包括vdev AB以及M1

4 高亮圈中显示了vdev树的相关联vdev

所有name-value对按XDR编码nvlist方式存储。更多关于XDR编码或者nvlist的信息,参见libnvpair3LIB)和nvlist_free3NVPAIR)手册。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和图4vdev树的等级特性的Nvlist结构。Vdev_tree递归的描述每一个子树中所有相关的vdev。下图展示图1和图4vdev A中的vdev_tree结构

5  1vdev Avdev_tree

每个vdev_tree nvlist包含下述的元素,注意并非所有nvlist元素都适合所有的vdev类型,vdev_tree中可能值包含下述元素的一个子集。

 

名称: type

: DATA_TYPE_STRING

描述:  表示vdev类型的字符串,如下表

类型

描述

disk”

vdev:块存储

file”

vdev:文件存储

mirror”

内部vdev:镜像

raidz”

内部vdevraidz

replacing”

内部vdev:镜像vdev的一个变种,磁盘替换时供ZFS使用

root”

内部vdevvdev树根

 

名称: 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.3vdevguid存放在guid中)。将这个值和ub_guid_sum比较,来验证pool中所有的vdev是否可用。

 

Ub_timestamp

uberblock写入的时间,从197011开始的UTC

 

Ub_rootbp

一个Blkptr结构,包含MOS位置信息。MOS在第四章说明,blkptr在第二章说明。

1.4 Boot

L0L1之后是3.5MB大小的空间预留做以后使用。

7 vdev标签格式以及boot块预留空间

阅读(1133) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~