graph driver-device mapper-03thin pool基本操作
阿新 • • 發佈:2017-07-15
ans sys call del syscall map atm lib join
// 在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基本操作