// thin device数据结构
type DevInfo struct {
Hash string `json:"-"`
DeviceId int `json:"device_id"`
Size uint64 `json:"size"`
TransactionId uint64 `json:"transaction_id"`
Initialized bool `json:"initialized"`
devices *DeviceSet `json:"-"` mountCount int `json:"-"`
mountPath string `json:"-"`
lock sync.Mutex `json:"-"`
} // thin pool数据结构
type DeviceSet struct {
MetaData
//根文件夹,默觉得/var/lib/docker/devicemapper
root string
//创建thin device名字使用的前缀,`docker-${major}:${minor}-${inode}`
devicePrefix string TransactionId uint64
NewTransactionId uint64
nextDeviceId int //选项
dataLoopbackSize int64 ///var/lib/docker /devicemapper/devicemapper/data稀疏文件大小
metaDataLoopbackSize int64 ///var/lib/docker/devicemapper/devicemapper/metadata稀疏文件大小
baseFsSize uint64 //base image之上格式化的文件系统大小
filesystem string //base image之上格式化的文件系统类型
mountOptions string
mkfsArgs []string //格式化base image文件系统时的选项
dataDevice string //指定使用哪个设备作为data device,eg。/dev/sda
metadataDevice string //指定使用哪个设备作为metadata device,eg。/dev/sda
doBlkDiscard bool
thinpBlockSize uint32 //thin pool block size
} // devmapper的driver数据结构
type Driver struct {
*DeviceSet
home string //home默觉得/var/lib/docker/devicemapper
}
docker使用device mapper的架构方式:

//初始化devicemapper driver
// home=/var/lib/docker/devicemapper
// options=device mapper的选项
// 调用路径:newdevice->initfunc
1.1 func Init(home string, options []string) (graphdriver.Driver, error) {
//初始化deviceset
deviceSet, err := NewDeviceSet(home, true, options)
if err != nil {
return nil, err
}
...
d := &Driver{
DeviceSet: deviceSet,
home: home,
}
return d, nil
} //初始化deviceset
// device set root=/var/lib/docker/devicemapper
// 调用路径:Init->NewDeviceSet
1.2 func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error) {
SetDevDir("/dev") devices := &DeviceSet{
root: root,
//metaData通过deviceID存放thin device的配置信息
MetaData: MetaData{Devices: make(map[string]*DevInfo)},
dataLoopbackSize: DefaultDataLoopbackSize,
metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
baseFsSize: DefaultBaseFsSize,
filesystem: "ext4",
doBlkDiscard: true,
thinpBlockSize: DefaultThinpBlockSize,
} //初始化deviceset选项參数
for _, option := range options {
key, val, err := utils.ParseKeyValueOpt(option)
if err != nil {
return nil, err
}
key = strings.ToLower(key)
switch key {
case "dm.basesize":
size, err := units.RAMInBytes(val)
if err != nil {
return nil, err
}
devices.baseFsSize = uint64(size)
...
default:
return nil, fmt.Errorf("Unknown option %s\n", key)
}
} //由deviceset继续完毕初始化
if err := devices.initDevmapper(doInit); err != nil {
return nil, err
} return devices, nil
} // 初始化thin pool
// 调用路径:NewDeviceSet->initDevmapper
1.3 func (devices *DeviceSet) initDevmapper(doInit bool) error {
logInit(devices) //创建/var/lib/docker/devicemapper/metadata文件夹
if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
return err
} //获取/var/lib/docker文件夹所在设备的 inode
st, err := os.Stat(devices.root)
if err != nil {
return fmt.Errorf("Error looking up dir %s: %s", devices.root, err)
}
sysSt := st.Sys().(*syscall.Stat_t) //thin device取名规则docker-$major:$minor-$inode-$imageid/$containerid
//thin poll取名为docker-$major:$minor-$inode-pool
devices.devicePrefix = fmt.Sprintf("docker-%d:%d-%d", major(sysSt.Dev), minor(sysSt.Dev), sysSt.Ino) //假设thin pool device存在,获取device的信息
utils.Debugf("Checking for existence of the pool '%s'", devices.getPoolName())
info, err := getInfo(devices.getPoolName())
if info == nil {
utils.Debugf("Error device getInfo: %s", err)
return err
} setCloseOnExec("/dev/mapper/control")
createdLoopback := false //创建thin pool
if info.Exists == 0 {
utils.Debugf("Pool doesn't exist. Creating it.") var (
dataFile *os.File
metadataFile *os.File
) //没有指定datadevice设备
if devices.dataDevice == "" { //检查/var/lib/docker/devicemapper/devicemapper/data文件是否存在
hasData := devices.hasImage("data") //既不要求初始化新的devicemapper,又没有旧的data文件
if !doInit && !hasData {
//返回错误
return errors.New("Loopback data file not found")
} //创建data loopdevice
if !hasData {
createdLoopback = true
} //创建/var/lib/docker/devicemapper/devicemapper/data 稀疏文件
data, err := devices.ensureImage("data", devices.dataLoopbackSize)
if err != nil {
utils.Debugf("Error device ensureImage (data): %s\n", err)
return err
} //data文件与loopback device关联
dataFile, err = attachLoopDevice(data)
if err != nil {
return err
}
} else {
//假设指定了data device,则打开
dataFile, err = os.OpenFile(devices.dataDevice, os.O_RDWR, 0600)
if err != nil {
return err
}
}
defer dataFile.Close() //通过相同的办法初始化metadata device
... //创建thin pool
if err := createPool(devices.getPoolName(), dataFile, metadataFile, devices.thinpBlockSize); err != nil {
return err
} //没有创建新loopback device,则从文件夹/var/lib/docker/devicemapper/metadata/$ids
//载入旧的metadata
if !createdLoopback {
if err = devices.initMetaData(); err != nil {
return err
}
} //初始化一个新的空镜像文件,作为全部镜像的祖先镜像
if doInit {
if err := devices.setupBaseImage(); err != nil {
utils.Debugf("Error device setupBaseImage: %s\n", err)
return err
}
}
return nil
} // 创建祖先镜像
1.4 func (devices *DeviceSet) setupBaseImage() error {
//祖先镜像的描写叙述信息存放在/var/lib/docker/devicemapper/metadata/base
oldInfo, _ := devices.lookupDevice("")
//之前已经创建。并完毕了初始化。则直接成功返回
if oldInfo != nil && oldInfo.Initialized {
return nil
}
//已创建。但未完毕初始化,删除base device
if oldInfo != nil && !oldInfo.Initialized {
utils.Debugf("Removing uninitialized base image")
if err := devices.deleteDevice(oldInfo); err != nil {
return err
}
} //下一个可用的deviceid
id := devices.nextDeviceId //创建base device
if err := createDevice(devices.getPoolDevName(), &id); err != nil {
return err
} devices.nextDeviceId = (id + 1) & 0xffffff //向thin pool注冊base device
utils.Debugf("Registering base device (id %v) with FS size %v", id, devices.baseFsSize)
info, err := devices.registerDevice(id, "", devices.baseFsSize)
if err != nil {
_ = deleteDevice(devices.getPoolDevName(), id)
return err
} //激活base device
if err = devices.activateDeviceIfNeeded(info); err != nil {
return err
} //在base device之上格式化新文件系统
if err := devices.createFilesystem(info); err != nil {
return err
} //完毕初始化,保存metadata到/var/lib/docker/devicemapper/metadata/base中
info.Initialized = true
if err = devices.saveMetadata(info); err != nil {
info.Initialized = false
return err
} return nil
}

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. Swift - 动画效果的实现方法总结(附样例)

    在iOS中,实现动画有两种方法.一个是统一的animateWithDuration,另一个是组合出现的beginAnimations和commitAnimations.这三个方法都是类方法. 一,使用 ...

  2. 几款屏幕录制软件 ActivePresente

    几款屏幕录制软件,最强大是  ActivePresenter ,免费版, 足以应对我们日常需求.列表如下 支持系统:W-Windows,L-Linux,M-Mac 软件 格式 W L M 免费 说明 ...

  3. (并查集)POJ 1308 & HDU 1325

    一开始以为两道题是一样的,POJ的过了直接用相同代码把HDU的交了,结果就悲剧了.最后发现HDU的没有考虑入度不能大于一. 题意:用树的定义来 判断吧,无环,n个结点最多有n-1条边,不然就会有环.只 ...

  4. POJ 3974 最长回文字串(manacher算法)

    题意:给出一个字符串,求出最长回文字串. 思路:一开始我直接上了后缀数组DC3的解法,然后MLE了.看了DISCUSS发现还有一种计算回文字串更加优越的算法,就是manacher算法.就去学习了一下, ...

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

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

  6. BI中事实表和维度表的定义

    一个典型的样例是,把逻辑业务比作一个立方体,产品维.时间维.地点维分别作为不同的坐标轴,而坐标轴的交点就是一个详细的事实.也就是说事实表是多个维度表的一个交点.而维度表是分析事实的一个窗体. 首先介绍 ...

  7. CentOS 6.5安装Erlang/OTP 17.0

    CentOS 6.5安装Erlang/OTP 17.0 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Erlang眼下已经是Fedora和Debian/ ...

  8. 开源工具DbUtils的使用(数据库的增删改查)

    开源工具DbUtils的使用(数据库的增删改查) 一.DbUtils简介: DBUtils是apache下的一个小巧的JDBC轻量级封装的工具包,其最核心的特性是结果集的封装,可以直接将查询出来的结果 ...

  9. nginx做下载限速

    nginx做下载限速-szszszsz-ChinaUnix博客 nginx做下载限速 2009-12-25 14:34:57 分类: 系统运维 nginx做下载服务器,在性能上满足需求.自带limit ...

  10. memwatch的使用

    博主的新Blog地址:http://www.brantchen.com 欢迎訪问:) linux下的測试工具真是少之又少,还不好用,近期试用了memwatch,感觉网上的介绍不太好,所以放在这里跟大家 ...