【graph driver-device mapper-03thin pool基本操作】古人已用三冬足,年少今开万卷余。这篇文章主要讲述graph driver-device mapper-03thin pool基本操作相关的知识,希望能为你提供帮助。
// 在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 }
推荐阅读
- android 3G移植
- 安卓权威编程 挑战练习13.6
- 打印机打印方式
- 图 华为3COM规范访问控制下文初识
- IPX 访问控制下文
- IP访问控制下文
- 访问控制—保护核心设备中的核心资源
- 局域网网络故障排除策略
- 广电专家称数字电视3千万用户目标不再提及