Thin device data structure type DevInfo struct {Hash string ' JSON: "-" ' DeviceId int ' json: "device_id" ' Size UInt64 ' JSON: ' Size ' ' TransactionID uint64 ' json: ' transaction_id ' ' Initialized bool ' JSON: ' Initializ Ed "' Devices *deviceset ' JSON:"-"' Mountcount int ' json:"-"' Mountpath string ' JSON:"-"' Lock sync." Mutex ' JSON: '-' '}//thin pool data structure type Deviceset struct {metadata//root directory, default =/var/lib/docker/devicemapperroot Stri ng//create a prefix for thin device name, using ' Docker-${major}:${minor}-${inode}-xxx-pool ' Deviceprefix Stringtransactionid by default Uint64newtransactionid uint64nextdeviceid int//option dataloopbacksize Int64///var/lib/docker/devicemapper/devicemapp Er/data sparse File Size metadataloopbacksize int64///var/lib/docker/devicemapper/devicemapper/metadata sparse file size basefssize uint //base image formatted file system size filesystem string//base Image format File system type Mountoptions Stringmkfsargs []string//options when formatting the base image file System DataDevice string//specifies which device to use as the data device,eg,/dev/sdametadatadevice string//specifies which device to use as the metadata Device,eg,/dev/sdadoblkdisc ARD boolthinpblocksize Uint32//thin pool block size}//devmapper Driver data structure type Driver struct {*devicesethom E string//home defaults to/var/lib/docker/devicemapper}
The way Docker uses device Mapper architecture:
Initialize devicemapper driver//home=/var/lib/docker/devicemapper//options=device mapper option//Call Path:newdevice-> initfunc1.1 func Init (Home string, Options []string) (Graphdriver. Driver, error) {//Initialize Devicesetdeviceset, err: = Newdeviceset (Home, true, options) if err! = Nil {return nil, err}...d: = &A Mp;driver{deviceset:deviceset,home:home,}return D, nil}//initialize Deviceset//device set Root=/var/lib/docker/devicemappe r//Call Path: init->newdeviceset1.2 func newdeviceset (root string, doinit bool, options []string) (*deviceset, error) { Setdevdir ("/dev") Devices: = &deviceset{root:root,//metadata The configuration information for thin device is stored via DeviceID metadata: Metadata{devices:make (Map[string]*devinfo)},dataloopbacksize:defaultdataloopbacksize,metadataloopbacksize:d Efaultmetadataloopbacksize,basefssize:defaultbasefssize,filesystem: "Ext4", doblkdiscard:true , thinpblocksize:defaultthinpblocksize,}//initialize deviceset option parameter 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)}}//continues to complete initialization by Deviceset if err: = Devices.initdevmapper (Doinit); Err! = Nil {return nil, err}return devices, nil}//initialize thin pool//call path: newdeviceset->initdevmapper1.3 func (Devices *dev Iceset) Initdevmapper (doinit bool) error {LogInit (Devices)//Create/var/lib/docker/devicemapper/metadata directory If err: = OS. Mkdirall (Devices.metadatadir (), 0700); Err! = Nil &&!os. Isexist (Err) {return err}//gets the inodest of the device where the/var/lib/docker directory resides, 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 naming rules docker-$major: $minor-$inode-$imageid/$containerid//thin poll named docker-$major: $minor-$ Inode-pooldevices.deviceprefix = FMT. SprinTF ("docker-%d:%d-%d", Major (Sysst.dev), minor (Sysst.dev), Sysst.ino)//If thin pool device is present, get information about device Utils. DEBUGF ("Checking for existence of the pool '%s '", Devices.getpoolname ()) info, err: = GetInfo (Devices.getpoolname ()) if INF o = = Nil {utils. DEBUGF ("Error device GetInfo:%s", err) return err}setcloseonexec ("/dev/mapper/control") Createdloopback: = false// Create thin Poolif info. Exists = = 0 {utils. DEBUGF ("Pool doesn ' t exist. Creating it. ") var (datafile *os. Filemetadatafile *os. File)//Not specified DataDevice device if Devices.datadevice = = "" {//Check/var/lib/docker/devicemapper/devicemapper/ Data file exists HasData: = Devices.hasimage ("data")//does not require initialization of new devicemapper, and no old data file if!doinit &&!hasdata {// Returns the error return errors. New ("Loopback data File not found")}//Create data loopdeviceif!hasdata {createdloopback = true}//Create/var/lib/docker/ Devicemapper/devicemapper/data sparse file data, err: = Devices.ensureimage ("Data", devices.dataloopbacksize) if err! = Nil { Utils. DEBUGF ("Error device Ensureimage (data):%s\n", err) RetuRN Err}//data file associated with loopback device datafile, err = attachloopdevice (data) if err! = Nil {return Err}} else {//If data Devic is specified E, open datafile, err = os. OpenFile (Devices.datadevice, OS. O_RDWR, 0600) if err! = Nil {return err}}defer datafile.close ()//Initialize metadata device...//by the same method without creating a new loopback device, then from the directory /var/lib/docker/devicemapper/metadata/$ids//load old Metadataif!createdloopback {if err = Devices.initmetadata (); Err! = Nil {return err}}//Initializes a new empty image file as an ancestor mirror for all mirrors if Doinit {if err: = Devices.setupbaseimage (); Err! = nil {utils. DEBUGF ("Error device setupbaseimage:%s\n", err) return Err}}return nil}//create ancestor Mirror 1.4 func (Devices *deviceset) Setupbaseimage () error {//ancestor image description information is stored in/var/lib/docker/devicemapper/metadata/baseoldinfo, _: = Devices.lookupdevice ( "")//has been created before, and completed initialization, the direct successful return if oldinfo! = Nil && oldinfo.initialized {return nil}//created, but not completed initialization, delete base Deviceif Oldinfo! = Nil &&!oldinfo.initialized {utils. DEBUGF ("Removing uninitialized base image") If err: = Devices.deletedevice (Oldinfo); Err! = Nil {return err}}//next available Deviceidid: = devices.nextdeviceid//Create base deviceif err: = CreateDevice ( Devices.getpooldevname (), &id); Err! = Nil {return Err}devices.nextdeviceid = (id + 1) & 0xffffff//to Thin pool to register base deviceutils. 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}//activate base Deviceif err = Devi ces.activatedeviceifneeded (info); Err! = Nil {return err}//on base device to format the new file system if err: = Devices.createfilesystem (info); Err! = Nil {return err}//complete initialization, save metadata to/var/lib/docker/devicemapper/metadata/base info. Initialized = Trueif Err = devices.savemetadata (info); Err! = Nil {info. Initialized = Falsereturn Err}return Nil}