//	在thin pool中创建一个新thin device
// 调用路径:driver.Create()
1.1 func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
//查找父device
baseInfo, err := devices.lookupDevice(baseHash)
if err != nil {
return err
} baseInfo.lock.Lock()
defer baseInfo.lock.Unlock() devices.Lock()
defer devices.Unlock() //检查imageid/containerid相应的image是否存在
if info, _ := devices.lookupDevice(hash); info != nil {
return fmt.Errorf("device %s already exists", hash)
} deviceId := devices.nextDeviceId //创建父设备的镜像
if err := createSnapDevice(devices.getPoolDevName(), &deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil {
utils.Debugf("Error creating snap device: %s\n", err)
return err
}
//创建thin device的DevInfo。并保存信息到/var/lib/docker/devicemapper/metadata/$id文件里
if _, err := devices.registerDevice(deviceId, hash, baseInfo.Size); err != nil {
deleteDevice(devices.getPoolDevName(), deviceId)
utils.Debugf("Error registering device: %s\n", err)
return err
}
return nil
} // 创建镜像文件的快照
// libdevmapper通过发送msg发送命令
// 调用路径:AddDevice->createSnapDevice
1.2 func createSnapDevice(poolName string, deviceId *int, baseName string, baseDeviceId int) error {
devinfo, _ := getInfo(baseName)
doSuspend := devinfo != nil && devinfo.Exists != 0 //设备存在,则在快照前要先挂起父设备
if doSuspend {
if err := suspendDevice(baseName); err != nil {
return err
}
} for {
//创建task,libdevmapper通过msg传递命令
task, err := createTask(DeviceTargetMsg, poolName)
if task == nil {
//创建task失败,恢复父device
if doSuspend {
resumeDevice(baseName)
}
return err
} if err := task.SetSector(0); err != nil {
if doSuspend {
resumeDevice(baseName)
}
return fmt.Errorf("Can't set sector %s", err)
} //发送创建命令
if err := task.SetMessage(fmt.Sprintf("create_snap %d %d", *deviceId, baseDeviceId)); err != nil {
if doSuspend {
resumeDevice(baseName)
}
return fmt.Errorf("Can't set message %s", err)
} dmSawExist = false
if err := task.Run(); err != nil {
//deviceid已存在。继续尝试下一个id
if dmSawExist {
*deviceId++
continue
} if doSuspend {
resumeDevice(baseName)
}
return fmt.Errorf("Error running DeviceCreate (createSnapDevice) %s", err)
} break
}
//创建成功。恢复父设备
if doSuspend {
if err := resumeDevice(baseName); err != nil {
return err
}
} return nil
} // 注冊thin device信息
// 加入devinfo到devices.Devices哈希表,并保存devinfo到/var/lib/docker/devicemapper/metadata/$id文件
// 调用路径:AddDevice->registerDevice
1.3 func (devices *DeviceSet) registerDevice(id int, hash string, size uint64) (*DevInfo, error) { info := &DevInfo{
Hash: hash,
DeviceId: id,
Size: size,
//分配一个新的transactionid
TransactionId: devices.allocateTransactionId(),
Initialized: false,
devices: devices,
} devices.devicesLock.Lock()
//加入devinfo到hash表
devices.Devices[hash] = info
devices.devicesLock.Unlock() //保存devinfo到/var/lib/docker/devicemapper/metadata/$id文件
if err := devices.saveMetadata(info); err != nil {
devices.devicesLock.Lock()
delete(devices.Devices, hash)
devices.devicesLock.Unlock()
return nil, err
} return info, nil
} // 删除设备
// 调用路径:driver.Remove()
2.1 func (devices *DeviceSet) DeleteDevice(hash string) error {
//检查设备是否存在
info, err := devices.lookupDevice(hash)
if err != nil {
return err
} info.lock.Lock()
defer info.lock.Unlock() devices.Lock()
defer devices.Unlock()
//传递devinfo,删除设备
return devices.deleteDevice(info) // 删除设备
// 1.discard thin device的block
// 2.传递device name删除设备名
// 3.传递device id删除设备
// 4.删除/var/lib/docker/devicemapper/metadata/$id文件
// 调用路径:DeleteDevice->deleteDevice
2.2 func (devices *DeviceSet) deleteDevice(info *DevInfo) error {
//删除设备时,discard其占用的block
if devices.doBlkDiscard {
//激活thin device设备
if err := devices.activateDeviceIfNeeded(info); err == nil {
//discard设备占用的block
if err := BlockDeviceDiscard(info.DevName()); err != nil {
utils.Debugf("Error discarding block on device: %s (ignoring)\n", err)
}
}
} devinfo, _ := getInfo(info.Name())
if devinfo != nil && devinfo.Exists != 0 {
//传递thin device名(docker-$major:$minor-$inode-$id)给libdevmapper,删除设备名
if err := devices.removeDeviceAndWait(info.Name()); err != nil {
utils.Debugf("Error removing device: %s\n", err)
return err
}
} //通过thin device id删除设备
if err := deleteDevice(devices.getPoolDevName(), info.DeviceId); err != nil {
utils.Debugf("Error deleting device: %s\n", err)
return err
} devices.allocateTransactionId()
devices.devicesLock.Lock()
//从内存中删除devinfo
delete(devices.Devices, info.Hash)
devices.devicesLock.Unlock() //删除/var/lib/docker/devicemapper/metadata/$id文件
if err := devices.removeMetadata(info); err != nil {
devices.devicesLock.Lock()
devices.Devices[info.Hash] = info
devices.devicesLock.Unlock()
utils.Debugf("Error removing meta data: %s\n", err)
return err
} return nil
} // 挂载设备到指定路径
// hash指定要挂载的thin device id
// path指定要挂载到的路径
// 一个thin device能够被多次挂载到同一个路径
// 调用路径:driver.Get()
3.1 func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
info, err := devices.lookupDevice(hash)
if err != nil {
return err
} info.lock.Lock()
defer info.lock.Unlock() devices.Lock()
defer devices.Unlock() //thin device不同意被挂载到多个不同路径
if info.mountCount > 0 {
if path != info.mountPath {
return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path)
} info.mountCount++
return nil
}
//激活设备
if err := devices.activateDeviceIfNeeded(info); err != nil {
return fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err)
} var flags uintptr = syscall.MS_MGC_VAL //获取thin device上文件系统的类型
//info.DevName()传递
fstype, err := ProbeFsType(info.DevName())
if err != nil {
return err
} options := "" //通过--storage-option 传递的mount选项
options = joinMountOptions(options, devices.mountOptions)
options = joinMountOptions(options, label.FormatMountLabel("", mountLabel)) //mount thin device到指定path
err = syscall.Mount(info.DevName(), path, fstype, flags, joinMountOptions("discard", options))
if err != nil && err == syscall.EINVAL {
err = syscall.Mount(info.DevName(), path, fstype, flags, options)
}
if err != nil {
return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err)
} info.mountCount = 1
info.mountPath = path return nil
} // 解挂thin device
// hash为imageid或containerid
// 直到挂载计数=0时才真正解挂
// 调用路径:driver.Put()
4.1 func (devices *DeviceSet) UnmountDevice(hash string) error { //查找devinfo
info, err := devices.lookupDevice(hash)
if err != nil {
return err
} info.lock.Lock()
defer info.lock.Unlock() devices.Lock()
defer devices.Unlock() //挂载了不止一次,成功返回
info.mountCount--
if info.mountCount > 0 {
return nil
} //从指定路径解挂
if err := syscall.Unmount(info.mountPath, 0); err != nil {
return err
}
//停止设备
if err := devices.deactivateDevice(info); err != nil {
return err
} info.mountPath = "" return nil
} // 停止thin device
// 等待thin device从/var/lib/docker/devicemapper/mnt/$id解挂,删除thin device名
// 调用路径:UnmountDevice->deactivateDevice
4.2 func (devices *DeviceSet) deactivateDevice(info *DevInfo) error { //等待thin device解挂。通过device id获取设备信息。打开计数降到0
if err := devices.waitClose(info); err != nil {
utils.Errorf("Warning: error waiting for device %s to close: %s\n", info.Hash, err)
} devinfo, err := getInfo(info.Name())
if err != nil {
return err
}
if devinfo.Exists != 0 {
//删除设备名
if err := devices.removeDeviceAndWait(info.Name()); err != nil {
return err
}
}
return nil
}

graph driver-device mapper-03thin pool基本操作的更多相关文章

  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. 01matplotlib

    一. 简介 1.概念 matplotlib:最流行的Python底层绘图库,主要做数据可视化图表,名字取材于MATLAB,模仿MATLAB构建. 2.作用 1)能将数据进行可视化,更直观的呈现 2)使 ...

  2. Windows环境下安装 mysql-8.0.11-winx64 遇到的问题解决办法

    下载mysql安装包,我的是下载mysql-8.0.11-winx64,解压到你想安装的目录下,然后配置环境(window环境下,mac本还没试过), 1.首先,配置环境:右击此电脑->属性-& ...

  3. mysql 删除恢复

    一.模拟误删除数据表的恢复 1 二进制日志功能启用 vim /etc/my.cnf [mysqld] log-bin 2  完全备份 mysqldump -A -F --master-data=2 - ...

  4. jquery中的全选,全不选

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. STM32F407 外部中断 个人笔记

    IO口 STM32F4有上百个IO口中,每个都可以作为外部中断输入 中断线 STM32F4的中断控制器支持22个外部中断/事件请求(中断线) 对于每个中断线,我们可以设置相应的触发方式(上升沿触发,下 ...

  6. 自动化项目配置或用例文件格式推荐--yaml

    关于yaml YAML语言的设计目标,就是方便人类读写.如果你想要实现一些用ini不好做到的配置,可以使用yaml格式作为配置文件 大小写敏感 使用缩进表示层级关系 缩进时不允许使用Tab键,只允许使 ...

  7. [codeforces551E]GukiZ and GukiZiana

    [codeforces551E]GukiZ and GukiZiana 试题描述 Professor GukiZ was playing with arrays again and accidenta ...

  8. java中filter的用法

    filter过滤器主要使用于前台向后台传递数据是的过滤操作.程度很简单就不说明了,直接给几个已经写好的代码: 一.使浏览器不缓存页面的过滤器 Java代码   import javax.servlet ...

  9. Codeforces889C. Maximum Element

    $n \leq 2000000$的排列,问有多少满足:存在个$i$,使得$p_i \neq n$,且$p_j<p_i,j \in [i+1,i+K]$,$K \leq 2000000$是给定常数 ...

  10. BZOJ2196: [Usaco2011 Mar]Brownie Slicing

    n<=500 * m<=500的方阵,先沿横坐标切A-1刀,再把每一块切B-1刀,得到A*B块,求这A*B块的数字之和的最小值的最大值. 最小值最大--二分,然后贪心切.每次扫一行,看这一 ...