graph driver-device mapper-03thin pool基本操作

來源:互聯網
上載者:User

標籤:docker   devicemapper   golang   

//在thin pool中建立一個新thin device//調用路徑:driver.Create()1.1 func (devices *DeviceSet) AddDevice(hash, baseHash string) error {//尋找父devicebaseInfo, 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->createSnapDevice1.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失敗,恢複父deviceif 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 = falseif err := task.Run(); err != nil {//deviceid已存在,繼續嘗試下一個idif 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->registerDevice1.3 func (devices *DeviceSet) registerDevice(id int, hash string, size uint64) (*DevInfo, error) {info := &DevInfo{Hash:          hash,DeviceId:      id,Size:          size,//分配一個新的transactionidTransactionId: devices.allocateTransactionId(),Initialized:   false,devices:       devices,}devices.devicesLock.Lock()//添加devinfo到hash表devices.Devices[hash] = infodevices.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->deleteDevice2.2 func (devices *DeviceSet) deleteDevice(info *DevInfo) error {//刪除裝置時,discard其佔用的blockif devices.doBlkDiscard {//啟用thin device裝置if err := devices.activateDeviceIfNeeded(info); err == nil {//discard裝置佔用的blockif 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()//從記憶體中刪除devinfodelete(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] = infodevices.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到指定patherr = 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 = 1info.mountPath = pathreturn nil}//解掛thin device//hash為imageid或containerid//直到掛載計數=0時才真正解掛//調用路徑:driver.Put()4.1 func (devices *DeviceSet) UnmountDevice(hash string) error {//尋找devinfoinfo, 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->deactivateDevice4.2 func (devices *DeviceSet) deactivateDevice(info *DevInfo) error {//等待thin device解掛,通過device id擷取裝置資訊,開啟計數降到0if 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}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.