github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/daemon/graphdriver/devmapper/driver.go (about) 1 // +build linux 2 3 package devmapper 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path" 10 "strconv" 11 12 "github.com/Sirupsen/logrus" 13 14 "github.com/docker/docker/daemon/graphdriver" 15 "github.com/docker/docker/pkg/devicemapper" 16 "github.com/docker/docker/pkg/idtools" 17 "github.com/docker/docker/pkg/mount" 18 "github.com/docker/go-units" 19 ) 20 21 func init() { 22 graphdriver.Register("devicemapper", Init) 23 } 24 25 // Driver contains the device set mounted and the home directory 26 type Driver struct { 27 *DeviceSet 28 home string 29 uidMaps []idtools.IDMap 30 gidMaps []idtools.IDMap 31 } 32 33 // Init creates a driver with the given home and the set of options. 34 func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { 35 deviceSet, err := NewDeviceSet(home, true, options, uidMaps, gidMaps) 36 if err != nil { 37 return nil, err 38 } 39 40 if err := mount.MakePrivate(home); err != nil { 41 return nil, err 42 } 43 44 d := &Driver{ 45 DeviceSet: deviceSet, 46 home: home, 47 uidMaps: uidMaps, 48 gidMaps: gidMaps, 49 } 50 51 return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil 52 } 53 54 func (d *Driver) String() string { 55 return "devicemapper" 56 } 57 58 // Status returns the status about the driver in a printable format. 59 // Information returned contains Pool Name, Data File, Metadata file, disk usage by 60 // the data and metadata, etc. 61 func (d *Driver) Status() [][2]string { 62 s := d.DeviceSet.Status() 63 64 status := [][2]string{ 65 {"Pool Name", s.PoolName}, 66 {"Pool Blocksize", fmt.Sprintf("%s", units.HumanSize(float64(s.SectorSize)))}, 67 {"Base Device Size", fmt.Sprintf("%s", units.HumanSize(float64(s.BaseDeviceSize)))}, 68 {"Backing Filesystem", s.BaseDeviceFS}, 69 {"Data file", s.DataFile}, 70 {"Metadata file", s.MetadataFile}, 71 {"Data Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Used)))}, 72 {"Data Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Total)))}, 73 {"Data Space Available", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Available)))}, 74 {"Metadata Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Used)))}, 75 {"Metadata Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Total)))}, 76 {"Metadata Space Available", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Available)))}, 77 {"Udev Sync Supported", fmt.Sprintf("%v", s.UdevSyncSupported)}, 78 {"Deferred Removal Enabled", fmt.Sprintf("%v", s.DeferredRemoveEnabled)}, 79 {"Deferred Deletion Enabled", fmt.Sprintf("%v", s.DeferredDeleteEnabled)}, 80 {"Deferred Deleted Device Count", fmt.Sprintf("%v", s.DeferredDeletedDeviceCount)}, 81 } 82 if len(s.DataLoopback) > 0 { 83 status = append(status, [2]string{"Data loop file", s.DataLoopback}) 84 } 85 if len(s.MetadataLoopback) > 0 { 86 status = append(status, [2]string{"Metadata loop file", s.MetadataLoopback}) 87 } 88 if vStr, err := devicemapper.GetLibraryVersion(); err == nil { 89 status = append(status, [2]string{"Library Version", vStr}) 90 } 91 return status 92 } 93 94 // GetMetadata returns a map of information about the device. 95 func (d *Driver) GetMetadata(id string) (map[string]string, error) { 96 m, err := d.DeviceSet.exportDeviceMetadata(id) 97 98 if err != nil { 99 return nil, err 100 } 101 102 metadata := make(map[string]string) 103 metadata["DeviceId"] = strconv.Itoa(m.deviceID) 104 metadata["DeviceSize"] = strconv.FormatUint(m.deviceSize, 10) 105 metadata["DeviceName"] = m.deviceName 106 return metadata, nil 107 } 108 109 // Cleanup unmounts a device. 110 func (d *Driver) Cleanup() error { 111 err := d.DeviceSet.Shutdown(d.home) 112 113 if err2 := mount.Unmount(d.home); err == nil { 114 err = err2 115 } 116 117 return err 118 } 119 120 // CreateReadWrite creates a layer that is writable for use as a container 121 // file system. 122 func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error { 123 return d.Create(id, parent, mountLabel, storageOpt) 124 } 125 126 // Create adds a device with a given id and the parent. 127 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error { 128 if err := d.DeviceSet.AddDevice(id, parent, storageOpt); err != nil { 129 return err 130 } 131 132 return nil 133 } 134 135 // Remove removes a device with a given id, unmounts the filesystem. 136 func (d *Driver) Remove(id string) error { 137 if !d.DeviceSet.HasDevice(id) { 138 // Consider removing a non-existing device a no-op 139 // This is useful to be able to progress on container removal 140 // if the underlying device has gone away due to earlier errors 141 return nil 142 } 143 144 // This assumes the device has been properly Get/Put:ed and thus is unmounted 145 if err := d.DeviceSet.DeleteDevice(id, false); err != nil { 146 return err 147 } 148 149 mp := path.Join(d.home, "mnt", id) 150 if err := os.RemoveAll(mp); err != nil && !os.IsNotExist(err) { 151 return err 152 } 153 154 return nil 155 } 156 157 // Get mounts a device with given id into the root filesystem 158 func (d *Driver) Get(id, mountLabel string) (string, error) { 159 mp := path.Join(d.home, "mnt", id) 160 161 uid, gid, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) 162 if err != nil { 163 return "", err 164 } 165 // Create the target directories if they don't exist 166 if err := idtools.MkdirAllAs(path.Join(d.home, "mnt"), 0755, uid, gid); err != nil && !os.IsExist(err) { 167 return "", err 168 } 169 if err := idtools.MkdirAs(mp, 0755, uid, gid); err != nil && !os.IsExist(err) { 170 return "", err 171 } 172 173 // Mount the device 174 if err := d.DeviceSet.MountDevice(id, mp, mountLabel); err != nil { 175 return "", err 176 } 177 178 rootFs := path.Join(mp, "rootfs") 179 if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) { 180 d.DeviceSet.UnmountDevice(id, mp) 181 return "", err 182 } 183 184 idFile := path.Join(mp, "id") 185 if _, err := os.Stat(idFile); err != nil && os.IsNotExist(err) { 186 // Create an "id" file with the container/image id in it to help reconstruct this in case 187 // of later problems 188 if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil { 189 d.DeviceSet.UnmountDevice(id, mp) 190 return "", err 191 } 192 } 193 194 return rootFs, nil 195 } 196 197 // Put unmounts a device and removes it. 198 func (d *Driver) Put(id string) error { 199 mp := path.Join(d.home, "mnt", id) 200 err := d.DeviceSet.UnmountDevice(id, mp) 201 if err != nil { 202 logrus.Errorf("devmapper: Error unmounting device %s: %s", id, err) 203 } 204 return err 205 } 206 207 // Exists checks to see if the device exists. 208 func (d *Driver) Exists(id string) bool { 209 return d.DeviceSet.HasDevice(id) 210 }