Create a new thin device//call path in the thin pool: driver. Create () 1.1 func (Devices *deviceset) AddDevice (hash, basehash string) error {//find parent Devicebaseinfo, err: = DEVICES.LOOKUPD Evice (Basehash) if err! = Nil {return Err}baseinfo.lock.lock () defer baseInfo.lock.Unlock () devices. Lock () Defer devices. Unlock ()//check if Imageid/containerid corresponds to an image if there is an if info, _: = Devices.lookupdevice (hash); Info! = Nil {return FMT. Errorf ("Device%s already exists", hash)}deviceid: = devices.nextdeviceid//Creates a mirror of the parent device if err: = Createsnapdevice ( Devices.getpooldevname (), &deviceid, Baseinfo.name (), Baseinfo.deviceid); Err! = Nil {utils. DEBUGF ("Error Creating snap Device:%s\n", err) return err}//creating thin device DevInfo, and saving information to/var/lib/docker/devicemapper/ metadata/$id File 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}//Create snapshot of image file//libdevmapper send msg by sending command// Call Path: Adddevice->createsnapdevice1.2 func createsnapdevice (poolname string, DeviceId *int, baseName string, Basedeviceid int) Error {DevInfo, _: = Getinf O (baseName) Dosuspend: = DevInfo! = Nil && DevInfo. Exists! = 0//device exists, the parent device should be suspended before the snapshot if Dosuspend {if err: = Suspenddevice (baseName); Err! = Nil {return err}}for {//Create Task,libde Vmapper Pass msg Command task, err: = CreateTask (devicetargetmsg, poolname) If task = nil {//Create task failed, restore parent 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)}//send create command 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 already exists, continue to try the next idif dmsawexist {*deviceid++continue}if dosuspend {resumedevice (baseName)}return FMT. Errorf ("Error running Devicecreate (createsnapdevice)%s", err)}break}//creation succeeded, restore parent Device if Dosuspend {if err: = Resumedevice (baseName); Err! = nil {return Err}}return nil}//register thin device information//add DevInfo to Devi Ces. Devices hash table and save DevInfo to/var/lib/docker/devicemapper/metadata/$id file//Call Path: adddevice->registerdevice1.3 func ( Devices *deviceset) registerdevice (id int, hash string, size UInt64) (*devinfo, error) {info: = &devinfo{hash: hash,deviceid:id,size:size,//assigns a new TransactionidTransactionId:devices.allocateTransactionId (), Initializ Ed:false,devices:devices,}devices.deviceslock.lock ()//Add DevInfo to hash table devices. Devices[hash] = Infodevices.devicesLock.Unlock ()//Save DevInfo to/var/lib/docker/devicemapper/metadata/$id file if err: = Devices.savemetadata (info); Err! = Nil {devices.devicesLock.Lock () Delete (devices. Devices, hash) Devices.devicesLock.Unlock () return nil, Err}return info, nil}//delete device//call path: Driver. Remove () 2.1 func (Devices *deviceset) Deletedevice (hash string) error {//check device for presence info, err: = Devices.lookupdevice (hash) If err! = Nil {return ERR}info.lock.lock () defer info.lock.Unlock () devices. Lock () Defer devices. Unlock ()///pass DevInfo, remove device return Devices.deletedevice (info)//delete device//1.discard thin device BLOCK//2. Pass device name to remove the unit name 3. Pass Device ID to remove//4. Delete/var/lib/docker/devicemapper/metadata/$id file//Call path: deletedevice->deletedevice2.2 func (Devices *deviceset) Deletedevice (info *devinfo) Error {//delete device, discard its occupied blockif Devices.doblkdiscard {//Activate thin Device devices If err: = devices.activatedeviceifneeded (info); Err = = Nil {//discard device occupies 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 {//pass thin device name (docker-$major: $minor-$inode-$id) to Libdevmapper, remove the unit name if err: = Devices.removedeviceandwait (info. Name ()); Err! = Nil {utils. DEBUGF ("Error removing Device:%s\n", err) return err}}//remove the device by thin devices ID Err: = Deletedevice ( Devices.getpooldevname (), info. DEVICEID); Err! = NIl {utils. DEBUGF ("Error Deleting device:%s\n", err) return Err}devices.allocatetransactionid () Devices.devicesLock.Lock ()// Remove Devinfodelete from memory (devices. Devices, Info. Hash) Devices.devicesLock.Unlock ()//delete/var/lib/docker/devicemapper/metadata/$id file 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}//mount device to the specified path//hash specify the path to mount to the thin device Id//path specified to mount A thin device can be mounted multiple times to the same path//call path: Driver. Get () 3.1 func (Devices *deviceset) mountdevice (hash, path, Mountlabel string) error {info, err: = Devices.lookupdevice (Has h) If err! = Nil {return Err}info.lock.lock () defer info.lock.Unlock () devices. Lock () Defer devices. Unlock ()//thin device does not allow mounting to multiple different paths 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}// Activate device 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//get thin device on The type of the file system is//info. Devname () passes fstype, err: = Probefstype (info. Devname ()) if err! = Nil {return err}options: = ""//The Mount option passed through--storage-option options = joinmountoptions (Options, Devic es.mountoptions) options = joinmountoptions (options, label. Formatmountlabel ("", Mountlabel))//mount thin device to the specified 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}//unpack thin device//hash for imageID or containerid// Until the mount count = 0 o'clock does not really solve the hang//call path: Driver. Put () 4.1 func (Devices *deviceset) Unmountdevice (hash string) error {//find devinfoinfo, err: = dEvices.lookupdevice (hash) if err! = Nil {return Err}info.lock.lock () defer info.lock.Unlock () devices. Lock () Defer devices. Unlock ()//Mount more than once, successfully return Info.mountcount--if info.mountcount > 0 {return nil}//from the specified path if err: = Syscall. Unmount (Info.mountpath, 0); Err! = Nil {return err}//stop device if err: = Devices.deactivatedevice (info); Err! = Nil {return Err}info.mountpath = "" Return nil}//stop thin device//wait thin device from/var/lib/docker/devicemapper/mnt/$ ID to remove thin device name//call Path: unmountdevice->deactivatedevice4.2 func (Devices *deviceset) Deactivatedevice (Info * DevInfo) Error {//wait for thin device to be hooked up, get device information through the devices ID, turn the count down to 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 {//Remove device name if err: = devices.removedeviceandwait (info. Name ()); Err! = Nil {return Err}}return nil}