Devicemapper 源码分析和流程


整个流程大体如下:

创建 thinpool

// This is theprogrammatic example of "dmsetup create"

funccreatePool(poolName string, dataFile, metadataFile *os.File, poolBlockSizeuint32) error {

...

params := fmt.Sprintf("%s %s %d 32768 1skip_block_zeroing", metadataFile.Name(), dataFile.Name(), poolBlockSize)

if err := task.AddTarget(0, size/512,"thin-pool", params); err != nil { return fmt.Errorf("Can‘t addtarget %s", err)

}

...

}

相当于执行下面的操作:

#  dmsetup create docker-8:1-696417-pool--table 0 419430400 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing‘

# dmsetup table docker-8:1-696417-pool

0 419430400thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing

创建 BaseImage

实际上,thin-provisionedvolume 分两步,首先是发送一个消息给 pool,创建一个 volume。然后激活

volume。只有 activated 的 volume,才能在 dmsetup info 的输出中看到。 (1)Creating a newthinly-provisioned volume

funccreateDevice(poolName string, deviceId *int) error {

if err :=task.SetMessage(fmt.Sprintf("create_thin %d", *deviceId)); err != nil{ return fmt.Errorf("Can‘t set message %s", err)

}

相当于执行下面的操作:

#dmsetup message/dev/mapper/ docker-8:1-696417-pool 0 "create_thin 0"

  

# hexdump -C  /var/lib/docker/devicemapper/metadata/base

00000000

7b

22

64 65 76

69 63

65

5f 69 64 22 3a

30

2c 22

|{"device_id":0,"|

00000010

73

69

7a 65

22

3a 32 31

34 37 34 38 33 36 34 38

|size":2147483648|

00000020

30

2c 22 74 72

61

6e

73

61 63 74 69

6f 6e 5f 69

|0,"transaction_i|

00000030

64

22

3a 31

2c

22

69

6e

69 74 69 61

6c

69

7a 65

|d":1,"initialize|

00000040

64

22

3a 74

72

75 65

7d

|d":true}|

可以看到 base 的 device_id 为 0。

(2)activatedthinly-provisioned volumes

funcactivateDevice(poolName string, name string, deviceId int, size uint64) error {

...

params :=fmt.Sprintf("%s %d", poolName, deviceId)

if err := task.AddTarget(0, size/512,"thin", params); err != nil { return fmt.Errorf("Can‘t addtarget %s", err)

}

相当于执行下面的操作:

#dmsetup createdocker-8:1-696417-base --table "0 41943040 thin /dev/mapper/docker-8:1-696417-pool 0"

#dmsetup table docker-8:1-696417-base 0 41943040 thin 253:0 0

只有 activated 的 volume,才能在 dmsetup info 的输出中看到。 Devicemapper 的基本操作

Driver的基本操作

///清除 thin pool

func (d *Driver)Cleanup()

///当加载新镜像时,添加一个新 thin volume,id 为 containerid 或 imageid func (d *Driver) Create(id, parent string)

///挂载 thin volume 到/var/lib/docker/devicemapper/mnt/$id 目录下(docker start) func (d *Driver) Get(id, mountLabelstring)

///从/var/lib/docker/devicemapper/mnt/$id目录 umount thinvolume(docker stop) func (d *Driver) Put(id string)

///删除 volume(真正删除)

func (d *Driver)Remove(id string)

Thinpool 的基本操作

///在 thin pool 中创建一个新的 snapshot volume

func (devices*DeviceSet) AddDevice(hash, baseHash string)

///删除 thin volume(释放空间,删除(remove+delete)thin volume) func (devices *DeviceSet) DeleteDevice(hashstring)

/// 将 thin volume 从 /var/lib/docker/devicemapper/mnt/$id umount, deactivate(remove )thinvolume(don‘t delete)

func (devices*DeviceSet) UnmountDevice(hash string)

///activate thin volume ,然后 mount 到/var/lib/docker/devicemapper/mnt/$idfunc (devices *DeviceSet) MountDevice(hash, path, mountLabel string)

///thin pool 的统计信息(docker info)

func (devices*DeviceSet) Status() *Status

///thin pool 初始化

funcNewDeviceSet(root string, doInit bool, options []string)

Devmapper接口

devmapper/devmapper.go封装了 OS 层的 thin volume 的基本操作。

///dmsetup suspend

funcsuspendDevice(name string)

///dmsetup resume

funcresumeDevice(name string)

///messagecreate_thin

funccreateDevice(poolName string, deviceId *int)

///message delete

funcdeleteDevice(poolName string, deviceId int)

///dmsetup remove

funcremoveDevice(name string)

///dmsetup create

funcactivateDevice(poolName string, name string, deviceId int, size uint64)

///message‘create_snap‘

funccreateSnapDevice(poolName string, deviceId *int, baseName string, baseDeviceIdint)

三者之间的调用关系如下:

查看 stop 的容器的文件系统

stop 的容器的 thin volume 都处于未激活(deactivate)状态,我们可以将其激活(activate),然后查 看文件系统中的内容。

我们创建一个容器,不启动:

# docker create --name="yy1" centos /bin/bash 93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e9

metadata 下面新增两个目录:

# ls metadata/93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e993f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e9 -init

我们可以查看 thin volume 的信息

#cat metadata/93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e9{"device_id":5,"size":21474836480,"transaction_id":8,"initialized":false}

# catmetadata/93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e9 -init{"device_id":4,"size":21474836480,"transaction_id":7,"initialized":false}

我们来尝试手动挂载 thin volume,首先 activate thin volume:

#
dmsetup
create
93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e9 -init
--table    "0
41943040 thin 253:0 4"

然后就可以挂载该 thin volume 了:

#

mount

/dev/mapper/93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e9-init mnt/93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e9-init

# lsmnt/93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e9 -init/ id lost+foundrootfs

deactivate thinvolume

# umountmnt/93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01ad89f8e9-init

# dmsetup remove93f595ea79a0420cc263d054d3e63b5ad1e4cc3da128167984a6ac01

更多精彩内容请关注:http://bbs.superwu.cn

关注超人学院微信二维码:

关注超人学院java免费学习交流群:

时间: 2024-10-13 19:41:50

Devicemapper 源码分析和流程的相关文章

Memcached 源码分析--命令流程分析

一.执行命令 首先是启动memcached 自带参数如下: <span style="font-size:18px;">-p <num> 设置TCP端口号(默认设置为: 11211) -U <num> UDP监听端口(默认: 11211, 0 时关闭) -l <ip_addr> 绑定地址(默认:所有都允许,无论内外网或者本机更换IP,有安全隐患,若设置为127.0.0.1就只能本机访问) -c <num> max simult

Spring源码分析--IOC流程

代码地址:https://github.com/LoveWK/mySpring/tree/master/myIocDemo 1.创建MyAnnotation类 1 @Configuration//java配置类注解 2 @ComponentScan("com.wk")//设置扫描包的路径 3 public class MyAnnotation { 4 } 2.创建Test类 1 /** 2 * 测试类 3 */ 4 public class Test { 5 public static

Android7.0 MediaRecorder源码分析

最近在做Camera的方案(双进程打开一个Camera),涉及到使用MediaRecorder 进行录像,还是自己新建一套录像系统.接下来我将记录下本次源码分析的流程.  有关于Client和Server间的binder通信,会在下一篇里分析  (Client)  STEP ONE(Contructor) 1../base/media/java/android/media/MediaRecorder.java  在MediaRecorder的构造中就是使用了native_setup()的方法(N

MyBatis源码分析(五):MyBatis Cache分析

一.Mybatis缓存介绍 在Mybatis中,它提供了一级缓存和二级缓存,默认的情况下只开启一级缓存,所以默认情况下是开启了缓存的,除非明确指定不开缓存功能.使用缓存的目的就是把数据保存在内存中,是应用能更快获取数据,避免与数据库频繁交互,特别是在查询比较多.命中率比较高的情况下,缓存就显得很重要.但是使用不得当,会产生脏数据. 二.目录 一级缓存介绍及相关配置. 一级缓存工作流程及源码分析. 一级缓存总结. 二级缓存介绍及相关配置. 二级缓存源码分析. 二级缓存总结. 全文总结. 三.一级缓

springmvc源码分析系列-请求处理流程

接上一篇-springmvc源码分析开头片 上一节主要说了一下springmvc与struts2的作为MVC中的C(controller)控制层的一些区别及两者在作为控制层方面的一些优缺点.今天就结合下面的一张图和上一篇中关于springmvc各个模块之间及各个模块中的类的继承关系的一张图对springmvc的请求处理流程进行一个分析.当然有了springmvc的请求处理流程我们就知道了springmvc是如何在启动的时候去加载或者去解析对应的具体控制器,以及modleAndView使干什么用的

HBase1.0.0源码分析之请求处理流程分析以Put操作为例(二)

HBase1.0.0源码分析之请求处理流程分析以Put操作为例(二) 1.通过mutate(put)操作,将单个put操作添加到缓冲操作中,这些缓冲操作其实就是Put的父类的一个List的集合.如下: private List<Row> writeAsyncBuffer = new LinkedList<>(); writeAsyncBuffer.add(m); 当writeAsyncBuffer满了之后或者是人为的调用backgroundFlushCommits操作促使缓冲池中的

Tomcat源码分析之—具体启动流程分析

从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息.Catalina.base信息,在initClassLoaders方法中初始化类加载器,然后通过反射初始化org.apache.catalina.startup.Catalina作为catalina守护进程: 一.load Bootstrap中load流程: 反射调用Catalina的load方法

angularjs源码分析之:angularjs执行流程

angularjs用了快一个月了,最难的不是代码本身,而是学会怎么用angular的思路思考问题.其中涉及到很多概念,比如:directive,controller,service,compile,link,scope,isolate scope,双向绑定,mvvm等.最近准备把这些都慢慢搞懂,分析源码并贴到博客园,如有分析不对的地方,还望各位包容并指正. angularjs源码分析之:angularjs执行流程 先上个大图,有个大概印象,注:angularjs的版本为:1.2.1,通过bowe

openVswitch(OVS)源码分析之工作流程(哈希桶结构体的解释)

这篇blog是专门解决前篇openVswitch(OVS)源码分析之工作流程(哈希桶结构体的疑惑)中提到的哈希桶结构flex_array结构体成员变量含义的问题. 引用下前篇blog中分析讨论得到的flex_array结构体成员变量的含义结论: struct { int element_size; // 这是flex_array_part结构体存放的哈希头指针的大小 int total_nr_elements; // 这是全部flex_array_part结构体中的哈希头指针的总个数 int e