linux内核dm thin pool分析

一、简介

Docker现在非常火热,作为docker存储引擎之一的dm thin pool用的比较多,thin-pool由一个metadata设备和data设备组成,thin的概念就是按需分配数据块,删除时也回收数据块,提高存储空间利用率。

a)         Dm thin pool创建命令如下:

//清零metadata设备的第一个page, why??因为第一个page是thin-pool的superblock, thin pool 内核模块里是通过判断superbock是否全0来决定是重新格式化一个thin-pool还是打开已有的thin-pool

dd if=/dev/zero of=$metadata_dev bs=4096 count=1

//创建pool, --table的参数,0为起始扇区,20971520是扇区数,这里的扇区都是512字节来算的,data_block_size --- 数据块的大小,单位还是扇区,512字节,data_block_size最小为128,最大为2097152

low_water_mark ---当空闲数据块个数小于water_mark时, dm thin-pool内核模块会给用户态daemon发送通知事件。

dmsetup create pool \

b)         --table "0 20971520 thin-pool $metadata_dev $data_dev \

  1. $data_block_size $low_water_mark"

//调用pool设备的message接口,创建thin设备,其中0是thin设备的id, 因为一个pool可以创建N个thin设备,所以需要一个id来区别开这些thin设备。

dmsetup message /dev/mapper/pool 0 "create_thin 0"

//为上面的thin设备创建/dev/dm-x 设备文件。

dmsetup create thin --table "0 2097152 thin /dev/mapper/pool 0"

二、thin-pool磁盘布局

a)         data设备

data设备是以data_block_size,如果是128就是128*512=64KB 划分为块来管理的,data设备存储的全是数据,没有任何元数据,所以磁盘布局略。

b)         Meta设备

c)         如图, meta设备的磁盘布局如上,meta设备的块大小为4KB, 第一个块是superblock, 代码里定义如下:

/*

Little endian on-disk superblock and device details.

*/

struct thin_disk_superblock {

__le32 csum;    /* Checksum of superblock except for this field. */

__le32 flags;

__le64 blocknr; /* This block number, dm_block_t. */

__u8 uuid[16];

__le64 magic;

__le32 version;

__le32 time;

__le64 trans_id;

/*

Root held by userspace transactions.

*/

__le64 held_root;

__u8 data_space_map_root[SPACE_MAP_ROOT_SIZE];

__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];

/*

2-level btree mapping (dev_id, (dev block, time)) -> data block

*/

__le64 data_mapping_root;

/*

Device detail root mapping dev_id -> device_details

*/

__le64 device_details_root;

__le32 data_block_size;     /* In 512-byte sectors. */

__le32 metadata_block_size; /* In 512-byte sectors. */

__le64 metadata_nr_blocks;

__le32 compat_flags;

__le32 compat_ro_flags;

__le32 incompat_flags;

} __packed;

d)         重要的字段:

l  Magic: pool设备的magic: 27022010

l  Data_space_map_root: 管理数据块设备使用空间(使用位图)的map_root结构

l  Metadata_space_map_root: 管理元数据块设备使用空间(使用位图)的map_root结构

l  Data_mapping_root: thin设备从虚拟块地址到数据块设备上真实地址的映射btree根块号

l  Device_details_root: 所有thin设备的信息以btree的方式存到Device_details_root指向的根块上

l  Data_block_size: 数据设备块大小 =  data_block_size * 512B

l  Meta_nr_blocks: 元数据设备总块数, 注元数据设备块大小为4KB

三、寻址

从thin设备的虚拟块地址到数据设备的实际块地址,thin-pool的寻址逻辑如下:

a)         先用thin设备的dev_id作为key, 从data_mapping_root指向的块所包含的btree根节点中,去查找thin设备所对应的数据映射btree的块号

b)         再用虚拟块号作为key从thin设备的数据映射btree里去查找实际的value, 查到的value就是数据块设备上对应的实际块号

c)         整个过程用伪代码如下:

block_t find_thin_block(dev_t dev_id, block_t block)

{

block_t thin_map_root;

//从data_map_root btree中以dev_id为key查找对应的值,结果为dev_id对应的thin设备的具体btree根节点所在的块

thin_map_root = btree_lookup(pool_data_map_root, dev_id);

//从meta设备上读出根节点

read_block(meta_dev, thin_map_root, &thin_map_tree);

//从btree中以thin的虚拟块block查找data设备对应的实际块

return btree_lookup(&thin_map_tree, block);

}

四、空间管理

a)         整个thin-pool模块里,所有的空间管理都是基于btree的。

b)         元数据块设备自身的空间管理: 这个是通过以Metadata_space_map_root为根块的btree来管理的,叶子节点存放的是管理空间的位图,与普通位图不同的是thin-pool的位图是一个单元2个位,一共能表示4个状态: 0为空闲,1为引用计数为1, 2位引用计数为2, 3表示引用计数>2, 需要从另一颗btree里去找实际的引用计数。

c)         数据块设备空间管理: 跟元数据块设备自身空间管理类似,数据块设备也是一颗btree, 叶子节点指向包含管理位图的块,当然这些块都是在元数据设备上的。

d)         空间释放:当引用bitmap里的引用计数变为0时, 块就变空闲了,这也就是thin设备的意义所在,不过,这需要上层文件系统discard的支持,thin-pool需要能知道哪些块上层不需要了,就可以减小位图的引用计数,释放块。

五、总结

thin-pool的存储格式还是比较清晰和简单的,总体看上面的布局结构图就已经很清晰了。

时间: 2024-08-10 19:17:16

linux内核dm thin pool分析的相关文章

Linux内核抢占实现机制分析【转】

Linux内核抢占实现机制分析 转自:http://blog.chinaunix.net/uid-24227137-id-3050754.html [摘要]本文详解了Linux内核抢占实现机制.首先介绍了内核抢占和用户抢占的概念和区别,接着分析了不可抢占内核的特点及实时系统中实现内核抢占的必要性.然后分析了禁止内核抢占的情况和内核抢占的时机,最后介绍了实现抢占内核所做的改动以及何时需要重新调度. [关键字]内核抢占,用户抢占,中断, 实时性,自旋锁,抢占时机,调度时机,schedule,pree

Linux内核抢占实现机制分析

Sailor_forever  [email protected] 转载请注明 http://blog.csdn.net/sailor_8318/archive/2008/09/03/2870184.aspx [摘要]本文详解了Linux内核抢占实现机制.首先介绍了内核抢占和用户抢占的概念和区别,接着分析了不可抢占内核的特点及实时系统中实现内核抢占的必要性.然后分析了禁止内核抢占的情况和内核抢占的时机,最后介绍了实现抢占内核所做的改动以及何时需要重新调度. [关键字]内核抢占,用户抢占,中断, 

(转)Linux内核基数树应用分析

Linux内核基数树应用分析 ——lvyilong316 基数树(Radix tree)可看做是以二进制位串为关键字的trie树,是一种多叉树结构,同时又类似多层索引表,每个中间节点包含指向多个节点的指针数组,叶子节点包含指向实际对象的指针(由于对象不具备树节点结构,因此将其父节点看做叶子节点). 图1是一个基数树样例,该基数树的分叉为4(2^2),树高为4,树的每个叶子结点用来快速定位8位文件内偏移,可以定位4x4x4x4=256(叶子节点的个数)页,如:图中虚线对应的两个叶子结点的路径组成值

Linux内核--网络栈实现分析(七)--数据包的传递过程(下)

本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7545855 更多请查看专栏,地址http://blog.csdn.net/column/details/linux-kernel-net.html 作者:闫明 注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”(上)“表示分析是从底层向上分析.”(下)“表示分析是从上向下分析. 在博文Linux内核--网络栈

Linux内核--网络栈实现分析(十一)--驱动程序层(下)

本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7555870 更多请查看专栏,地址http://blog.csdn.net/column/details/linux-kernel-net.html 作者:闫明 注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”(上)“表示分析是从底层向上分析.”(下)“表示分析是从上向下分析. 在博文Linux内核--网络栈

Linux内核态抢占机制分析(转)

Linux内核态抢占机制分析  http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html 摘 要]本文首先介绍非抢占式内核(Non-Preemptive Kernel)和可抢占式内核(Preemptive Kernel)的区别.接着分析Linux下有两种抢占:用户态抢占(User Preemption).内核态抢占(Kernel Preemption).然后分析了在内核态下:如何判断能否抢占内核(什么是可抢占的条件):何时触发重新调度(何时设置可抢

Linux内核--网络栈实现分析(一)--网络栈初始化

本文分析基于内核Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7488828 更多请看专栏,地址http://blog.csdn.net/column/details/linux-kernel-net.html 作者:闫明 以后的系列博文将深入分析Linux内核的网络栈实现原理,这里看到曹桂平博士的分析后,也决定选择Linux内核1.2.13版本进行分析. 原因如下: 1.功能和网络栈层次

Linux内核的idle进程分析

1. idle是什么 简单的说idle是一个进程,其pid号为 0.其前身是系统创建的第一个进程.也是唯一一个没有通过fork()产生的进程. 在smp系统中,每一个处理器单元有独立的一个执行队列,而每一个执行队列上又有一个idle进程,即有多少处理器单元.就有多少idle进程. 系统的空暇时间,事实上就是指idle进程的"执行时间".既然是idle是进程.那我们来看看idle是怎样被创建,又详细做了哪些事情? 2. idle的创建 我们知道系统是从BIOS加电自检,载入MBR中的引导

Linux内核中断和异常分析(下)

这节,我们继续上,中(以前的日志有)篇目进行分析,结合一个真实的驱动案例来描述linux内核中驱动的中断机制,首先我们先了解一下linux内核中提供的中断接口. 这个接口我们需要包含一个头文件:#include <linux/interrupt.h> 在中断接口中,最重要的是以下的接口函数: 1.这个是请求中断函数 int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const cha