1. // thin device数据结构
  2. type DevInfo struct {
  3. Hash string `json:"-"`
  4. DeviceId int `json:"device_id"`
  5. Size uint64 `json:"size"`
  6. TransactionId uint64 `json:"transaction_id"`
  7. Initialized bool `json:"initialized"`
  8. devices *DeviceSet `json:"-"`
  9.  
  10. mountCount int `json:"-"`
  11. mountPath string `json:"-"`
  12. lock sync.Mutex `json:"-"`
  13. }
  14.  
  15. // thin pool数据结构
  16. type DeviceSet struct {
  17. MetaData
  18. //根文件夹,默觉得/var/lib/docker/devicemapper
  19. root string
  20. //创建thin device名字使用的前缀,`docker-${major}:${minor}-${inode}`
  21. devicePrefix string
  22.  
  23. TransactionId uint64
  24. NewTransactionId uint64
  25. nextDeviceId int
  26.  
  27. //选项
  28. dataLoopbackSize int64 ///var/lib/docker /devicemapper/devicemapper/data稀疏文件大小
  29. metaDataLoopbackSize int64 ///var/lib/docker/devicemapper/devicemapper/metadata稀疏文件大小
  30. baseFsSize uint64 //base image之上格式化的文件系统大小
  31. filesystem string //base image之上格式化的文件系统类型
  32. mountOptions string
  33. mkfsArgs []string //格式化base image文件系统时的选项
  34. dataDevice string //指定使用哪个设备作为data device,eg。/dev/sda
  35. metadataDevice string //指定使用哪个设备作为metadata device,eg。/dev/sda
  36. doBlkDiscard bool
  37. thinpBlockSize uint32 //thin pool block size
  38. }
  39.  
  40. // devmapper的driver数据结构
  41. type Driver struct {
  42. *DeviceSet
  43. home string //home默觉得/var/lib/docker/devicemapper
  44. }
  1. docker使用device mapper的架构方式:

  1. //初始化devicemapper driver
  2. // home=/var/lib/docker/devicemapper
  3. // options=device mapper的选项
  4. // 调用路径:newdevice->initfunc
  5. 1.1 func Init(home string, options []string) (graphdriver.Driver, error) {
  6. //初始化deviceset
  7. deviceSet, err := NewDeviceSet(home, true, options)
  8. if err != nil {
  9. return nil, err
  10. }
  11. ...
  12. d := &Driver{
  13. DeviceSet: deviceSet,
  14. home: home,
  15. }
  16. return d, nil
  17. }
  18.  
  19. //初始化deviceset
  20. // device set root=/var/lib/docker/devicemapper
  21. // 调用路径:Init->NewDeviceSet
  22. 1.2 func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error) {
  23. SetDevDir("/dev")
  24.  
  25. devices := &DeviceSet{
  26. root: root,
  27. //metaData通过deviceID存放thin device的配置信息
  28. MetaData: MetaData{Devices: make(map[string]*DevInfo)},
  29. dataLoopbackSize: DefaultDataLoopbackSize,
  30. metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
  31. baseFsSize: DefaultBaseFsSize,
  32. filesystem: "ext4",
  33. doBlkDiscard: true,
  34. thinpBlockSize: DefaultThinpBlockSize,
  35. }
  36.  
  37. //初始化deviceset选项參数
  38. for _, option := range options {
  39. key, val, err := utils.ParseKeyValueOpt(option)
  40. if err != nil {
  41. return nil, err
  42. }
  43. key = strings.ToLower(key)
  44. switch key {
  45. case "dm.basesize":
  46. size, err := units.RAMInBytes(val)
  47. if err != nil {
  48. return nil, err
  49. }
  50. devices.baseFsSize = uint64(size)
  51. ...
  52. default:
  53. return nil, fmt.Errorf("Unknown option %s\n", key)
  54. }
  55. }
  56.  
  57. //由deviceset继续完毕初始化
  58. if err := devices.initDevmapper(doInit); err != nil {
  59. return nil, err
  60. }
  61.  
  62. return devices, nil
  63. }
  64.  
  65. // 初始化thin pool
  66. // 调用路径:NewDeviceSet->initDevmapper
  67. 1.3 func (devices *DeviceSet) initDevmapper(doInit bool) error {
  68. logInit(devices)
  69.  
  70. //创建/var/lib/docker/devicemapper/metadata文件夹
  71. if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
  72. return err
  73. }
  74.  
  75. //获取/var/lib/docker文件夹所在设备的 inode
  76. st, err := os.Stat(devices.root)
  77. if err != nil {
  78. return fmt.Errorf("Error looking up dir %s: %s", devices.root, err)
  79. }
  80. sysSt := st.Sys().(*syscall.Stat_t)
  81.  
  82. //thin device取名规则docker-$major:$minor-$inode-$imageid/$containerid
  83. //thin poll取名为docker-$major:$minor-$inode-pool
  84. devices.devicePrefix = fmt.Sprintf("docker-%d:%d-%d", major(sysSt.Dev), minor(sysSt.Dev), sysSt.Ino)
  85.  
  86. //假设thin pool device存在,获取device的信息
  87. utils.Debugf("Checking for existence of the pool '%s'", devices.getPoolName())
  88. info, err := getInfo(devices.getPoolName())
  89. if info == nil {
  90. utils.Debugf("Error device getInfo: %s", err)
  91. return err
  92. }
  93.  
  94. setCloseOnExec("/dev/mapper/control")
  95. createdLoopback := false
  96.  
  97. //创建thin pool
  98. if info.Exists == 0 {
  99. utils.Debugf("Pool doesn't exist. Creating it.")
  100.  
  101. var (
  102. dataFile *os.File
  103. metadataFile *os.File
  104. )
  105.  
  106. //没有指定datadevice设备
  107. if devices.dataDevice == "" {
  108.  
  109. //检查/var/lib/docker/devicemapper/devicemapper/data文件是否存在
  110. hasData := devices.hasImage("data")
  111.  
  112. //既不要求初始化新的devicemapper,又没有旧的data文件
  113. if !doInit && !hasData {
  114. //返回错误
  115. return errors.New("Loopback data file not found")
  116. }
  117.  
  118. //创建data loopdevice
  119. if !hasData {
  120. createdLoopback = true
  121. }
  122.  
  123. //创建/var/lib/docker/devicemapper/devicemapper/data 稀疏文件
  124. data, err := devices.ensureImage("data", devices.dataLoopbackSize)
  125. if err != nil {
  126. utils.Debugf("Error device ensureImage (data): %s\n", err)
  127. return err
  128. }
  129.  
  130. //data文件与loopback device关联
  131. dataFile, err = attachLoopDevice(data)
  132. if err != nil {
  133. return err
  134. }
  135. } else {
  136. //假设指定了data device,则打开
  137. dataFile, err = os.OpenFile(devices.dataDevice, os.O_RDWR, 0600)
  138. if err != nil {
  139. return err
  140. }
  141. }
  142. defer dataFile.Close()
  143.  
  144. //通过相同的办法初始化metadata device
  145. ...
  146.  
  147. //创建thin pool
  148. if err := createPool(devices.getPoolName(), dataFile, metadataFile, devices.thinpBlockSize); err != nil {
  149. return err
  150. }
  151.  
  152. //没有创建新loopback device,则从文件夹/var/lib/docker/devicemapper/metadata/$ids
  153. //载入旧的metadata
  154. if !createdLoopback {
  155. if err = devices.initMetaData(); err != nil {
  156. return err
  157. }
  158. }
  159.  
  160. //初始化一个新的空镜像文件,作为全部镜像的祖先镜像
  161. if doInit {
  162. if err := devices.setupBaseImage(); err != nil {
  163. utils.Debugf("Error device setupBaseImage: %s\n", err)
  164. return err
  165. }
  166. }
  167. return nil
  168. }
  169.  
  170. // 创建祖先镜像
  171. 1.4 func (devices *DeviceSet) setupBaseImage() error {
  172. //祖先镜像的描写叙述信息存放在/var/lib/docker/devicemapper/metadata/base
  173. oldInfo, _ := devices.lookupDevice("")
  174. //之前已经创建。并完毕了初始化。则直接成功返回
  175. if oldInfo != nil && oldInfo.Initialized {
  176. return nil
  177. }
  178. //已创建。但未完毕初始化,删除base device
  179. if oldInfo != nil && !oldInfo.Initialized {
  180. utils.Debugf("Removing uninitialized base image")
  181. if err := devices.deleteDevice(oldInfo); err != nil {
  182. return err
  183. }
  184. }
  185.  
  186. //下一个可用的deviceid
  187. id := devices.nextDeviceId
  188.  
  189. //创建base device
  190. if err := createDevice(devices.getPoolDevName(), &id); err != nil {
  191. return err
  192. }
  193.  
  194. devices.nextDeviceId = (id + 1) & 0xffffff
  195.  
  196. //向thin pool注冊base device
  197. utils.Debugf("Registering base device (id %v) with FS size %v", id, devices.baseFsSize)
  198. info, err := devices.registerDevice(id, "", devices.baseFsSize)
  199. if err != nil {
  200. _ = deleteDevice(devices.getPoolDevName(), id)
  201. return err
  202. }
  203.  
  204. //激活base device
  205. if err = devices.activateDeviceIfNeeded(info); err != nil {
  206. return err
  207. }
  208.  
  209. //在base device之上格式化新文件系统
  210. if err := devices.createFilesystem(info); err != nil {
  211. return err
  212. }
  213.  
  214. //完毕初始化,保存metadata到/var/lib/docker/devicemapper/metadata/base中
  215. info.Initialized = true
  216. if err = devices.saveMetadata(info); err != nil {
  217. info.Initialized = false
  218. return err
  219. }
  220.  
  221. return nil
  222. }

graph driver-device mapper-01driver初始化的更多相关文章

  1. Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

  2. [转] Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

  3. Linux kernel device mapper

    Device Mapper 是 Linux2.6 内核中支持逻辑卷管理的通用设备映射机制,它为实现用于存储资源管理的块设备驱动提供了一个高度模块化的内核架构,如图 1. 图1 Device Mappe ...

  4. Docker存储驱动之Device Mapper简介

    Device Mapper是一个基于kernel的框架,它增强了很多Linux上的高级卷管理技术.Docker的devicemapper驱动在镜像和容器管理上,利用了该框架的超配和快照功能.为了区别, ...

  5. Docker Device Mapper 使用 direct-lvm

      一.Device Mapper: loop-lvm 默认 CentOS7 下 Docker 使用的 Device Mapper 设备默认使用 loopback 设备,后端为自动生成的稀疏文件,如下 ...

  6. flashcache中应用device mapper机制

    Device Mapper(DM)是Linux 2.6全面引入的块设备新构架,通过DM可以灵活地管理系统中所有的真实或虚拟的块设备. DM以块设备的形式注册到Linux内核中,凡是挂载(或者说“映射” ...

  7. Device Mapper 代码分析

    Device Mapper(DM)是Linux 2.6全面引入的块设备新构架,通过DM可以灵活地管理系统中所有的真实或虚拟的块设备. DM以块设备的形式注册到Linux内核中,凡是挂载(或者说&quo ...

  8. Linux系统中的Device Mapper学习

    在linux系统中你使用一些命令时(例如nmon.iostat 如下截图所示),有可能会看到一些名字为dm-xx的设备,那么这些设备到底是什么设备呢,跟磁盘有什么关系呢?以前不了解的时候,我也很纳闷. ...

  9. 使用 Device Mapper来改变Docker容器的大小

    作者:Jérôme Petazzoni ( Docker 布道师) 译者:Mark Shao ( EMC 中国高级工程师) 如果在 CentOS . REHL . Fedor 或者其他默认没有 AUF ...

  10. Device Mapper Multipath(DM-Multipath)

    Device Mapper Multipath(DM-Multipath)能够将server节点和存储阵列之间的多条I/O链路配置为一个单独的设备.这些I/O链路是由不同的线缆.交换机.控制器组成的S ...

随机推荐

  1. 用VC制作应用程序启动画面

    摘 要:本文提供了四种启动画面制作方法. 使用启动画面一是可以减少等待程序加载过程中的枯燥感(尤其是一些大型程序):二是 可以用来显示软件名称和版权等提示信息.怎样使用VC++制作应用程序的启动画面呢 ...

  2. 动态修改PE文件图标(使用UpdateResource API函数)

    PE文件的图标存储在资源文件中,而操作资源要用到的API函数就是UpdateResource首先我们需要先了解一下ICO格式,参考资料:http://www.moon-soft.com/program ...

  3. 14.6.1 Creating InnoDB Tables 创建InnoDB 表:

    14.6.1 Creating InnoDB Tables 创建InnoDB 表: 创建一个InnoDB 表,使用CREATE TABLE 语句,你不需要指定 ENGINE=InnoDB子句 如果In ...

  4. Find命令, find用法,

    Find命令 用法示例:查找HOME目录下大于1M小于10M的文件$ find ~ -size +1M -size -10M 15个小时这一时刻修改的文件:find . -mmin 900 | xar ...

  5. Git权威指南学习笔记(二)Git暂存区

    例如以下图所看到的: 左側为工作区,是我们的工作文件夹. 右側为版本号库,当中: index标记的是暂存区(stage),所处文件夹为.git/index,记录了文件的状态和变更信息. master标 ...

  6. Swift - 使用UIWebView和UIToolbar制作一个浏览器

    使用网页控件(UIWebView)与工具栏控件(UIToolbar),我们可以自制一个小型的浏览器,其功能如下: 1,输入网址,点击“Go”按钮加载网页 2,加载过程中有进度条,同时可以点击停止按钮取 ...

  7. A*寻路算法的实现

    原理:http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html 算法理论请到原理这个传送门,代码中的注释,已经比较详细,所以我不会讲 ...

  8. ThinkPhp学习10

    原文:ThinkPhp学习10 查询操作 Action模块 User下的search public function search(){ //判断username是否已经传入,且不为空 if(isse ...

  9. 五、Linux/UNIX操作命令积累【cp、mv、cat、grep、ps】

    在使用Linux/UNIX下,常常会使用文本界面去设置系统或操作系统,作者本人在工作的过程也在不断接触这方面的命令,所以为此特酝酿.准备.開始了本文的编写.本文主要记录自己平时遇到的一些Linux/U ...

  10. 在HTML中如何隐藏某段文字具体该怎么实现

    <p style="display:none;"> 需要隐藏的文字....... </p> <div style="display:none ...