前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅谈zfs中概念-part1

浅谈zfs中概念-part1

作者头像
用户4700054
发布2022-08-17 12:41:32
1.2K0
发布2022-08-17 12:41:32
举报
文章被收录于专栏:存储内核技术交流

zfs试验环境

代码语言:javascript
复制
$ uname -a
Linux CentOS8-Dev 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Tue Nov 16 14:42:35 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

$ zfs --version
zfs-2.1.99-530_g269b5dadc
zfs-kmod-2.1.99-530_g269b5dadc

zfs中核心概念

  • vdevs(virtial devices):zfs的pool是由一组vdevs组成。vdev有物理虚拟设备和逻辑虚拟设备组成。zfs的pool可以看成是一棵树,树的非叶子节点是逻辑虚拟设备,叶子节点是物理虚拟设备。逻辑虚拟设备在指向由一组物理虚拟设备,物理虚拟设备则是具体的物理磁盘。例如创建一个zfs pool,pool中有2个互为镜像(M1和M2,M1和M2互为mirrors).M1包含了2个物理虚拟磁盘(dev-A和dev-B).M2包含了2个物理虚拟磁盘(dev-C和dev-D).pool的顶层是root vdev.其数据结构把无关的字段去掉后,如下
代码语言:javascript
复制
struct vdev {
	// 当前vdev的唯一标识
	uint64_t	vdev_id;
	// root vdev节点
	vdev_t		*vdev_top;	
	// 当前vdev的父节点
	vdev_t		*vdev_parent;	
	// 当前vdev的子节点数组
	vdev_t		**vdev_child;	
	// 当前vdev子节点的个数
	uint64_t	vdev_children;	
}

整个vdev的结构如下图所示:

代码语言:javascript
复制
// 创建了2个pool,一个是cow
$ zdb cow 
Cached configuration:
        version: 5000
		// pool的名称
        name: 'cow'
        state: 0
        txg: 565
        pool_guid: 1484685820301823750
        errata: 0
        hostname: 'CentOS8-Dev'
        com.delphix:has_per_vdev_zaps
		// 这里只有一个节点子节点
        vdev_children: 1
		// 虚拟设备的tree
        vdev_tree:
			// 这里是root vdev
            type: 'root'
            id: 0
            guid: 1484685820301823750
            create_txg: 4
			// 当前子节点的vdev
            children[0]:
                type: 'disk'
                id: 0
                guid: 8957727234128580398
                path: '/dev/sdb1'
                devid: 'ata-CentOS8-Dev-0_SSD_WJMTS4R4TWPMF4J1N2KV-part1'
                phys_path: 'pci-0000:00:1f.2-ata-3'
                whole_disk: 1
                metaslab_array: 67
                metaslab_shift: 29
                ashift: 12
                asize: 68704272384
                is_log: 0
                create_txg: 4
  • vdev labels:每个物理虚拟设备(叶子节点的磁盘)包含了256K的vdev_label.vdev_label包括具体物理设备的描述信息和其他共享top-level的vdev的物理设备。设计vdev_label有两个目的,第一个是为了访问pool的信息,同时用来校验pool的可用性。每个zfs pool会对每个物理虚拟设备写入4份vdev_label的信息,其中2份(0,2)写入到物理虚拟磁盘的头部;剩下2份(1,3)写入物理虚拟磁盘的尾部。 struct vdev_label是用来描述vdev_label的信息,具体定义如下:
代码语言:javascript
复制
typedef struct vdev_label {
	// 填充
	char		vl_pad1[VDEV_PAD_SIZE];			/*  8K */
	// boot header的信息
	vdev_boot_envblock_t	vl_be;				/*  8K */
	// 112K的name-value的kv结构,用来描述物理虚拟设备信息,比如之前的vdev结构中,在物理虚拟设备vdev-A的物理虚拟设备的vdev_label会包含vdev-A和vdev-B和M的信息
	vdev_phys_t	vl_vdev_phys;				/* 112K	*/
	// uberblock的结构,用来访问pool的,uberblock从来不会被重写,是采用cow的策略
	char		vl_uberblock[VDEV_UBERBLOCK_RING];	/* 128K	*/
} vdev_label_t;		

下面展示了struct vdev_label具体存储的信息

  • zfs中数据在内存和磁盘之间的传输的最小单位是block.blkptr_t结构是zfs用来描述数据块位置、校验。zfs的读写的数据洗是需要从逻辑虚拟设备到物理虚拟设备的抓换,zfs内部如果数据块超过128K则需要1个数据块以及多个数据块指针。blkptr_t在zfs中定义如下:
代码语言:javascript
复制
typedef struct blkptr {
	// 给定文件名称来确定在vdev中的数据指针(包括了vdev + offset)
	dva_t		blk_dva[SPA_DVAS_PER_BP]; 
	uint64_t	blk_prop;	/* size, compression, type, etc	    */
	uint64_t	blk_pad[2];	/* Extra space for the future	    */
	// 当block被申请后txg的编号
	uint64_t	blk_phys_birth;	/* txg when block was allocated	    */
	// txg的编号
	uint64_t	blk_birth;	/* transaction group at birth	    */
	// block pointer数据指针的个数
	uint64_t	blk_fill;	/* fill count			    */
	// zfs会计算数据和元数据的cehcksum,存储在这个字段中
	zio_cksum_t	blk_cksum;	/* 256-bit checksum		    */
} blkptr_t;
代码语言:javascript
复制
// 获取inode信息
$ ls -i /cow/fs1
11 data1

// 使用zdb来查看这个inode的数据块分布
$ zdb -dddddd cow/fs1 11
Dataset cow/fs1 [ZPL], ID 133, cr_txg 8, 104K, 9 objects, rootbp DVA[0]=<0:3c001b000:1000> DVA[1]=<0:3e001a000:1000> [L0 DMU objset] fletcher4 uncompressed unencrypted LE contiguous unique double size=1000L/1000P birth=17722L/17722P fill=9 cksum=d95af3266:2524e8bfa703:3623a469f762d6:37d3ce753d3b7f0c

    Object  lvl   iblk   dblk  dsize  dnsize  lsize   %full  type
        11    1   128K    512     4K     512    512  100.00  ZFS plain file (K=inherit) (Z=inherit=uncompressed)
                                               184   bonus  System attributes
        dnode flags: USED_BYTES USERUSED_ACCOUNTED USEROBJUSED_ACCOUNTED 
        dnode maxblkid: 0
		// data1文件的元数据
        path    /data1
        uid     0
        gid     0
        atime   Fri Dec  3 05:22:18 2021
        mtime   Fri Dec  3 05:22:18 2021
        ctime   Fri Dec  3 05:22:18 2021
        crtime  Fri Dec  3 05:22:18 2021
        gen     17721
        mode    100755
        size    133
        parent  34
        links   1
        pflags  840800000104
        xattr   12
// 这里indirect blocks,这里就是个数据块
Indirect blocks:
			   //	 L0 是数据块
			   // 0 是vdev的编号;3a001c000是虚拟设备的offset.当前数据的是在vdev=0,offset=3a001c000的偏移量,F=1 是当前数据指针是1个,B=17721代表txg的number
               0 L0 0:3a001c000:1000 200L/200P F=1 B=17721/17721 cksum=c49acd1a9:55c27b8b422:1301dda03a28f:2da540a668650a

                segment [0000000000000000, 0000000000000200) size   512
  • zfs中数据结构关系概览图
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 存储内核技术交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • zfs试验环境
    • zfs中核心概念
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档