github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/daemon/graphdriver/devmapper/deviceset.go (about) 1 //go:build linux 2 // +build linux 3 4 package devmapper // import "github.com/docker/docker/daemon/graphdriver/devmapper" 5 6 import ( 7 "bufio" 8 "encoding/json" 9 "fmt" 10 "io" 11 "os" 12 "os/exec" 13 "path" 14 "path/filepath" 15 "reflect" 16 "strconv" 17 "strings" 18 "sync" 19 "time" 20 21 "github.com/docker/docker/daemon/graphdriver" 22 "github.com/docker/docker/dockerversion" 23 "github.com/docker/docker/pkg/devicemapper" 24 "github.com/docker/docker/pkg/dmesg" 25 "github.com/docker/docker/pkg/idtools" 26 "github.com/docker/docker/pkg/loopback" 27 "github.com/docker/docker/pkg/parsers" 28 "github.com/docker/docker/pkg/parsers/kernel" 29 units "github.com/docker/go-units" 30 "github.com/moby/sys/mount" 31 "github.com/opencontainers/selinux/go-selinux/label" 32 "github.com/pkg/errors" 33 "github.com/sirupsen/logrus" 34 "golang.org/x/sys/unix" 35 ) 36 37 var ( 38 defaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024 39 defaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024 40 defaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024 41 defaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors 42 defaultUdevSyncOverride = false 43 maxDeviceID = 0xffffff // 24 bit, pool limit 44 deviceIDMapSz = (maxDeviceID + 1) / 8 45 driverDeferredRemovalSupport = false 46 enableDeferredRemoval = false 47 enableDeferredDeletion = false 48 userBaseSize = false 49 defaultMinFreeSpacePercent uint32 = 10 50 lvmSetupConfigForce bool 51 ) 52 53 const deviceSetMetaFile = "deviceset-metadata" 54 const transactionMetaFile = "transaction-metadata" 55 56 type transaction struct { 57 OpenTransactionID uint64 `json:"open_transaction_id"` 58 DeviceIDHash string `json:"device_hash"` 59 DeviceID int `json:"device_id"` 60 } 61 62 type devInfo struct { 63 Hash string `json:"-"` 64 DeviceID int `json:"device_id"` 65 Size uint64 `json:"size"` 66 TransactionID uint64 `json:"transaction_id"` 67 Initialized bool `json:"initialized"` 68 Deleted bool `json:"deleted"` 69 devices *DeviceSet 70 71 // The global DeviceSet lock guarantees that we serialize all 72 // the calls to libdevmapper (which is not threadsafe), but we 73 // sometimes release that lock while sleeping. In that case 74 // this per-device lock is still held, protecting against 75 // other accesses to the device that we're doing the wait on. 76 // 77 // WARNING: In order to avoid AB-BA deadlocks when releasing 78 // the global lock while holding the per-device locks all 79 // device locks must be acquired *before* the device lock, and 80 // multiple device locks should be acquired parent before child. 81 lock sync.Mutex 82 } 83 84 type metaData struct { 85 Devices map[string]*devInfo `json:"Devices"` 86 } 87 88 // DeviceSet holds information about list of devices 89 type DeviceSet struct { 90 metaData `json:"-"` 91 sync.Mutex `json:"-"` // Protects all fields of DeviceSet and serializes calls into libdevmapper 92 root string 93 devicePrefix string 94 TransactionID uint64 `json:"-"` 95 NextDeviceID int `json:"next_device_id"` 96 deviceIDMap []byte 97 98 // Options 99 dataLoopbackSize int64 100 metaDataLoopbackSize int64 101 baseFsSize uint64 102 filesystem string 103 mountOptions string 104 mkfsArgs []string 105 dataDevice string // block or loop dev 106 dataLoopFile string // loopback file, if used 107 metadataDevice string // block or loop dev 108 metadataLoopFile string // loopback file, if used 109 doBlkDiscard bool 110 thinpBlockSize uint32 111 thinPoolDevice string 112 transaction `json:"-"` 113 overrideUdevSyncCheck bool 114 deferredRemove bool // use deferred removal 115 deferredDelete bool // use deferred deletion 116 BaseDeviceUUID string // save UUID of base device 117 BaseDeviceFilesystem string // save filesystem of base device 118 nrDeletedDevices uint // number of deleted devices 119 deletionWorkerTicker *time.Ticker 120 idMap idtools.IdentityMapping 121 minFreeSpacePercent uint32 // min free space percentage in thinpool 122 xfsNospaceRetries string // max retries when xfs receives ENOSPC 123 lvmSetupConfig directLVMConfig 124 } 125 126 // DiskUsage contains information about disk usage and is used when reporting Status of a device. 127 type DiskUsage struct { 128 // Used bytes on the disk. 129 Used uint64 130 // Total bytes on the disk. 131 Total uint64 132 // Available bytes on the disk. 133 Available uint64 134 } 135 136 // Status returns the information about the device. 137 type Status struct { 138 // PoolName is the name of the data pool. 139 PoolName string 140 // DataFile is the actual block device for data. 141 DataFile string 142 // DataLoopback loopback file, if used. 143 DataLoopback string 144 // MetadataFile is the actual block device for metadata. 145 MetadataFile string 146 // MetadataLoopback is the loopback file, if used. 147 MetadataLoopback string 148 // Data is the disk used for data. 149 Data DiskUsage 150 // Metadata is the disk used for meta data. 151 Metadata DiskUsage 152 // BaseDeviceSize is base size of container and image 153 BaseDeviceSize uint64 154 // BaseDeviceFS is backing filesystem. 155 BaseDeviceFS string 156 // SectorSize size of the vector. 157 SectorSize uint64 158 // UdevSyncSupported is true if sync is supported. 159 UdevSyncSupported bool 160 // DeferredRemoveEnabled is true then the device is not unmounted. 161 DeferredRemoveEnabled bool 162 // True if deferred deletion is enabled. This is different from 163 // deferred removal. "removal" means that device mapper device is 164 // deactivated. Thin device is still in thin pool and can be activated 165 // again. But "deletion" means that thin device will be deleted from 166 // thin pool and it can't be activated again. 167 DeferredDeleteEnabled bool 168 DeferredDeletedDeviceCount uint 169 MinFreeSpace uint64 170 } 171 172 // Structure used to export image/container metadata in docker inspect. 173 type deviceMetadata struct { 174 deviceID int 175 deviceSize uint64 // size in bytes 176 deviceName string // Device name as used during activation 177 } 178 179 // DevStatus returns information about device mounted containing its id, size and sector information. 180 type DevStatus struct { 181 // DeviceID is the id of the device. 182 DeviceID int 183 // Size is the size of the filesystem. 184 Size uint64 185 // TransactionID is a unique integer per device set used to identify an operation on the file system, this number is incremental. 186 TransactionID uint64 187 // SizeInSectors indicates the size of the sectors allocated. 188 SizeInSectors uint64 189 // MappedSectors indicates number of mapped sectors. 190 MappedSectors uint64 191 // HighestMappedSector is the pointer to the highest mapped sector. 192 HighestMappedSector uint64 193 } 194 195 func getDevName(name string) string { 196 return "/dev/mapper/" + name 197 } 198 199 func (info *devInfo) Name() string { 200 hash := info.Hash 201 if hash == "" { 202 hash = "base" 203 } 204 return fmt.Sprintf("%s-%s", info.devices.devicePrefix, hash) 205 } 206 207 func (info *devInfo) DevName() string { 208 return getDevName(info.Name()) 209 } 210 211 func (devices *DeviceSet) loopbackDir() string { 212 return path.Join(devices.root, "devicemapper") 213 } 214 215 func (devices *DeviceSet) metadataDir() string { 216 return path.Join(devices.root, "metadata") 217 } 218 219 func (devices *DeviceSet) metadataFile(info *devInfo) string { 220 file := info.Hash 221 if file == "" { 222 file = "base" 223 } 224 return path.Join(devices.metadataDir(), file) 225 } 226 227 func (devices *DeviceSet) transactionMetaFile() string { 228 return path.Join(devices.metadataDir(), transactionMetaFile) 229 } 230 231 func (devices *DeviceSet) deviceSetMetaFile() string { 232 return path.Join(devices.metadataDir(), deviceSetMetaFile) 233 } 234 235 func (devices *DeviceSet) oldMetadataFile() string { 236 return path.Join(devices.loopbackDir(), "json") 237 } 238 239 func (devices *DeviceSet) getPoolName() string { 240 if devices.thinPoolDevice == "" { 241 return devices.devicePrefix + "-pool" 242 } 243 return devices.thinPoolDevice 244 } 245 246 func (devices *DeviceSet) getPoolDevName() string { 247 return getDevName(devices.getPoolName()) 248 } 249 250 func (devices *DeviceSet) hasImage(name string) bool { 251 dirname := devices.loopbackDir() 252 filename := path.Join(dirname, name) 253 254 _, err := os.Stat(filename) 255 return err == nil 256 } 257 258 // ensureImage creates a sparse file of <size> bytes at the path 259 // <root>/devicemapper/<name>. 260 // If the file already exists and new size is larger than its current size, it grows to the new size. 261 // Either way it returns the full path. 262 func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) { 263 dirname := devices.loopbackDir() 264 filename := path.Join(dirname, name) 265 266 if err := idtools.MkdirAllAndChown(dirname, 0700, devices.idMap.RootPair()); err != nil { 267 return "", err 268 } 269 270 if fi, err := os.Stat(filename); err != nil { 271 if !os.IsNotExist(err) { 272 return "", err 273 } 274 logrus.WithField("storage-driver", "devicemapper").Debugf("Creating loopback file %s for device-manage use", filename) 275 file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600) 276 if err != nil { 277 return "", err 278 } 279 defer file.Close() 280 281 if err := file.Truncate(size); err != nil { 282 return "", err 283 } 284 } else { 285 if fi.Size() < size { 286 file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600) 287 if err != nil { 288 return "", err 289 } 290 defer file.Close() 291 if err := file.Truncate(size); err != nil { 292 return "", fmt.Errorf("devmapper: Unable to grow loopback file %s: %v", filename, err) 293 } 294 } else if fi.Size() > size { 295 logrus.WithField("storage-driver", "devicemapper").Warnf("Can't shrink loopback file %s", filename) 296 } 297 } 298 return filename, nil 299 } 300 301 func (devices *DeviceSet) allocateTransactionID() uint64 { 302 devices.OpenTransactionID = devices.TransactionID + 1 303 return devices.OpenTransactionID 304 } 305 306 func (devices *DeviceSet) updatePoolTransactionID() error { 307 if err := devicemapper.SetTransactionID(devices.getPoolDevName(), devices.TransactionID, devices.OpenTransactionID); err != nil { 308 return fmt.Errorf("devmapper: Error setting devmapper transaction ID: %s", err) 309 } 310 devices.TransactionID = devices.OpenTransactionID 311 return nil 312 } 313 314 func (devices *DeviceSet) removeMetadata(info *devInfo) error { 315 if err := os.RemoveAll(devices.metadataFile(info)); err != nil { 316 return fmt.Errorf("devmapper: Error removing metadata file %s: %s", devices.metadataFile(info), err) 317 } 318 return nil 319 } 320 321 // Given json data and file path, write it to disk 322 func (devices *DeviceSet) writeMetaFile(jsonData []byte, filePath string) error { 323 tmpFile, err := os.CreateTemp(devices.metadataDir(), ".tmp") 324 if err != nil { 325 return fmt.Errorf("devmapper: Error creating metadata file: %s", err) 326 } 327 328 n, err := tmpFile.Write(jsonData) 329 if err != nil { 330 return fmt.Errorf("devmapper: Error writing metadata to %s: %s", tmpFile.Name(), err) 331 } 332 if n < len(jsonData) { 333 return io.ErrShortWrite 334 } 335 if err := tmpFile.Sync(); err != nil { 336 return fmt.Errorf("devmapper: Error syncing metadata file %s: %s", tmpFile.Name(), err) 337 } 338 if err := tmpFile.Close(); err != nil { 339 return fmt.Errorf("devmapper: Error closing metadata file %s: %s", tmpFile.Name(), err) 340 } 341 if err := os.Rename(tmpFile.Name(), filePath); err != nil { 342 return fmt.Errorf("devmapper: Error committing metadata file %s: %s", tmpFile.Name(), err) 343 } 344 345 return nil 346 } 347 348 func (devices *DeviceSet) saveMetadata(info *devInfo) error { 349 jsonData, err := json.Marshal(info) 350 if err != nil { 351 return fmt.Errorf("devmapper: Error encoding metadata to json: %s", err) 352 } 353 return devices.writeMetaFile(jsonData, devices.metadataFile(info)) 354 } 355 356 func (devices *DeviceSet) markDeviceIDUsed(deviceID int) { 357 var mask byte 358 i := deviceID % 8 359 mask = 1 << uint(i) 360 devices.deviceIDMap[deviceID/8] = devices.deviceIDMap[deviceID/8] | mask 361 } 362 363 func (devices *DeviceSet) markDeviceIDFree(deviceID int) { 364 var mask byte 365 i := deviceID % 8 366 mask = ^(1 << uint(i)) 367 devices.deviceIDMap[deviceID/8] = devices.deviceIDMap[deviceID/8] & mask 368 } 369 370 func (devices *DeviceSet) isDeviceIDFree(deviceID int) bool { 371 var mask byte 372 i := deviceID % 8 373 mask = (1 << uint(i)) 374 return (devices.deviceIDMap[deviceID/8] & mask) == 0 375 } 376 377 // Should be called with devices.Lock() held. 378 func (devices *DeviceSet) lookupDevice(hash string) (*devInfo, error) { 379 info := devices.Devices[hash] 380 if info == nil { 381 info = devices.loadMetadata(hash) 382 if info == nil { 383 return nil, fmt.Errorf("devmapper: Unknown device %s", hash) 384 } 385 386 devices.Devices[hash] = info 387 } 388 return info, nil 389 } 390 391 func (devices *DeviceSet) lookupDeviceWithLock(hash string) (*devInfo, error) { 392 devices.Lock() 393 defer devices.Unlock() 394 info, err := devices.lookupDevice(hash) 395 return info, err 396 } 397 398 // This function relies on that device hash map has been loaded in advance. 399 // Should be called with devices.Lock() held. 400 func (devices *DeviceSet) constructDeviceIDMap() { 401 logrus.WithField("storage-driver", "devicemapper").Debug("constructDeviceIDMap()") 402 defer logrus.WithField("storage-driver", "devicemapper").Debug("constructDeviceIDMap() END") 403 404 for _, info := range devices.Devices { 405 devices.markDeviceIDUsed(info.DeviceID) 406 logrus.WithField("storage-driver", "devicemapper").Debugf("Added deviceId=%d to DeviceIdMap", info.DeviceID) 407 } 408 } 409 410 func (devices *DeviceSet) deviceFileWalkFunction(path string, name string) error { 411 logger := logrus.WithField("storage-driver", "devicemapper") 412 413 // Skip some of the meta files which are not device files. 414 if strings.HasSuffix(name, ".migrated") { 415 logger.Debugf("Skipping file %s", path) 416 return nil 417 } 418 419 if strings.HasPrefix(name, ".") { 420 logger.Debugf("Skipping file %s", path) 421 return nil 422 } 423 424 if name == deviceSetMetaFile { 425 logger.Debugf("Skipping file %s", path) 426 return nil 427 } 428 429 if name == transactionMetaFile { 430 logger.Debugf("Skipping file %s", path) 431 return nil 432 } 433 434 logger.Debugf("Loading data for file %s", path) 435 436 hash := name 437 if hash == "base" { 438 hash = "" 439 } 440 441 // Include deleted devices also as cleanup delete device logic 442 // will go through it and see if there are any deleted devices. 443 if _, err := devices.lookupDevice(hash); err != nil { 444 return fmt.Errorf("devmapper: Error looking up device %s:%v", hash, err) 445 } 446 447 return nil 448 } 449 450 func (devices *DeviceSet) loadDeviceFilesOnStart() error { 451 logrus.WithField("storage-driver", "devicemapper").Debug("loadDeviceFilesOnStart()") 452 defer logrus.WithField("storage-driver", "devicemapper").Debug("loadDeviceFilesOnStart() END") 453 454 var scan = func(path string, info os.DirEntry, err error) error { 455 if err != nil { 456 logrus.WithField("storage-driver", "devicemapper").Debugf("Can't walk the file %s", path) 457 return nil 458 } 459 460 // Skip any directories 461 if info.IsDir() { 462 return nil 463 } 464 465 return devices.deviceFileWalkFunction(path, info.Name()) 466 } 467 468 return filepath.WalkDir(devices.metadataDir(), scan) 469 } 470 471 // Should be called with devices.Lock() held. 472 func (devices *DeviceSet) unregisterDevice(hash string) error { 473 logrus.WithField("storage-driver", "devicemapper").Debugf("unregisterDevice(%v)", hash) 474 info := &devInfo{ 475 Hash: hash, 476 } 477 478 delete(devices.Devices, hash) 479 480 if err := devices.removeMetadata(info); err != nil { 481 logrus.WithField("storage-driver", "devicemapper").Debugf("Error removing metadata: %s", err) 482 return err 483 } 484 485 return nil 486 } 487 488 // Should be called with devices.Lock() held. 489 func (devices *DeviceSet) registerDevice(id int, hash string, size uint64, transactionID uint64) (*devInfo, error) { 490 logrus.WithField("storage-driver", "devicemapper").Debugf("registerDevice(%v, %v)", id, hash) 491 info := &devInfo{ 492 Hash: hash, 493 DeviceID: id, 494 Size: size, 495 TransactionID: transactionID, 496 Initialized: false, 497 devices: devices, 498 } 499 500 devices.Devices[hash] = info 501 502 if err := devices.saveMetadata(info); err != nil { 503 // Try to remove unused device 504 delete(devices.Devices, hash) 505 return nil, err 506 } 507 508 return info, nil 509 } 510 511 func (devices *DeviceSet) activateDeviceIfNeeded(info *devInfo, ignoreDeleted bool) error { 512 logrus.WithField("storage-driver", "devicemapper").Debugf("activateDeviceIfNeeded(%v)", info.Hash) 513 514 if info.Deleted && !ignoreDeleted { 515 return fmt.Errorf("devmapper: Can't activate device %v as it is marked for deletion", info.Hash) 516 } 517 518 // Make sure deferred removal on device is canceled, if one was 519 // scheduled. 520 if err := devices.cancelDeferredRemovalIfNeeded(info); err != nil { 521 return fmt.Errorf("devmapper: Device Deferred Removal Cancellation Failed: %s", err) 522 } 523 524 if devinfo, _ := devicemapper.GetInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 { 525 return nil 526 } 527 528 return devicemapper.ActivateDevice(devices.getPoolDevName(), info.Name(), info.DeviceID, info.Size) 529 } 530 531 // xfsSupported checks if xfs is supported, returns nil if it is, otherwise an error 532 func xfsSupported() error { 533 // Make sure mkfs.xfs is available 534 if _, err := exec.LookPath("mkfs.xfs"); err != nil { 535 return err // error text is descriptive enough 536 } 537 538 mountTarget, err := os.MkdirTemp("", "supportsXFS") 539 if err != nil { 540 return errors.Wrapf(err, "error checking for xfs support") 541 } 542 543 /* The mounting will fail--after the module has been loaded.*/ 544 defer os.RemoveAll(mountTarget) 545 unix.Mount("none", mountTarget, "xfs", 0, "") 546 547 f, err := os.Open("/proc/filesystems") 548 if err != nil { 549 return errors.Wrapf(err, "error checking for xfs support") 550 } 551 defer f.Close() 552 553 s := bufio.NewScanner(f) 554 for s.Scan() { 555 if strings.HasSuffix(s.Text(), "\txfs") { 556 return nil 557 } 558 } 559 560 if err := s.Err(); err != nil { 561 return errors.Wrapf(err, "error checking for xfs support") 562 } 563 564 return errors.New(`kernel does not support xfs, or "modprobe xfs" failed`) 565 } 566 567 func determineDefaultFS() string { 568 err := xfsSupported() 569 if err == nil { 570 return "xfs" 571 } 572 573 logrus.WithField("storage-driver", "devicemapper").Warnf("XFS is not supported in your system (%v). Defaulting to ext4 filesystem", err) 574 return "ext4" 575 } 576 577 // mkfsOptions tries to figure out whether some additional mkfs options are required 578 func mkfsOptions(fs string) []string { 579 if fs == "xfs" && !kernel.CheckKernelVersion(3, 16, 0) { 580 // For kernels earlier than 3.16 (and newer xfsutils), 581 // some xfs features need to be explicitly disabled. 582 return []string{"-m", "crc=0,finobt=0"} 583 } 584 585 return []string{} 586 } 587 588 func (devices *DeviceSet) createFilesystem(info *devInfo) (err error) { 589 devname := info.DevName() 590 591 if devices.filesystem == "" { 592 devices.filesystem = determineDefaultFS() 593 } 594 if err := devices.saveBaseDeviceFilesystem(devices.filesystem); err != nil { 595 return err 596 } 597 598 args := mkfsOptions(devices.filesystem) 599 args = append(args, devices.mkfsArgs...) 600 args = append(args, devname) 601 602 logrus.WithField("storage-driver", "devicemapper").Infof("Creating filesystem %s on device %s, mkfs args: %v", devices.filesystem, info.Name(), args) 603 defer func() { 604 if err != nil { 605 logrus.WithField("storage-driver", "devicemapper").Infof("Error while creating filesystem %s on device %s: %v", devices.filesystem, info.Name(), err) 606 } else { 607 logrus.WithField("storage-driver", "devicemapper").Infof("Successfully created filesystem %s on device %s", devices.filesystem, info.Name()) 608 } 609 }() 610 611 switch devices.filesystem { 612 case "xfs": 613 err = exec.Command("mkfs.xfs", args...).Run() 614 case "ext4": 615 err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0"}, args...)...).Run() 616 if err != nil { 617 err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0"}, args...)...).Run() 618 } 619 if err != nil { 620 return err 621 } 622 err = exec.Command("tune2fs", append([]string{"-c", "-1", "-i", "0"}, devname)...).Run() 623 default: 624 err = fmt.Errorf("devmapper: Unsupported filesystem type %s", devices.filesystem) 625 } 626 return 627 } 628 629 func (devices *DeviceSet) migrateOldMetaData() error { 630 // Migrate old metadata file 631 jsonData, err := os.ReadFile(devices.oldMetadataFile()) 632 if err != nil && !os.IsNotExist(err) { 633 return err 634 } 635 636 if jsonData != nil { 637 m := metaData{Devices: make(map[string]*devInfo)} 638 639 if err := json.Unmarshal(jsonData, &m); err != nil { 640 return err 641 } 642 643 for hash, info := range m.Devices { 644 info.Hash = hash 645 devices.saveMetadata(info) 646 } 647 if err := os.Rename(devices.oldMetadataFile(), devices.oldMetadataFile()+".migrated"); err != nil { 648 return err 649 } 650 } 651 652 return nil 653 } 654 655 // Cleanup deleted devices. It assumes that all the devices have been 656 // loaded in the hash table. 657 func (devices *DeviceSet) cleanupDeletedDevices() error { 658 devices.Lock() 659 660 // If there are no deleted devices, there is nothing to do. 661 if devices.nrDeletedDevices == 0 { 662 devices.Unlock() 663 return nil 664 } 665 666 var deletedDevices []*devInfo 667 668 for _, info := range devices.Devices { 669 if !info.Deleted { 670 continue 671 } 672 logrus.WithField("storage-driver", "devicemapper").Debugf("Found deleted device %s.", info.Hash) 673 deletedDevices = append(deletedDevices, info) 674 } 675 676 // Delete the deleted devices. DeleteDevice() first takes the info lock 677 // and then devices.Lock(). So drop it to avoid deadlock. 678 devices.Unlock() 679 680 for _, info := range deletedDevices { 681 // This will again try deferred deletion. 682 if err := devices.DeleteDevice(info.Hash, false); err != nil { 683 logrus.WithField("storage-driver", "devicemapper").Warnf("Deletion of device %s, device_id=%v failed:%v", info.Hash, info.DeviceID, err) 684 } 685 } 686 687 return nil 688 } 689 690 func (devices *DeviceSet) countDeletedDevices() { 691 for _, info := range devices.Devices { 692 if !info.Deleted { 693 continue 694 } 695 devices.nrDeletedDevices++ 696 } 697 } 698 699 func (devices *DeviceSet) startDeviceDeletionWorker() { 700 // Deferred deletion is not enabled. Don't do anything. 701 if !devices.deferredDelete { 702 return 703 } 704 705 logrus.WithField("storage-driver", "devicemapper").Debug("Worker to cleanup deleted devices started") 706 for range devices.deletionWorkerTicker.C { 707 devices.cleanupDeletedDevices() 708 } 709 } 710 711 func (devices *DeviceSet) initMetaData() error { 712 devices.Lock() 713 defer devices.Unlock() 714 715 if err := devices.migrateOldMetaData(); err != nil { 716 return err 717 } 718 719 _, transactionID, _, _, _, _, err := devices.poolStatus() 720 if err != nil { 721 return err 722 } 723 724 devices.TransactionID = transactionID 725 726 if err := devices.loadDeviceFilesOnStart(); err != nil { 727 return fmt.Errorf("devmapper: Failed to load device files:%v", err) 728 } 729 730 devices.constructDeviceIDMap() 731 devices.countDeletedDevices() 732 733 if err := devices.processPendingTransaction(); err != nil { 734 return err 735 } 736 737 // Start a goroutine to cleanup Deleted Devices 738 go devices.startDeviceDeletionWorker() 739 return nil 740 } 741 742 func (devices *DeviceSet) incNextDeviceID() { 743 // IDs are 24bit, so wrap around 744 devices.NextDeviceID = (devices.NextDeviceID + 1) & maxDeviceID 745 } 746 747 func (devices *DeviceSet) getNextFreeDeviceID() (int, error) { 748 devices.incNextDeviceID() 749 for i := 0; i <= maxDeviceID; i++ { 750 if devices.isDeviceIDFree(devices.NextDeviceID) { 751 devices.markDeviceIDUsed(devices.NextDeviceID) 752 return devices.NextDeviceID, nil 753 } 754 devices.incNextDeviceID() 755 } 756 757 return 0, fmt.Errorf("devmapper: Unable to find a free device ID") 758 } 759 760 func (devices *DeviceSet) poolHasFreeSpace() error { 761 if devices.minFreeSpacePercent == 0 { 762 return nil 763 } 764 765 _, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus() 766 if err != nil { 767 return err 768 } 769 770 minFreeData := (dataTotal * uint64(devices.minFreeSpacePercent)) / 100 771 if minFreeData < 1 { 772 minFreeData = 1 773 } 774 dataFree := dataTotal - dataUsed 775 if dataFree < minFreeData { 776 return fmt.Errorf("devmapper: Thin Pool has %v free data blocks which is less than minimum required %v free data blocks. Create more free space in thin pool or use dm.min_free_space option to change behavior", (dataTotal - dataUsed), minFreeData) 777 } 778 779 minFreeMetadata := (metadataTotal * uint64(devices.minFreeSpacePercent)) / 100 780 if minFreeMetadata < 1 { 781 minFreeMetadata = 1 782 } 783 784 metadataFree := metadataTotal - metadataUsed 785 if metadataFree < minFreeMetadata { 786 return fmt.Errorf("devmapper: Thin Pool has %v free metadata blocks which is less than minimum required %v free metadata blocks. Create more free metadata space in thin pool or use dm.min_free_space option to change behavior", (metadataTotal - metadataUsed), minFreeMetadata) 787 } 788 789 return nil 790 } 791 792 func (devices *DeviceSet) createRegisterDevice(hash string) (*devInfo, error) { 793 devices.Lock() 794 defer devices.Unlock() 795 796 deviceID, err := devices.getNextFreeDeviceID() 797 if err != nil { 798 return nil, err 799 } 800 801 logger := logrus.WithField("storage-driver", "devicemapper") 802 803 if err := devices.openTransaction(hash, deviceID); err != nil { 804 logger.Debugf("Error opening transaction hash = %s deviceID = %d", hash, deviceID) 805 devices.markDeviceIDFree(deviceID) 806 return nil, err 807 } 808 809 for { 810 if err := devicemapper.CreateDevice(devices.getPoolDevName(), deviceID); err != nil { 811 if devicemapper.DeviceIDExists(err) { 812 // Device ID already exists. This should not 813 // happen. Now we have a mechanism to find 814 // a free device ID. So something is not right. 815 // Give a warning and continue. 816 logger.Errorf("Device ID %d exists in pool but it is supposed to be unused", deviceID) 817 deviceID, err = devices.getNextFreeDeviceID() 818 if err != nil { 819 return nil, err 820 } 821 // Save new device id into transaction 822 devices.refreshTransaction(deviceID) 823 continue 824 } 825 logger.Debugf("Error creating device: %s", err) 826 devices.markDeviceIDFree(deviceID) 827 return nil, err 828 } 829 break 830 } 831 832 logger.Debugf("Registering device (id %v) with FS size %v", deviceID, devices.baseFsSize) 833 info, err := devices.registerDevice(deviceID, hash, devices.baseFsSize, devices.OpenTransactionID) 834 if err != nil { 835 _ = devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID) 836 devices.markDeviceIDFree(deviceID) 837 return nil, err 838 } 839 840 if err := devices.closeTransaction(); err != nil { 841 devices.unregisterDevice(hash) 842 devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID) 843 devices.markDeviceIDFree(deviceID) 844 return nil, err 845 } 846 return info, nil 847 } 848 849 func (devices *DeviceSet) takeSnapshot(hash string, baseInfo *devInfo, size uint64) error { 850 var ( 851 devinfo *devicemapper.Info 852 err error 853 ) 854 855 if err = devices.poolHasFreeSpace(); err != nil { 856 return err 857 } 858 859 if devices.deferredRemove { 860 devinfo, err = devicemapper.GetInfoWithDeferred(baseInfo.Name()) 861 if err != nil { 862 return err 863 } 864 if devinfo != nil && devinfo.DeferredRemove != 0 { 865 err = devices.cancelDeferredRemoval(baseInfo) 866 if err != nil { 867 // If Error is ErrEnxio. Device is probably already gone. Continue. 868 if err != devicemapper.ErrEnxio { 869 return err 870 } 871 devinfo = nil 872 } else { 873 defer devices.deactivateDevice(baseInfo) 874 } 875 } 876 } else { 877 devinfo, err = devicemapper.GetInfo(baseInfo.Name()) 878 if err != nil { 879 return err 880 } 881 } 882 883 doSuspend := devinfo != nil && devinfo.Exists != 0 884 885 if doSuspend { 886 if err = devicemapper.SuspendDevice(baseInfo.Name()); err != nil { 887 return err 888 } 889 defer devicemapper.ResumeDevice(baseInfo.Name()) 890 } 891 892 return devices.createRegisterSnapDevice(hash, baseInfo, size) 893 } 894 895 func (devices *DeviceSet) createRegisterSnapDevice(hash string, baseInfo *devInfo, size uint64) error { 896 deviceID, err := devices.getNextFreeDeviceID() 897 if err != nil { 898 return err 899 } 900 901 logger := logrus.WithField("storage-driver", "devicemapper") 902 903 if err := devices.openTransaction(hash, deviceID); err != nil { 904 logger.Debugf("Error opening transaction hash = %s deviceID = %d", hash, deviceID) 905 devices.markDeviceIDFree(deviceID) 906 return err 907 } 908 909 for { 910 if err := devicemapper.CreateSnapDeviceRaw(devices.getPoolDevName(), deviceID, baseInfo.DeviceID); err != nil { 911 if devicemapper.DeviceIDExists(err) { 912 // Device ID already exists. This should not 913 // happen. Now we have a mechanism to find 914 // a free device ID. So something is not right. 915 // Give a warning and continue. 916 logger.Errorf("Device ID %d exists in pool but it is supposed to be unused", deviceID) 917 deviceID, err = devices.getNextFreeDeviceID() 918 if err != nil { 919 return err 920 } 921 // Save new device id into transaction 922 devices.refreshTransaction(deviceID) 923 continue 924 } 925 logger.Debugf("Error creating snap device: %s", err) 926 devices.markDeviceIDFree(deviceID) 927 return err 928 } 929 break 930 } 931 932 if _, err := devices.registerDevice(deviceID, hash, size, devices.OpenTransactionID); err != nil { 933 devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID) 934 devices.markDeviceIDFree(deviceID) 935 logger.Debugf("Error registering device: %s", err) 936 return err 937 } 938 939 if err := devices.closeTransaction(); err != nil { 940 devices.unregisterDevice(hash) 941 devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID) 942 devices.markDeviceIDFree(deviceID) 943 return err 944 } 945 return nil 946 } 947 948 func (devices *DeviceSet) loadMetadata(hash string) *devInfo { 949 info := &devInfo{Hash: hash, devices: devices} 950 logger := logrus.WithField("storage-driver", "devicemapper") 951 952 jsonData, err := os.ReadFile(devices.metadataFile(info)) 953 if err != nil { 954 logger.Debugf("Failed to read %s with err: %v", devices.metadataFile(info), err) 955 return nil 956 } 957 958 if err := json.Unmarshal(jsonData, &info); err != nil { 959 logger.Debugf("Failed to unmarshal devInfo from %s with err: %v", devices.metadataFile(info), err) 960 return nil 961 } 962 963 if info.DeviceID > maxDeviceID { 964 logger.Errorf("Ignoring Invalid DeviceId=%d", info.DeviceID) 965 return nil 966 } 967 968 return info 969 } 970 971 func getDeviceUUID(device string) (string, error) { 972 out, err := exec.Command("blkid", "-s", "UUID", "-o", "value", device).Output() 973 if err != nil { 974 return "", fmt.Errorf("devmapper: Failed to find uuid for device %s:%v", device, err) 975 } 976 977 uuid := strings.TrimSuffix(string(out), "\n") 978 uuid = strings.TrimSpace(uuid) 979 logrus.WithField("storage-driver", "devicemapper").Debugf("UUID for device: %s is:%s", device, uuid) 980 return uuid, nil 981 } 982 983 func (devices *DeviceSet) getBaseDeviceSize() uint64 { 984 info, _ := devices.lookupDevice("") 985 if info == nil { 986 return 0 987 } 988 return info.Size 989 } 990 991 func (devices *DeviceSet) getBaseDeviceFS() string { 992 return devices.BaseDeviceFilesystem 993 } 994 995 func (devices *DeviceSet) verifyBaseDeviceUUIDFS(baseInfo *devInfo) error { 996 devices.Lock() 997 defer devices.Unlock() 998 999 if err := devices.activateDeviceIfNeeded(baseInfo, false); err != nil { 1000 return err 1001 } 1002 defer devices.deactivateDevice(baseInfo) 1003 1004 uuid, err := getDeviceUUID(baseInfo.DevName()) 1005 if err != nil { 1006 return err 1007 } 1008 1009 if devices.BaseDeviceUUID != uuid { 1010 return fmt.Errorf("devmapper: Current Base Device UUID:%s does not match with stored UUID:%s. Possibly using a different thin pool than last invocation", uuid, devices.BaseDeviceUUID) 1011 } 1012 1013 if devices.BaseDeviceFilesystem == "" { 1014 fsType, err := ProbeFsType(baseInfo.DevName()) 1015 if err != nil { 1016 return err 1017 } 1018 if err := devices.saveBaseDeviceFilesystem(fsType); err != nil { 1019 return err 1020 } 1021 } 1022 1023 // If user specified a filesystem using dm.fs option and current 1024 // file system of base image is not same, warn user that dm.fs 1025 // will be ignored. 1026 if devices.BaseDeviceFilesystem != devices.filesystem { 1027 logrus.WithField("storage-driver", "devicemapper").Warnf("Base device already exists and has filesystem %s on it. User specified filesystem %s will be ignored.", devices.BaseDeviceFilesystem, devices.filesystem) 1028 devices.filesystem = devices.BaseDeviceFilesystem 1029 } 1030 return nil 1031 } 1032 1033 func (devices *DeviceSet) saveBaseDeviceFilesystem(fs string) error { 1034 devices.BaseDeviceFilesystem = fs 1035 return devices.saveDeviceSetMetaData() 1036 } 1037 1038 func (devices *DeviceSet) saveBaseDeviceUUID(baseInfo *devInfo) error { 1039 devices.Lock() 1040 defer devices.Unlock() 1041 1042 if err := devices.activateDeviceIfNeeded(baseInfo, false); err != nil { 1043 return err 1044 } 1045 defer devices.deactivateDevice(baseInfo) 1046 1047 uuid, err := getDeviceUUID(baseInfo.DevName()) 1048 if err != nil { 1049 return err 1050 } 1051 1052 devices.BaseDeviceUUID = uuid 1053 return devices.saveDeviceSetMetaData() 1054 } 1055 1056 func (devices *DeviceSet) createBaseImage() error { 1057 logrus.WithField("storage-driver", "devicemapper").Debug("Initializing base device-mapper thin volume") 1058 1059 // Create initial device 1060 info, err := devices.createRegisterDevice("") 1061 if err != nil { 1062 return err 1063 } 1064 1065 logrus.WithField("storage-driver", "devicemapper").Debug("Creating filesystem on base device-mapper thin volume") 1066 1067 if err := devices.activateDeviceIfNeeded(info, false); err != nil { 1068 return err 1069 } 1070 1071 if err := devices.createFilesystem(info); err != nil { 1072 return err 1073 } 1074 1075 info.Initialized = true 1076 if err := devices.saveMetadata(info); err != nil { 1077 info.Initialized = false 1078 return err 1079 } 1080 1081 if err := devices.saveBaseDeviceUUID(info); err != nil { 1082 return fmt.Errorf("devmapper: Could not query and save base device UUID:%v", err) 1083 } 1084 1085 return nil 1086 } 1087 1088 // Returns if thin pool device exists or not. If device exists, also makes 1089 // sure it is a thin pool device and not some other type of device. 1090 func (devices *DeviceSet) thinPoolExists(thinPoolDevice string) (bool, error) { 1091 logrus.WithField("storage-driver", "devicemapper").Debugf("Checking for existence of the pool %s", thinPoolDevice) 1092 1093 info, err := devicemapper.GetInfo(thinPoolDevice) 1094 if err != nil { 1095 return false, fmt.Errorf("devmapper: GetInfo() on device %s failed: %v", thinPoolDevice, err) 1096 } 1097 1098 // Device does not exist. 1099 if info.Exists == 0 { 1100 return false, nil 1101 } 1102 1103 _, _, deviceType, _, err := devicemapper.GetStatus(thinPoolDevice) 1104 if err != nil { 1105 return false, fmt.Errorf("devmapper: GetStatus() on device %s failed: %v", thinPoolDevice, err) 1106 } 1107 1108 if deviceType != "thin-pool" { 1109 return false, fmt.Errorf("devmapper: Device %s is not a thin pool", thinPoolDevice) 1110 } 1111 1112 return true, nil 1113 } 1114 1115 func (devices *DeviceSet) checkThinPool() error { 1116 _, transactionID, dataUsed, _, _, _, err := devices.poolStatus() 1117 if err != nil { 1118 return err 1119 } 1120 if dataUsed != 0 { 1121 return fmt.Errorf("devmapper: Unable to take ownership of thin-pool (%s) that already has used data blocks", 1122 devices.thinPoolDevice) 1123 } 1124 if transactionID != 0 { 1125 return fmt.Errorf("devmapper: Unable to take ownership of thin-pool (%s) with non-zero transaction ID", 1126 devices.thinPoolDevice) 1127 } 1128 return nil 1129 } 1130 1131 // Base image is initialized properly. Either save UUID for first time (for 1132 // upgrade case or verify UUID. 1133 func (devices *DeviceSet) setupVerifyBaseImageUUIDFS(baseInfo *devInfo) error { 1134 // If BaseDeviceUUID is nil (upgrade case), save it and return success. 1135 if devices.BaseDeviceUUID == "" { 1136 if err := devices.saveBaseDeviceUUID(baseInfo); err != nil { 1137 return fmt.Errorf("devmapper: Could not query and save base device UUID:%v", err) 1138 } 1139 return nil 1140 } 1141 1142 if err := devices.verifyBaseDeviceUUIDFS(baseInfo); err != nil { 1143 return fmt.Errorf("devmapper: Base Device UUID and Filesystem verification failed: %v", err) 1144 } 1145 1146 return nil 1147 } 1148 1149 func (devices *DeviceSet) checkGrowBaseDeviceFS(info *devInfo) error { 1150 if !userBaseSize { 1151 return nil 1152 } 1153 1154 if devices.baseFsSize < devices.getBaseDeviceSize() { 1155 return fmt.Errorf("devmapper: Base device size cannot be smaller than %s", units.HumanSize(float64(devices.getBaseDeviceSize()))) 1156 } 1157 1158 if devices.baseFsSize == devices.getBaseDeviceSize() { 1159 return nil 1160 } 1161 1162 info.lock.Lock() 1163 defer info.lock.Unlock() 1164 1165 devices.Lock() 1166 defer devices.Unlock() 1167 1168 info.Size = devices.baseFsSize 1169 1170 if err := devices.saveMetadata(info); err != nil { 1171 // Try to remove unused device 1172 delete(devices.Devices, info.Hash) 1173 return err 1174 } 1175 1176 return devices.growFS(info) 1177 } 1178 1179 func (devices *DeviceSet) growFS(info *devInfo) error { 1180 if err := devices.activateDeviceIfNeeded(info, false); err != nil { 1181 return fmt.Errorf("Error activating devmapper device: %s", err) 1182 } 1183 1184 defer devices.deactivateDevice(info) 1185 1186 fsMountPoint := "/run/docker/mnt" 1187 if _, err := os.Stat(fsMountPoint); os.IsNotExist(err) { 1188 if err := os.MkdirAll(fsMountPoint, 0700); err != nil { 1189 return err 1190 } 1191 defer os.RemoveAll(fsMountPoint) 1192 } 1193 1194 options := "" 1195 if devices.BaseDeviceFilesystem == "xfs" { 1196 // XFS needs nouuid or it can't mount filesystems with the same fs 1197 options = joinMountOptions(options, "nouuid") 1198 } 1199 options = joinMountOptions(options, devices.mountOptions) 1200 1201 if err := mount.Mount(info.DevName(), fsMountPoint, devices.BaseDeviceFilesystem, options); err != nil { 1202 return errors.Wrapf(err, "Failed to mount; dmesg: %s", string(dmesg.Dmesg(256))) 1203 } 1204 1205 defer unix.Unmount(fsMountPoint, unix.MNT_DETACH) 1206 1207 switch devices.BaseDeviceFilesystem { 1208 case "ext4": 1209 if out, err := exec.Command("resize2fs", info.DevName()).CombinedOutput(); err != nil { 1210 return fmt.Errorf("Failed to grow rootfs:%v:%s", err, string(out)) 1211 } 1212 case "xfs": 1213 if out, err := exec.Command("xfs_growfs", info.DevName()).CombinedOutput(); err != nil { 1214 return fmt.Errorf("Failed to grow rootfs:%v:%s", err, string(out)) 1215 } 1216 default: 1217 return fmt.Errorf("Unsupported filesystem type %s", devices.BaseDeviceFilesystem) 1218 } 1219 return nil 1220 } 1221 1222 func (devices *DeviceSet) setupBaseImage() error { 1223 oldInfo, _ := devices.lookupDeviceWithLock("") 1224 1225 // base image already exists. If it is initialized properly, do UUID 1226 // verification and return. Otherwise remove image and set it up 1227 // fresh. 1228 1229 if oldInfo != nil { 1230 if oldInfo.Initialized && !oldInfo.Deleted { 1231 if err := devices.setupVerifyBaseImageUUIDFS(oldInfo); err != nil { 1232 return err 1233 } 1234 return devices.checkGrowBaseDeviceFS(oldInfo) 1235 } 1236 1237 logrus.WithField("storage-driver", "devicemapper").Debug("Removing uninitialized base image") 1238 // If previous base device is in deferred delete state, 1239 // that needs to be cleaned up first. So don't try 1240 // deferred deletion. 1241 if err := devices.DeleteDevice("", true); err != nil { 1242 return err 1243 } 1244 } 1245 1246 // If we are setting up base image for the first time, make sure 1247 // thin pool is empty. 1248 if devices.thinPoolDevice != "" && oldInfo == nil { 1249 if err := devices.checkThinPool(); err != nil { 1250 return err 1251 } 1252 } 1253 1254 // Create new base image device 1255 return devices.createBaseImage() 1256 } 1257 1258 func setCloseOnExec(name string) { 1259 fileInfos, _ := os.ReadDir("/proc/self/fd") 1260 for _, i := range fileInfos { 1261 link, _ := os.Readlink(filepath.Join("/proc/self/fd", i.Name())) 1262 if link == name { 1263 fd, err := strconv.Atoi(i.Name()) 1264 if err == nil { 1265 unix.CloseOnExec(fd) 1266 } 1267 } 1268 } 1269 } 1270 1271 func major(device uint64) uint64 { 1272 return (device >> 8) & 0xfff 1273 } 1274 1275 func minor(device uint64) uint64 { 1276 return (device & 0xff) | ((device >> 12) & 0xfff00) 1277 } 1278 1279 // ResizePool increases the size of the pool. 1280 func (devices *DeviceSet) ResizePool(size int64) error { 1281 dirname := devices.loopbackDir() 1282 datafilename := path.Join(dirname, "data") 1283 if len(devices.dataDevice) > 0 { 1284 datafilename = devices.dataDevice 1285 } 1286 metadatafilename := path.Join(dirname, "metadata") 1287 if len(devices.metadataDevice) > 0 { 1288 metadatafilename = devices.metadataDevice 1289 } 1290 1291 datafile, err := os.OpenFile(datafilename, os.O_RDWR, 0) 1292 if datafile == nil { 1293 return err 1294 } 1295 defer datafile.Close() 1296 1297 fi, err := datafile.Stat() 1298 if fi == nil { 1299 return err 1300 } 1301 1302 if fi.Size() > size { 1303 return fmt.Errorf("devmapper: Can't shrink file") 1304 } 1305 1306 dataloopback := loopback.FindLoopDeviceFor(datafile) 1307 if dataloopback == nil { 1308 return fmt.Errorf("devmapper: Unable to find loopback mount for: %s", datafilename) 1309 } 1310 defer dataloopback.Close() 1311 1312 metadatafile, err := os.OpenFile(metadatafilename, os.O_RDWR, 0) 1313 if metadatafile == nil { 1314 return err 1315 } 1316 defer metadatafile.Close() 1317 1318 metadataloopback := loopback.FindLoopDeviceFor(metadatafile) 1319 if metadataloopback == nil { 1320 return fmt.Errorf("devmapper: Unable to find loopback mount for: %s", metadatafilename) 1321 } 1322 defer metadataloopback.Close() 1323 1324 // Grow loopback file 1325 if err := datafile.Truncate(size); err != nil { 1326 return fmt.Errorf("devmapper: Unable to grow loopback file: %s", err) 1327 } 1328 1329 // Reload size for loopback device 1330 if err := loopback.SetCapacity(dataloopback); err != nil { 1331 return fmt.Errorf("Unable to update loopback capacity: %s", err) 1332 } 1333 1334 // Suspend the pool 1335 if err := devicemapper.SuspendDevice(devices.getPoolName()); err != nil { 1336 return fmt.Errorf("devmapper: Unable to suspend pool: %s", err) 1337 } 1338 1339 // Reload with the new block sizes 1340 if err := devicemapper.ReloadPool(devices.getPoolName(), dataloopback, metadataloopback, devices.thinpBlockSize); err != nil { 1341 return fmt.Errorf("devmapper: Unable to reload pool: %s", err) 1342 } 1343 1344 // Resume the pool 1345 if err := devicemapper.ResumeDevice(devices.getPoolName()); err != nil { 1346 return fmt.Errorf("devmapper: Unable to resume pool: %s", err) 1347 } 1348 1349 return nil 1350 } 1351 1352 func (devices *DeviceSet) loadTransactionMetaData() error { 1353 jsonData, err := os.ReadFile(devices.transactionMetaFile()) 1354 if err != nil { 1355 // There is no active transaction. This will be the case 1356 // during upgrade. 1357 if os.IsNotExist(err) { 1358 devices.OpenTransactionID = devices.TransactionID 1359 return nil 1360 } 1361 return err 1362 } 1363 1364 json.Unmarshal(jsonData, &devices.transaction) 1365 return nil 1366 } 1367 1368 func (devices *DeviceSet) saveTransactionMetaData() error { 1369 jsonData, err := json.Marshal(&devices.transaction) 1370 if err != nil { 1371 return fmt.Errorf("devmapper: Error encoding metadata to json: %s", err) 1372 } 1373 1374 return devices.writeMetaFile(jsonData, devices.transactionMetaFile()) 1375 } 1376 1377 func (devices *DeviceSet) removeTransactionMetaData() error { 1378 return os.RemoveAll(devices.transactionMetaFile()) 1379 } 1380 1381 func (devices *DeviceSet) rollbackTransaction() error { 1382 logger := logrus.WithField("storage-driver", "devicemapper") 1383 1384 logger.Debugf("Rolling back open transaction: TransactionID=%d hash=%s device_id=%d", devices.OpenTransactionID, devices.DeviceIDHash, devices.DeviceID) 1385 1386 // A device id might have already been deleted before transaction 1387 // closed. In that case this call will fail. Just leave a message 1388 // in case of failure. 1389 if err := devicemapper.DeleteDevice(devices.getPoolDevName(), devices.DeviceID); err != nil { 1390 logger.Errorf("Unable to delete device: %s", err) 1391 } 1392 1393 dinfo := &devInfo{Hash: devices.DeviceIDHash} 1394 if err := devices.removeMetadata(dinfo); err != nil { 1395 logger.Errorf("Unable to remove metadata: %s", err) 1396 } else { 1397 devices.markDeviceIDFree(devices.DeviceID) 1398 } 1399 1400 if err := devices.removeTransactionMetaData(); err != nil { 1401 logger.Errorf("Unable to remove transaction meta file %s: %s", devices.transactionMetaFile(), err) 1402 } 1403 1404 return nil 1405 } 1406 1407 func (devices *DeviceSet) processPendingTransaction() error { 1408 if err := devices.loadTransactionMetaData(); err != nil { 1409 return err 1410 } 1411 1412 // If there was open transaction but pool transaction ID is same 1413 // as open transaction ID, nothing to roll back. 1414 if devices.TransactionID == devices.OpenTransactionID { 1415 return nil 1416 } 1417 1418 // If open transaction ID is less than pool transaction ID, something 1419 // is wrong. Bail out. 1420 if devices.OpenTransactionID < devices.TransactionID { 1421 logrus.WithField("storage-driver", "devicemapper").Errorf("Open Transaction id %d is less than pool transaction id %d", devices.OpenTransactionID, devices.TransactionID) 1422 return nil 1423 } 1424 1425 // Pool transaction ID is not same as open transaction. There is 1426 // a transaction which was not completed. 1427 if err := devices.rollbackTransaction(); err != nil { 1428 return fmt.Errorf("devmapper: Rolling back open transaction failed: %s", err) 1429 } 1430 1431 devices.OpenTransactionID = devices.TransactionID 1432 return nil 1433 } 1434 1435 func (devices *DeviceSet) loadDeviceSetMetaData() error { 1436 jsonData, err := os.ReadFile(devices.deviceSetMetaFile()) 1437 if err != nil { 1438 // For backward compatibility return success if file does 1439 // not exist. 1440 if os.IsNotExist(err) { 1441 return nil 1442 } 1443 return err 1444 } 1445 1446 return json.Unmarshal(jsonData, devices) 1447 } 1448 1449 func (devices *DeviceSet) saveDeviceSetMetaData() error { 1450 jsonData, err := json.Marshal(devices) 1451 if err != nil { 1452 return fmt.Errorf("devmapper: Error encoding metadata to json: %s", err) 1453 } 1454 1455 return devices.writeMetaFile(jsonData, devices.deviceSetMetaFile()) 1456 } 1457 1458 func (devices *DeviceSet) openTransaction(hash string, DeviceID int) error { 1459 devices.allocateTransactionID() 1460 devices.DeviceIDHash = hash 1461 devices.DeviceID = DeviceID 1462 if err := devices.saveTransactionMetaData(); err != nil { 1463 return fmt.Errorf("devmapper: Error saving transaction metadata: %s", err) 1464 } 1465 return nil 1466 } 1467 1468 func (devices *DeviceSet) refreshTransaction(DeviceID int) error { 1469 devices.DeviceID = DeviceID 1470 if err := devices.saveTransactionMetaData(); err != nil { 1471 return fmt.Errorf("devmapper: Error saving transaction metadata: %s", err) 1472 } 1473 return nil 1474 } 1475 1476 func (devices *DeviceSet) closeTransaction() error { 1477 if err := devices.updatePoolTransactionID(); err != nil { 1478 logrus.WithField("storage-driver", "devicemapper").Debug("Failed to close Transaction") 1479 return err 1480 } 1481 return nil 1482 } 1483 1484 func determineDriverCapabilities(version string) error { 1485 // Kernel driver version >= 4.27.0 support deferred removal 1486 1487 logrus.WithField("storage-driver", "devicemapper").Debugf("kernel dm driver version is %s", version) 1488 1489 versionSplit := strings.Split(version, ".") 1490 major, err := strconv.Atoi(versionSplit[0]) 1491 if err != nil { 1492 return graphdriver.ErrNotSupported 1493 } 1494 1495 if major > 4 { 1496 driverDeferredRemovalSupport = true 1497 return nil 1498 } 1499 1500 if major < 4 { 1501 return nil 1502 } 1503 1504 minor, err := strconv.Atoi(versionSplit[1]) 1505 if err != nil { 1506 return graphdriver.ErrNotSupported 1507 } 1508 1509 /* 1510 * If major is 4 and minor is 27, then there is no need to 1511 * check for patch level as it can not be less than 0. 1512 */ 1513 if minor >= 27 { 1514 driverDeferredRemovalSupport = true 1515 return nil 1516 } 1517 1518 return nil 1519 } 1520 1521 // Determine the major and minor number of loopback device 1522 func getDeviceMajorMinor(file *os.File) (uint64, uint64, error) { 1523 var stat unix.Stat_t 1524 err := unix.Stat(file.Name(), &stat) 1525 if err != nil { 1526 return 0, 0, err 1527 } 1528 1529 // the type is 32bit on mips 1530 dev := uint64(stat.Rdev) //nolint: unconvert 1531 majorNum := major(dev) 1532 minorNum := minor(dev) 1533 1534 logrus.WithField("storage-driver", "devicemapper").Debugf("Major:Minor for device: %s is:%v:%v", file.Name(), majorNum, minorNum) 1535 return majorNum, minorNum, nil 1536 } 1537 1538 // Given a file which is backing file of a loop back device, find the 1539 // loopback device name and its major/minor number. 1540 func getLoopFileDeviceMajMin(filename string) (string, uint64, uint64, error) { 1541 file, err := os.Open(filename) 1542 if err != nil { 1543 logrus.WithField("storage-driver", "devicemapper").Debugf("Failed to open file %s", filename) 1544 return "", 0, 0, err 1545 } 1546 1547 defer file.Close() 1548 loopbackDevice := loopback.FindLoopDeviceFor(file) 1549 if loopbackDevice == nil { 1550 return "", 0, 0, fmt.Errorf("devmapper: Unable to find loopback mount for: %s", filename) 1551 } 1552 defer loopbackDevice.Close() 1553 1554 Major, Minor, err := getDeviceMajorMinor(loopbackDevice) 1555 if err != nil { 1556 return "", 0, 0, err 1557 } 1558 return loopbackDevice.Name(), Major, Minor, nil 1559 } 1560 1561 // Get the major/minor numbers of thin pool data and metadata devices 1562 func (devices *DeviceSet) getThinPoolDataMetaMajMin() (uint64, uint64, uint64, uint64, error) { 1563 var params, poolDataMajMin, poolMetadataMajMin string 1564 1565 _, _, _, params, err := devicemapper.GetTable(devices.getPoolName()) 1566 if err != nil { 1567 return 0, 0, 0, 0, err 1568 } 1569 1570 if _, err = fmt.Sscanf(params, "%s %s", &poolMetadataMajMin, &poolDataMajMin); err != nil { 1571 return 0, 0, 0, 0, err 1572 } 1573 1574 logrus.WithField("storage-driver", "devicemapper").Debugf("poolDataMajMin=%s poolMetaMajMin=%s\n", poolDataMajMin, poolMetadataMajMin) 1575 1576 poolDataMajMinorSplit := strings.Split(poolDataMajMin, ":") 1577 poolDataMajor, err := strconv.ParseUint(poolDataMajMinorSplit[0], 10, 32) 1578 if err != nil { 1579 return 0, 0, 0, 0, err 1580 } 1581 1582 poolDataMinor, err := strconv.ParseUint(poolDataMajMinorSplit[1], 10, 32) 1583 if err != nil { 1584 return 0, 0, 0, 0, err 1585 } 1586 1587 poolMetadataMajMinorSplit := strings.Split(poolMetadataMajMin, ":") 1588 poolMetadataMajor, err := strconv.ParseUint(poolMetadataMajMinorSplit[0], 10, 32) 1589 if err != nil { 1590 return 0, 0, 0, 0, err 1591 } 1592 1593 poolMetadataMinor, err := strconv.ParseUint(poolMetadataMajMinorSplit[1], 10, 32) 1594 if err != nil { 1595 return 0, 0, 0, 0, err 1596 } 1597 1598 return poolDataMajor, poolDataMinor, poolMetadataMajor, poolMetadataMinor, nil 1599 } 1600 1601 func (devices *DeviceSet) loadThinPoolLoopBackInfo() error { 1602 poolDataMajor, poolDataMinor, poolMetadataMajor, poolMetadataMinor, err := devices.getThinPoolDataMetaMajMin() 1603 if err != nil { 1604 return err 1605 } 1606 1607 dirname := devices.loopbackDir() 1608 1609 // data device has not been passed in. So there should be a data file 1610 // which is being mounted as loop device. 1611 if devices.dataDevice == "" { 1612 datafilename := path.Join(dirname, "data") 1613 dataLoopDevice, dataMajor, dataMinor, err := getLoopFileDeviceMajMin(datafilename) 1614 if err != nil { 1615 return err 1616 } 1617 1618 // Compare the two 1619 if poolDataMajor == dataMajor && poolDataMinor == dataMinor { 1620 devices.dataDevice = dataLoopDevice 1621 devices.dataLoopFile = datafilename 1622 } 1623 } 1624 1625 // metadata device has not been passed in. So there should be a 1626 // metadata file which is being mounted as loop device. 1627 if devices.metadataDevice == "" { 1628 metadatafilename := path.Join(dirname, "metadata") 1629 metadataLoopDevice, metadataMajor, metadataMinor, err := getLoopFileDeviceMajMin(metadatafilename) 1630 if err != nil { 1631 return err 1632 } 1633 if poolMetadataMajor == metadataMajor && poolMetadataMinor == metadataMinor { 1634 devices.metadataDevice = metadataLoopDevice 1635 devices.metadataLoopFile = metadatafilename 1636 } 1637 } 1638 1639 return nil 1640 } 1641 1642 func (devices *DeviceSet) enableDeferredRemovalDeletion() error { 1643 // If user asked for deferred removal then check both libdm library 1644 // and kernel driver support deferred removal otherwise error out. 1645 if enableDeferredRemoval { 1646 if !driverDeferredRemovalSupport { 1647 return fmt.Errorf("devmapper: Deferred removal can not be enabled as kernel does not support it") 1648 } 1649 if !devicemapper.LibraryDeferredRemovalSupport { 1650 return fmt.Errorf("devmapper: Deferred removal can not be enabled as libdm does not support it") 1651 } 1652 logrus.WithField("storage-driver", "devicemapper").Debug("Deferred removal support enabled.") 1653 devices.deferredRemove = true 1654 } 1655 1656 if enableDeferredDeletion { 1657 if !devices.deferredRemove { 1658 return fmt.Errorf("devmapper: Deferred deletion can not be enabled as deferred removal is not enabled. Enable deferred removal using --storage-opt dm.use_deferred_removal=true parameter") 1659 } 1660 logrus.WithField("storage-driver", "devicemapper").Debug("Deferred deletion support enabled.") 1661 devices.deferredDelete = true 1662 } 1663 return nil 1664 } 1665 1666 func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) { 1667 if err := devices.enableDeferredRemovalDeletion(); err != nil { 1668 return err 1669 } 1670 1671 logger := logrus.WithField("storage-driver", "devicemapper") 1672 1673 // https://github.com/docker/docker/issues/4036 1674 if supported := devicemapper.UdevSetSyncSupport(true); !supported { 1675 if dockerversion.IAmStatic == "true" { 1676 logger.Error("Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a dynamic binary to use devicemapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/dockerd/#storage-driver-options") 1677 } else { 1678 logger.Error("Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a more recent version of libdevmapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/dockerd/#storage-driver-options") 1679 } 1680 1681 if !devices.overrideUdevSyncCheck { 1682 return graphdriver.ErrNotSupported 1683 } 1684 } 1685 1686 // create the root dir of the devmapper driver ownership to match this 1687 // daemon's remapped root uid/gid so containers can start properly 1688 if err := idtools.MkdirAndChown(devices.root, 0700, devices.idMap.RootPair()); err != nil { 1689 return err 1690 } 1691 if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil { 1692 return err 1693 } 1694 1695 prevSetupConfig, err := readLVMConfig(devices.root) 1696 if err != nil { 1697 return err 1698 } 1699 1700 if !reflect.DeepEqual(devices.lvmSetupConfig, directLVMConfig{}) { 1701 if devices.thinPoolDevice != "" { 1702 return errors.New("cannot setup direct-lvm when `dm.thinpooldev` is also specified") 1703 } 1704 1705 if !reflect.DeepEqual(prevSetupConfig, devices.lvmSetupConfig) { 1706 if !reflect.DeepEqual(prevSetupConfig, directLVMConfig{}) { 1707 return errors.New("changing direct-lvm config is not supported") 1708 } 1709 logger.WithField("direct-lvm-config", devices.lvmSetupConfig).Debugf("Setting up direct lvm mode") 1710 if err := verifyBlockDevice(devices.lvmSetupConfig.Device, lvmSetupConfigForce); err != nil { 1711 return err 1712 } 1713 if err := setupDirectLVM(devices.lvmSetupConfig); err != nil { 1714 return err 1715 } 1716 if err := writeLVMConfig(devices.root, devices.lvmSetupConfig); err != nil { 1717 return err 1718 } 1719 } 1720 devices.thinPoolDevice = "docker-thinpool" 1721 logger.Debugf("Setting dm.thinpooldev to %q", devices.thinPoolDevice) 1722 } 1723 1724 // Set the device prefix from the device id and inode of the docker root dir 1725 var st unix.Stat_t 1726 if err := unix.Stat(devices.root, &st); err != nil { 1727 return fmt.Errorf("devmapper: Error looking up dir %s: %s", devices.root, err) 1728 } 1729 // "reg-" stands for "regular file". 1730 // In the future we might use "dev-" for "device file", etc. 1731 // docker-maj,min[-inode] stands for: 1732 // - Managed by docker 1733 // - The target of this device is at major <maj> and minor <min> 1734 // - If <inode> is defined, use that file inside the device as a loopback image. Otherwise use the device itself. 1735 // The type Dev in Stat_t is 32bit on mips. 1736 devices.devicePrefix = fmt.Sprintf("docker-%d:%d-%d", major(uint64(st.Dev)), minor(uint64(st.Dev)), st.Ino) //nolint: unconvert 1737 logger.Debugf("Generated prefix: %s", devices.devicePrefix) 1738 1739 // Check for the existence of the thin-pool device 1740 poolExists, err := devices.thinPoolExists(devices.getPoolName()) 1741 if err != nil { 1742 return err 1743 } 1744 1745 // It seems libdevmapper opens this without O_CLOEXEC, and go exec will not close files 1746 // that are not Close-on-exec, 1747 // so we add this badhack to make sure it closes itself 1748 setCloseOnExec("/dev/mapper/control") 1749 1750 // Make sure the sparse images exist in <root>/devicemapper/data and 1751 // <root>/devicemapper/metadata 1752 1753 createdLoopback := false 1754 1755 // If the pool doesn't exist, create it 1756 if !poolExists && devices.thinPoolDevice == "" { 1757 logger.Debug("Pool doesn't exist. Creating it.") 1758 1759 var ( 1760 dataFile *os.File 1761 metadataFile *os.File 1762 ) 1763 1764 if devices.dataDevice == "" { 1765 // Make sure the sparse images exist in <root>/devicemapper/data 1766 1767 hasData := devices.hasImage("data") 1768 1769 if !doInit && !hasData { 1770 return errors.New("loopback data file not found") 1771 } 1772 1773 if !hasData { 1774 createdLoopback = true 1775 } 1776 1777 data, err := devices.ensureImage("data", devices.dataLoopbackSize) 1778 if err != nil { 1779 logger.Debugf("Error device ensureImage (data): %s", err) 1780 return err 1781 } 1782 1783 dataFile, err = loopback.AttachLoopDevice(data) 1784 if err != nil { 1785 return err 1786 } 1787 devices.dataLoopFile = data 1788 devices.dataDevice = dataFile.Name() 1789 } else { 1790 dataFile, err = os.OpenFile(devices.dataDevice, os.O_RDWR, 0600) 1791 if err != nil { 1792 return err 1793 } 1794 } 1795 defer dataFile.Close() 1796 1797 if devices.metadataDevice == "" { 1798 // Make sure the sparse images exist in <root>/devicemapper/metadata 1799 1800 hasMetadata := devices.hasImage("metadata") 1801 1802 if !doInit && !hasMetadata { 1803 return errors.New("loopback metadata file not found") 1804 } 1805 1806 if !hasMetadata { 1807 createdLoopback = true 1808 } 1809 1810 metadata, err := devices.ensureImage("metadata", devices.metaDataLoopbackSize) 1811 if err != nil { 1812 logger.Debugf("Error device ensureImage (metadata): %s", err) 1813 return err 1814 } 1815 1816 metadataFile, err = loopback.AttachLoopDevice(metadata) 1817 if err != nil { 1818 return err 1819 } 1820 devices.metadataLoopFile = metadata 1821 devices.metadataDevice = metadataFile.Name() 1822 } else { 1823 metadataFile, err = os.OpenFile(devices.metadataDevice, os.O_RDWR, 0600) 1824 if err != nil { 1825 return err 1826 } 1827 } 1828 defer metadataFile.Close() 1829 1830 if err := devicemapper.CreatePool(devices.getPoolName(), dataFile, metadataFile, devices.thinpBlockSize); err != nil { 1831 return err 1832 } 1833 defer func() { 1834 if retErr != nil { 1835 err = devices.deactivatePool() 1836 if err != nil { 1837 logger.Warnf("Failed to deactivatePool: %v", err) 1838 } 1839 } 1840 }() 1841 } 1842 1843 // Pool already exists and caller did not pass us a pool. That means 1844 // we probably created pool earlier and could not remove it as some 1845 // containers were still using it. Detect some of the properties of 1846 // pool, like is it using loop devices. 1847 if poolExists && devices.thinPoolDevice == "" { 1848 if err := devices.loadThinPoolLoopBackInfo(); err != nil { 1849 logger.Debugf("Failed to load thin pool loopback device information:%v", err) 1850 return err 1851 } 1852 } 1853 1854 // If we didn't just create the data or metadata image, we need to 1855 // load the transaction id and migrate old metadata 1856 if !createdLoopback { 1857 if err := devices.initMetaData(); err != nil { 1858 return err 1859 } 1860 } 1861 1862 if devices.thinPoolDevice == "" { 1863 if devices.metadataLoopFile != "" || devices.dataLoopFile != "" { 1864 logger.Warn("Usage of loopback devices is strongly discouraged for production use. Please use `--storage-opt dm.thinpooldev` or use `man dockerd` to refer to dm.thinpooldev section.") 1865 } 1866 } 1867 1868 // Right now this loads only NextDeviceID. If there is more metadata 1869 // down the line, we might have to move it earlier. 1870 if err := devices.loadDeviceSetMetaData(); err != nil { 1871 return err 1872 } 1873 1874 // Setup the base image 1875 if doInit { 1876 if err := devices.setupBaseImage(); err != nil { 1877 logger.Debugf("Error device setupBaseImage: %s", err) 1878 return err 1879 } 1880 } 1881 1882 return nil 1883 } 1884 1885 // AddDevice adds a device and registers in the hash. 1886 func (devices *DeviceSet) AddDevice(hash, baseHash string, storageOpt map[string]string) error { 1887 logrus.WithField("storage-driver", "devicemapper").Debugf("AddDevice START(hash=%s basehash=%s)", hash, baseHash) 1888 defer logrus.WithField("storage-driver", "devicemapper").Debugf("AddDevice END(hash=%s basehash=%s)", hash, baseHash) 1889 1890 // If a deleted device exists, return error. 1891 baseInfo, err := devices.lookupDeviceWithLock(baseHash) 1892 if err != nil { 1893 return err 1894 } 1895 1896 if baseInfo.Deleted { 1897 return fmt.Errorf("devmapper: Base device %v has been marked for deferred deletion", baseInfo.Hash) 1898 } 1899 1900 baseInfo.lock.Lock() 1901 defer baseInfo.lock.Unlock() 1902 1903 devices.Lock() 1904 defer devices.Unlock() 1905 1906 // Also include deleted devices in case hash of new device is 1907 // same as one of the deleted devices. 1908 if info, _ := devices.lookupDevice(hash); info != nil { 1909 return fmt.Errorf("devmapper: device %s already exists. Deleted=%v", hash, info.Deleted) 1910 } 1911 1912 size, err := devices.parseStorageOpt(storageOpt) 1913 if err != nil { 1914 return err 1915 } 1916 1917 if size == 0 { 1918 size = baseInfo.Size 1919 } 1920 1921 if size < baseInfo.Size { 1922 return fmt.Errorf("devmapper: Container size cannot be smaller than %s", units.HumanSize(float64(baseInfo.Size))) 1923 } 1924 1925 if err := devices.takeSnapshot(hash, baseInfo, size); err != nil { 1926 return err 1927 } 1928 1929 // Grow the container rootfs. 1930 if size > baseInfo.Size { 1931 info, err := devices.lookupDevice(hash) 1932 if err != nil { 1933 return err 1934 } 1935 1936 if err := devices.growFS(info); err != nil { 1937 return err 1938 } 1939 } 1940 1941 return nil 1942 } 1943 1944 func (devices *DeviceSet) parseStorageOpt(storageOpt map[string]string) (uint64, error) { 1945 // Read size to change the block device size per container. 1946 for key, val := range storageOpt { 1947 key := strings.ToLower(key) 1948 switch key { 1949 case "size": 1950 size, err := units.RAMInBytes(val) 1951 if err != nil { 1952 return 0, err 1953 } 1954 return uint64(size), nil 1955 default: 1956 return 0, fmt.Errorf("Unknown option %s", key) 1957 } 1958 } 1959 1960 return 0, nil 1961 } 1962 1963 func (devices *DeviceSet) markForDeferredDeletion(info *devInfo) error { 1964 // If device is already in deleted state, there is nothing to be done. 1965 if info.Deleted { 1966 return nil 1967 } 1968 1969 logrus.WithField("storage-driver", "devicemapper").Debugf("Marking device %s for deferred deletion.", info.Hash) 1970 1971 info.Deleted = true 1972 1973 // save device metadata to reflect deleted state. 1974 if err := devices.saveMetadata(info); err != nil { 1975 info.Deleted = false 1976 return err 1977 } 1978 1979 devices.nrDeletedDevices++ 1980 return nil 1981 } 1982 1983 // Should be called with devices.Lock() held. 1984 func (devices *DeviceSet) deleteTransaction(info *devInfo, syncDelete bool) error { 1985 if err := devices.openTransaction(info.Hash, info.DeviceID); err != nil { 1986 logrus.WithField("storage-driver", "devicemapper").Debugf("Error opening transaction hash = %s deviceId = %d", "", info.DeviceID) 1987 return err 1988 } 1989 1990 defer devices.closeTransaction() 1991 1992 err := devicemapper.DeleteDevice(devices.getPoolDevName(), info.DeviceID) 1993 if err != nil { 1994 // If syncDelete is true, we want to return error. If deferred 1995 // deletion is not enabled, we return an error. If error is 1996 // something other then EBUSY, return an error. 1997 if syncDelete || !devices.deferredDelete || err != devicemapper.ErrBusy { 1998 logrus.WithField("storage-driver", "devicemapper").Debugf("Error deleting device: %s", err) 1999 return err 2000 } 2001 } 2002 2003 if err == nil { 2004 if err := devices.unregisterDevice(info.Hash); err != nil { 2005 return err 2006 } 2007 // If device was already in deferred delete state that means 2008 // deletion was being tried again later. Reduce the deleted 2009 // device count. 2010 if info.Deleted { 2011 devices.nrDeletedDevices-- 2012 } 2013 devices.markDeviceIDFree(info.DeviceID) 2014 } else { 2015 if err := devices.markForDeferredDeletion(info); err != nil { 2016 return err 2017 } 2018 } 2019 2020 return nil 2021 } 2022 2023 // Issue discard only if device open count is zero. 2024 func (devices *DeviceSet) issueDiscard(info *devInfo) error { 2025 logger := logrus.WithField("storage-driver", "devicemapper") 2026 logger.Debugf("issueDiscard START(device: %s).", info.Hash) 2027 defer logger.Debugf("issueDiscard END(device: %s).", info.Hash) 2028 // This is a workaround for the kernel not discarding block so 2029 // on the thin pool when we remove a thinp device, so we do it 2030 // manually. 2031 // Even if device is deferred deleted, activate it and issue 2032 // discards. 2033 if err := devices.activateDeviceIfNeeded(info, true); err != nil { 2034 return err 2035 } 2036 2037 devinfo, err := devicemapper.GetInfo(info.Name()) 2038 if err != nil { 2039 return err 2040 } 2041 2042 if devinfo.OpenCount != 0 { 2043 logger.Debugf("Device: %s is in use. OpenCount=%d. Not issuing discards.", info.Hash, devinfo.OpenCount) 2044 return nil 2045 } 2046 2047 if err := devicemapper.BlockDeviceDiscard(info.DevName()); err != nil { 2048 logger.Debugf("Error discarding block on device: %s (ignoring)", err) 2049 } 2050 return nil 2051 } 2052 2053 // Should be called with devices.Lock() held. 2054 func (devices *DeviceSet) deleteDevice(info *devInfo, syncDelete bool) error { 2055 if devices.doBlkDiscard { 2056 devices.issueDiscard(info) 2057 } 2058 2059 // Try to deactivate device in case it is active. 2060 // If deferred removal is enabled and deferred deletion is disabled 2061 // then make sure device is removed synchronously. There have been 2062 // some cases of device being busy for short duration and we would 2063 // rather busy wait for device removal to take care of these cases. 2064 deferredRemove := devices.deferredRemove 2065 if !devices.deferredDelete { 2066 deferredRemove = false 2067 } 2068 2069 if err := devices.deactivateDeviceMode(info, deferredRemove); err != nil { 2070 logrus.WithField("storage-driver", "devicemapper").Debugf("Error deactivating device: %s", err) 2071 return err 2072 } 2073 2074 return devices.deleteTransaction(info, syncDelete) 2075 } 2076 2077 // DeleteDevice will return success if device has been marked for deferred 2078 // removal. If one wants to override that and want DeleteDevice() to fail if 2079 // device was busy and could not be deleted, set syncDelete=true. 2080 func (devices *DeviceSet) DeleteDevice(hash string, syncDelete bool) error { 2081 logrus.WithField("storage-driver", "devicemapper").Debugf("DeleteDevice START(hash=%v syncDelete=%v)", hash, syncDelete) 2082 defer logrus.WithField("storage-driver", "devicemapper").Debugf("DeleteDevice END(hash=%v syncDelete=%v)", hash, syncDelete) 2083 info, err := devices.lookupDeviceWithLock(hash) 2084 if err != nil { 2085 return err 2086 } 2087 2088 info.lock.Lock() 2089 defer info.lock.Unlock() 2090 2091 devices.Lock() 2092 defer devices.Unlock() 2093 2094 return devices.deleteDevice(info, syncDelete) 2095 } 2096 2097 func (devices *DeviceSet) deactivatePool() error { 2098 logrus.WithField("storage-driver", "devicemapper").Debug("deactivatePool() START") 2099 defer logrus.WithField("storage-driver", "devicemapper").Debug("deactivatePool() END") 2100 devname := devices.getPoolDevName() 2101 2102 devinfo, err := devicemapper.GetInfo(devname) 2103 if err != nil { 2104 return err 2105 } 2106 2107 if devinfo.Exists == 0 { 2108 return nil 2109 } 2110 if err := devicemapper.RemoveDevice(devname); err != nil { 2111 return err 2112 } 2113 2114 if d, err := devicemapper.GetDeps(devname); err == nil { 2115 logrus.WithField("storage-driver", "devicemapper").Warnf("device %s still has %d active dependents", devname, d.Count) 2116 } 2117 2118 return nil 2119 } 2120 2121 func (devices *DeviceSet) deactivateDevice(info *devInfo) error { 2122 return devices.deactivateDeviceMode(info, devices.deferredRemove) 2123 } 2124 2125 func (devices *DeviceSet) deactivateDeviceMode(info *devInfo, deferredRemove bool) error { 2126 var err error 2127 logrus.WithField("storage-driver", "devicemapper").Debugf("deactivateDevice START(%s)", info.Hash) 2128 defer logrus.WithField("storage-driver", "devicemapper").Debugf("deactivateDevice END(%s)", info.Hash) 2129 2130 devinfo, err := devicemapper.GetInfo(info.Name()) 2131 if err != nil { 2132 return err 2133 } 2134 2135 if devinfo.Exists == 0 { 2136 return nil 2137 } 2138 2139 if deferredRemove { 2140 err = devicemapper.RemoveDeviceDeferred(info.Name()) 2141 } else { 2142 err = devices.removeDevice(info.Name()) 2143 } 2144 2145 // This function's semantics is such that it does not return an 2146 // error if device does not exist. So if device went away by 2147 // the time we actually tried to remove it, do not return error. 2148 if err != devicemapper.ErrEnxio { 2149 return err 2150 } 2151 return nil 2152 } 2153 2154 // Issues the underlying dm remove operation. 2155 func (devices *DeviceSet) removeDevice(devname string) error { 2156 var err error 2157 2158 logrus.WithField("storage-driver", "devicemapper").Debugf("removeDevice START(%s)", devname) 2159 defer logrus.WithField("storage-driver", "devicemapper").Debugf("removeDevice END(%s)", devname) 2160 2161 for i := 0; i < 200; i++ { 2162 err = devicemapper.RemoveDevice(devname) 2163 if err == nil { 2164 break 2165 } 2166 if err != devicemapper.ErrBusy { 2167 return err 2168 } 2169 2170 // If we see EBUSY it may be a transient error, 2171 // sleep a bit a retry a few times. 2172 devices.Unlock() 2173 time.Sleep(100 * time.Millisecond) 2174 devices.Lock() 2175 } 2176 2177 return err 2178 } 2179 2180 func (devices *DeviceSet) cancelDeferredRemovalIfNeeded(info *devInfo) error { 2181 if !devices.deferredRemove { 2182 return nil 2183 } 2184 2185 logrus.WithField("storage-driver", "devicemapper").Debugf("cancelDeferredRemovalIfNeeded START(%s)", info.Name()) 2186 defer logrus.WithField("storage-driver", "devicemapper").Debugf("cancelDeferredRemovalIfNeeded END(%s)", info.Name()) 2187 2188 devinfo, err := devicemapper.GetInfoWithDeferred(info.Name()) 2189 if err != nil { 2190 return err 2191 } 2192 2193 if devinfo != nil && devinfo.DeferredRemove == 0 { 2194 return nil 2195 } 2196 2197 // Cancel deferred remove 2198 if err := devices.cancelDeferredRemoval(info); err != nil { 2199 // If Error is ErrEnxio. Device is probably already gone. Continue. 2200 if err != devicemapper.ErrEnxio { 2201 return err 2202 } 2203 } 2204 return nil 2205 } 2206 2207 func (devices *DeviceSet) cancelDeferredRemoval(info *devInfo) error { 2208 logrus.WithField("storage-driver", "devicemapper").Debugf("cancelDeferredRemoval START(%s)", info.Name()) 2209 defer logrus.WithField("storage-driver", "devicemapper").Debugf("cancelDeferredRemoval END(%s)", info.Name()) 2210 2211 var err error 2212 2213 // Cancel deferred remove 2214 for i := 0; i < 100; i++ { 2215 err = devicemapper.CancelDeferredRemove(info.Name()) 2216 if err != nil { 2217 if err == devicemapper.ErrBusy { 2218 // If we see EBUSY it may be a transient error, 2219 // sleep a bit a retry a few times. 2220 devices.Unlock() 2221 time.Sleep(100 * time.Millisecond) 2222 devices.Lock() 2223 continue 2224 } 2225 } 2226 break 2227 } 2228 return err 2229 } 2230 2231 func (devices *DeviceSet) unmountAndDeactivateAll(dir string) { 2232 logger := logrus.WithField("storage-driver", "devicemapper") 2233 2234 files, err := os.ReadDir(dir) 2235 if err != nil { 2236 logger.Warnf("unmountAndDeactivate: %s", err) 2237 return 2238 } 2239 2240 for _, d := range files { 2241 if !d.IsDir() { 2242 continue 2243 } 2244 2245 name := d.Name() 2246 fullname := path.Join(dir, name) 2247 2248 // We use MNT_DETACH here in case it is still busy in some running 2249 // container. This means it'll go away from the global scope directly, 2250 // and the device will be released when that container dies. 2251 if err := unix.Unmount(fullname, unix.MNT_DETACH); err != nil && err != unix.EINVAL { 2252 logger.Warnf("Shutdown unmounting %s, error: %s", fullname, err) 2253 } 2254 2255 if devInfo, err := devices.lookupDevice(name); err != nil { 2256 logger.Debugf("Shutdown lookup device %s, error: %s", name, err) 2257 } else { 2258 if err := devices.deactivateDevice(devInfo); err != nil { 2259 logger.Debugf("Shutdown deactivate %s, error: %s", devInfo.Hash, err) 2260 } 2261 } 2262 } 2263 } 2264 2265 // Shutdown shuts down the device by unmounting the root. 2266 func (devices *DeviceSet) Shutdown(home string) error { 2267 logger := logrus.WithField("storage-driver", "devicemapper") 2268 2269 logger.Debugf("[deviceset %s] Shutdown()", devices.devicePrefix) 2270 logger.Debugf("Shutting down DeviceSet: %s", devices.root) 2271 defer logger.Debugf("[deviceset %s] Shutdown() END", devices.devicePrefix) 2272 2273 // Stop deletion worker. This should start delivering new events to 2274 // ticker channel. That means no new instance of cleanupDeletedDevice() 2275 // will run after this call. If one instance is already running at 2276 // the time of the call, it must be holding devices.Lock() and 2277 // we will block on this lock till cleanup function exits. 2278 devices.deletionWorkerTicker.Stop() 2279 2280 devices.Lock() 2281 // Save DeviceSet Metadata first. Docker kills all threads if they 2282 // don't finish in certain time. It is possible that Shutdown() 2283 // routine does not finish in time as we loop trying to deactivate 2284 // some devices while these are busy. In that case shutdown() routine 2285 // will be killed and we will not get a chance to save deviceset 2286 // metadata. Hence save this early before trying to deactivate devices. 2287 devices.saveDeviceSetMetaData() 2288 devices.unmountAndDeactivateAll(path.Join(home, "mnt")) 2289 devices.Unlock() 2290 2291 info, _ := devices.lookupDeviceWithLock("") 2292 if info != nil { 2293 info.lock.Lock() 2294 devices.Lock() 2295 if err := devices.deactivateDevice(info); err != nil { 2296 logger.Debugf("Shutdown deactivate base , error: %s", err) 2297 } 2298 devices.Unlock() 2299 info.lock.Unlock() 2300 } 2301 2302 devices.Lock() 2303 if devices.thinPoolDevice == "" { 2304 if err := devices.deactivatePool(); err != nil { 2305 logger.Debugf("Shutdown deactivate pool , error: %s", err) 2306 } 2307 } 2308 devices.Unlock() 2309 2310 return nil 2311 } 2312 2313 // Recent XFS changes allow changing behavior of filesystem in case of errors. 2314 // When thin pool gets full and XFS gets ENOSPC error, currently it tries 2315 // IO infinitely and sometimes it can block the container process 2316 // and process can't be killWith 0 value, XFS will not retry upon error 2317 // and instead will shutdown filesystem. 2318 2319 func (devices *DeviceSet) xfsSetNospaceRetries(info *devInfo) error { 2320 dmDevicePath, err := os.Readlink(info.DevName()) 2321 if err != nil { 2322 return fmt.Errorf("devmapper: readlink failed for device %v:%v", info.DevName(), err) 2323 } 2324 2325 dmDeviceName := path.Base(dmDevicePath) 2326 filePath := "/sys/fs/xfs/" + dmDeviceName + "/error/metadata/ENOSPC/max_retries" 2327 maxRetriesFile, err := os.OpenFile(filePath, os.O_WRONLY, 0) 2328 if err != nil { 2329 return fmt.Errorf("devmapper: user specified daemon option dm.xfs_nospace_max_retries but it does not seem to be supported on this system :%v", err) 2330 } 2331 defer maxRetriesFile.Close() 2332 2333 // Set max retries to 0 2334 _, err = maxRetriesFile.WriteString(devices.xfsNospaceRetries) 2335 if err != nil { 2336 return fmt.Errorf("devmapper: Failed to write string %v to file %v:%v", devices.xfsNospaceRetries, filePath, err) 2337 } 2338 return nil 2339 } 2340 2341 // MountDevice mounts the device if not already mounted. 2342 func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { 2343 info, err := devices.lookupDeviceWithLock(hash) 2344 if err != nil { 2345 return err 2346 } 2347 2348 if info.Deleted { 2349 return fmt.Errorf("devmapper: Can't mount device %v as it has been marked for deferred deletion", info.Hash) 2350 } 2351 2352 info.lock.Lock() 2353 defer info.lock.Unlock() 2354 2355 devices.Lock() 2356 defer devices.Unlock() 2357 2358 if err := devices.activateDeviceIfNeeded(info, false); err != nil { 2359 return fmt.Errorf("devmapper: Error activating devmapper device for '%s': %s", hash, err) 2360 } 2361 2362 fstype, err := ProbeFsType(info.DevName()) 2363 if err != nil { 2364 return err 2365 } 2366 2367 options := "" 2368 2369 if fstype == "xfs" { 2370 // XFS needs nouuid or it can't mount filesystems with the same fs 2371 options = joinMountOptions(options, "nouuid") 2372 } 2373 2374 options = joinMountOptions(options, devices.mountOptions) 2375 options = joinMountOptions(options, label.FormatMountLabel("", mountLabel)) 2376 2377 if err := mount.Mount(info.DevName(), path, fstype, options); err != nil { 2378 return errors.Wrapf(err, "Failed to mount; dmesg: %s", string(dmesg.Dmesg(256))) 2379 } 2380 2381 if fstype == "xfs" && devices.xfsNospaceRetries != "" { 2382 if err := devices.xfsSetNospaceRetries(info); err != nil { 2383 unix.Unmount(path, unix.MNT_DETACH) 2384 devices.deactivateDevice(info) 2385 return err 2386 } 2387 } 2388 2389 return nil 2390 } 2391 2392 // UnmountDevice unmounts the device and removes it from hash. 2393 func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error { 2394 logger := logrus.WithField("storage-driver", "devicemapper") 2395 2396 logger.Debugf("UnmountDevice START(hash=%s)", hash) 2397 defer logger.Debugf("UnmountDevice END(hash=%s)", hash) 2398 2399 info, err := devices.lookupDeviceWithLock(hash) 2400 if err != nil { 2401 return err 2402 } 2403 2404 info.lock.Lock() 2405 defer info.lock.Unlock() 2406 2407 devices.Lock() 2408 defer devices.Unlock() 2409 2410 logger.Debugf("Unmount(%s)", mountPath) 2411 if err := unix.Unmount(mountPath, unix.MNT_DETACH); err != nil { 2412 return err 2413 } 2414 logger.Debug("Unmount done") 2415 2416 // Remove the mountpoint here. Removing the mountpoint (in newer kernels) 2417 // will cause all other instances of this mount in other mount namespaces 2418 // to be killed (this is an anti-DoS measure that is necessary for things 2419 // like devicemapper). This is necessary to avoid cases where a libdm mount 2420 // that is present in another namespace will cause subsequent RemoveDevice 2421 // operations to fail. We ignore any errors here because this may fail on 2422 // older kernels which don't have 2423 // torvalds/linux@8ed936b5671bfb33d89bc60bdcc7cf0470ba52fe applied. 2424 if err := os.Remove(mountPath); err != nil { 2425 logger.Debugf("error doing a remove on unmounted device %s: %v", mountPath, err) 2426 } 2427 2428 return devices.deactivateDevice(info) 2429 } 2430 2431 // HasDevice returns true if the device metadata exists. 2432 func (devices *DeviceSet) HasDevice(hash string) bool { 2433 info, _ := devices.lookupDeviceWithLock(hash) 2434 return info != nil 2435 } 2436 2437 // List returns a list of device ids. 2438 func (devices *DeviceSet) List() []string { 2439 devices.Lock() 2440 defer devices.Unlock() 2441 2442 ids := make([]string, len(devices.Devices)) 2443 i := 0 2444 for k := range devices.Devices { 2445 ids[i] = k 2446 i++ 2447 } 2448 return ids 2449 } 2450 2451 func (devices *DeviceSet) deviceStatus(devName string) (sizeInSectors, mappedSectors, highestMappedSector uint64, err error) { 2452 var params string 2453 _, sizeInSectors, _, params, err = devicemapper.GetStatus(devName) 2454 if err != nil { 2455 return 2456 } 2457 if _, err = fmt.Sscanf(params, "%d %d", &mappedSectors, &highestMappedSector); err == nil { 2458 return 2459 } 2460 return 2461 } 2462 2463 // GetDeviceStatus provides size, mapped sectors 2464 func (devices *DeviceSet) GetDeviceStatus(hash string) (*DevStatus, error) { 2465 info, err := devices.lookupDeviceWithLock(hash) 2466 if err != nil { 2467 return nil, err 2468 } 2469 2470 info.lock.Lock() 2471 defer info.lock.Unlock() 2472 2473 devices.Lock() 2474 defer devices.Unlock() 2475 2476 status := &DevStatus{ 2477 DeviceID: info.DeviceID, 2478 Size: info.Size, 2479 TransactionID: info.TransactionID, 2480 } 2481 2482 if err := devices.activateDeviceIfNeeded(info, false); err != nil { 2483 return nil, fmt.Errorf("devmapper: Error activating devmapper device for '%s': %s", hash, err) 2484 } 2485 2486 sizeInSectors, mappedSectors, highestMappedSector, err := devices.deviceStatus(info.DevName()) 2487 2488 if err != nil { 2489 return nil, err 2490 } 2491 2492 status.SizeInSectors = sizeInSectors 2493 status.MappedSectors = mappedSectors 2494 status.HighestMappedSector = highestMappedSector 2495 2496 return status, nil 2497 } 2498 2499 func (devices *DeviceSet) poolStatus() (totalSizeInSectors, transactionID, dataUsed, dataTotal, metadataUsed, metadataTotal uint64, err error) { 2500 var params string 2501 if _, totalSizeInSectors, _, params, err = devicemapper.GetStatus(devices.getPoolName()); err == nil { 2502 _, err = fmt.Sscanf(params, "%d %d/%d %d/%d", &transactionID, &metadataUsed, &metadataTotal, &dataUsed, &dataTotal) 2503 } 2504 return 2505 } 2506 2507 // DataDevicePath returns the path to the data storage for this deviceset, 2508 // regardless of loopback or block device 2509 func (devices *DeviceSet) DataDevicePath() string { 2510 return devices.dataDevice 2511 } 2512 2513 // MetadataDevicePath returns the path to the metadata storage for this deviceset, 2514 // regardless of loopback or block device 2515 func (devices *DeviceSet) MetadataDevicePath() string { 2516 return devices.metadataDevice 2517 } 2518 2519 func (devices *DeviceSet) getUnderlyingAvailableSpace(loopFile string) (uint64, error) { 2520 buf := new(unix.Statfs_t) 2521 if err := unix.Statfs(loopFile, buf); err != nil { 2522 logrus.WithField("storage-driver", "devicemapper").Warnf("Couldn't stat loopfile filesystem %v: %v", loopFile, err) 2523 return 0, err 2524 } 2525 return buf.Bfree * uint64(buf.Bsize), nil 2526 } 2527 2528 func (devices *DeviceSet) isRealFile(loopFile string) (bool, error) { 2529 if loopFile != "" { 2530 fi, err := os.Stat(loopFile) 2531 if err != nil { 2532 logrus.WithField("storage-driver", "devicemapper").Warnf("Couldn't stat loopfile %v: %v", loopFile, err) 2533 return false, err 2534 } 2535 return fi.Mode().IsRegular(), nil 2536 } 2537 return false, nil 2538 } 2539 2540 // Status returns the current status of this deviceset 2541 func (devices *DeviceSet) Status() *Status { 2542 devices.Lock() 2543 defer devices.Unlock() 2544 2545 status := &Status{} 2546 2547 status.PoolName = devices.getPoolName() 2548 status.DataFile = devices.DataDevicePath() 2549 status.DataLoopback = devices.dataLoopFile 2550 status.MetadataFile = devices.MetadataDevicePath() 2551 status.MetadataLoopback = devices.metadataLoopFile 2552 status.UdevSyncSupported = devicemapper.UdevSyncSupported() 2553 status.DeferredRemoveEnabled = devices.deferredRemove 2554 status.DeferredDeleteEnabled = devices.deferredDelete 2555 status.DeferredDeletedDeviceCount = devices.nrDeletedDevices 2556 status.BaseDeviceSize = devices.getBaseDeviceSize() 2557 status.BaseDeviceFS = devices.getBaseDeviceFS() 2558 2559 totalSizeInSectors, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus() 2560 if err == nil { 2561 // Convert from blocks to bytes 2562 blockSizeInSectors := totalSizeInSectors / dataTotal 2563 2564 status.Data.Used = dataUsed * blockSizeInSectors * 512 2565 status.Data.Total = dataTotal * blockSizeInSectors * 512 2566 status.Data.Available = status.Data.Total - status.Data.Used 2567 2568 // metadata blocks are always 4k 2569 status.Metadata.Used = metadataUsed * 4096 2570 status.Metadata.Total = metadataTotal * 4096 2571 status.Metadata.Available = status.Metadata.Total - status.Metadata.Used 2572 2573 status.SectorSize = blockSizeInSectors * 512 2574 2575 if check, _ := devices.isRealFile(devices.dataLoopFile); check { 2576 actualSpace, err := devices.getUnderlyingAvailableSpace(devices.dataLoopFile) 2577 if err == nil && actualSpace < status.Data.Available { 2578 status.Data.Available = actualSpace 2579 } 2580 } 2581 2582 if check, _ := devices.isRealFile(devices.metadataLoopFile); check { 2583 actualSpace, err := devices.getUnderlyingAvailableSpace(devices.metadataLoopFile) 2584 if err == nil && actualSpace < status.Metadata.Available { 2585 status.Metadata.Available = actualSpace 2586 } 2587 } 2588 2589 minFreeData := (dataTotal * uint64(devices.minFreeSpacePercent)) / 100 2590 status.MinFreeSpace = minFreeData * blockSizeInSectors * 512 2591 } 2592 2593 return status 2594 } 2595 2596 // Status returns the current status of this deviceset 2597 func (devices *DeviceSet) exportDeviceMetadata(hash string) (*deviceMetadata, error) { 2598 info, err := devices.lookupDeviceWithLock(hash) 2599 if err != nil { 2600 return nil, err 2601 } 2602 2603 info.lock.Lock() 2604 defer info.lock.Unlock() 2605 2606 metadata := &deviceMetadata{info.DeviceID, info.Size, info.Name()} 2607 return metadata, nil 2608 } 2609 2610 // NewDeviceSet creates the device set based on the options provided. 2611 func NewDeviceSet(root string, doInit bool, options []string, idMap idtools.IdentityMapping) (*DeviceSet, error) { 2612 devicemapper.SetDevDir("/dev") 2613 2614 devices := &DeviceSet{ 2615 root: root, 2616 metaData: metaData{Devices: make(map[string]*devInfo)}, 2617 dataLoopbackSize: defaultDataLoopbackSize, 2618 metaDataLoopbackSize: defaultMetaDataLoopbackSize, 2619 baseFsSize: defaultBaseFsSize, 2620 overrideUdevSyncCheck: defaultUdevSyncOverride, 2621 doBlkDiscard: true, 2622 thinpBlockSize: defaultThinpBlockSize, 2623 deviceIDMap: make([]byte, deviceIDMapSz), 2624 deletionWorkerTicker: time.NewTicker(time.Second * 30), 2625 idMap: idMap, 2626 minFreeSpacePercent: defaultMinFreeSpacePercent, 2627 } 2628 2629 version, err := devicemapper.GetDriverVersion() 2630 if err != nil { 2631 // Can't even get driver version, assume not supported 2632 return nil, graphdriver.ErrNotSupported 2633 } 2634 2635 if err := determineDriverCapabilities(version); err != nil { 2636 return nil, graphdriver.ErrNotSupported 2637 } 2638 2639 if driverDeferredRemovalSupport && devicemapper.LibraryDeferredRemovalSupport { 2640 // enable deferred stuff by default 2641 enableDeferredDeletion = true 2642 enableDeferredRemoval = true 2643 } 2644 2645 foundBlkDiscard := false 2646 var lvmSetupConfig directLVMConfig 2647 for _, option := range options { 2648 key, val, err := parsers.ParseKeyValueOpt(option) 2649 if err != nil { 2650 return nil, err 2651 } 2652 key = strings.ToLower(key) 2653 switch key { 2654 case "dm.basesize": 2655 size, err := units.RAMInBytes(val) 2656 if err != nil { 2657 return nil, err 2658 } 2659 userBaseSize = true 2660 devices.baseFsSize = uint64(size) 2661 case "dm.loopdatasize": 2662 size, err := units.RAMInBytes(val) 2663 if err != nil { 2664 return nil, err 2665 } 2666 devices.dataLoopbackSize = size 2667 case "dm.loopmetadatasize": 2668 size, err := units.RAMInBytes(val) 2669 if err != nil { 2670 return nil, err 2671 } 2672 devices.metaDataLoopbackSize = size 2673 case "dm.fs": 2674 if val != "ext4" && val != "xfs" { 2675 return nil, fmt.Errorf("devmapper: Unsupported filesystem %s", val) 2676 } 2677 devices.filesystem = val 2678 case "dm.mkfsarg": 2679 devices.mkfsArgs = append(devices.mkfsArgs, val) 2680 case "dm.mountopt": 2681 devices.mountOptions = joinMountOptions(devices.mountOptions, val) 2682 case "dm.metadatadev": 2683 devices.metadataDevice = val 2684 case "dm.datadev": 2685 devices.dataDevice = val 2686 case "dm.thinpooldev": 2687 devices.thinPoolDevice = strings.TrimPrefix(val, "/dev/mapper/") 2688 case "dm.blkdiscard": 2689 foundBlkDiscard = true 2690 devices.doBlkDiscard, err = strconv.ParseBool(val) 2691 if err != nil { 2692 return nil, err 2693 } 2694 case "dm.blocksize": 2695 size, err := units.RAMInBytes(val) 2696 if err != nil { 2697 return nil, err 2698 } 2699 // convert to 512b sectors 2700 devices.thinpBlockSize = uint32(size) >> 9 2701 case "dm.override_udev_sync_check": 2702 devices.overrideUdevSyncCheck, err = strconv.ParseBool(val) 2703 if err != nil { 2704 return nil, err 2705 } 2706 2707 case "dm.use_deferred_removal": 2708 enableDeferredRemoval, err = strconv.ParseBool(val) 2709 if err != nil { 2710 return nil, err 2711 } 2712 2713 case "dm.use_deferred_deletion": 2714 enableDeferredDeletion, err = strconv.ParseBool(val) 2715 if err != nil { 2716 return nil, err 2717 } 2718 2719 case "dm.min_free_space": 2720 if !strings.HasSuffix(val, "%") { 2721 return nil, fmt.Errorf("devmapper: Option dm.min_free_space requires %% suffix") 2722 } 2723 2724 valstring := strings.TrimSuffix(val, "%") 2725 minFreeSpacePercent, err := strconv.ParseUint(valstring, 10, 32) 2726 if err != nil { 2727 return nil, err 2728 } 2729 2730 if minFreeSpacePercent >= 100 { 2731 return nil, fmt.Errorf("devmapper: Invalid value %v for option dm.min_free_space", val) 2732 } 2733 2734 devices.minFreeSpacePercent = uint32(minFreeSpacePercent) 2735 case "dm.xfs_nospace_max_retries": 2736 _, err := strconv.ParseUint(val, 10, 64) 2737 if err != nil { 2738 return nil, err 2739 } 2740 devices.xfsNospaceRetries = val 2741 case "dm.directlvm_device": 2742 lvmSetupConfig.Device = val 2743 case "dm.directlvm_device_force": 2744 lvmSetupConfigForce, err = strconv.ParseBool(val) 2745 if err != nil { 2746 return nil, err 2747 } 2748 case "dm.thinp_percent": 2749 per, err := strconv.ParseUint(strings.TrimSuffix(val, "%"), 10, 32) 2750 if err != nil { 2751 return nil, errors.Wrapf(err, "could not parse `dm.thinp_percent=%s`", val) 2752 } 2753 if per >= 100 { 2754 return nil, errors.New("dm.thinp_percent must be greater than 0 and less than 100") 2755 } 2756 lvmSetupConfig.ThinpPercent = per 2757 case "dm.thinp_metapercent": 2758 per, err := strconv.ParseUint(strings.TrimSuffix(val, "%"), 10, 32) 2759 if err != nil { 2760 return nil, errors.Wrapf(err, "could not parse `dm.thinp_metapercent=%s`", val) 2761 } 2762 if per >= 100 { 2763 return nil, errors.New("dm.thinp_metapercent must be greater than 0 and less than 100") 2764 } 2765 lvmSetupConfig.ThinpMetaPercent = per 2766 case "dm.thinp_autoextend_percent": 2767 per, err := strconv.ParseUint(strings.TrimSuffix(val, "%"), 10, 32) 2768 if err != nil { 2769 return nil, errors.Wrapf(err, "could not parse `dm.thinp_autoextend_percent=%s`", val) 2770 } 2771 if per > 100 { 2772 return nil, errors.New("dm.thinp_autoextend_percent must be greater than 0 and less than 100") 2773 } 2774 lvmSetupConfig.AutoExtendPercent = per 2775 case "dm.thinp_autoextend_threshold": 2776 per, err := strconv.ParseUint(strings.TrimSuffix(val, "%"), 10, 32) 2777 if err != nil { 2778 return nil, errors.Wrapf(err, "could not parse `dm.thinp_autoextend_threshold=%s`", val) 2779 } 2780 if per > 100 { 2781 return nil, errors.New("dm.thinp_autoextend_threshold must be greater than 0 and less than 100") 2782 } 2783 lvmSetupConfig.AutoExtendThreshold = per 2784 case "dm.libdm_log_level": 2785 level, err := strconv.ParseInt(val, 10, 32) 2786 if err != nil { 2787 return nil, errors.Wrapf(err, "could not parse `dm.libdm_log_level=%s`", val) 2788 } 2789 if level < devicemapper.LogLevelFatal || level > devicemapper.LogLevelDebug { 2790 return nil, errors.Errorf("dm.libdm_log_level must be in range [%d,%d]", devicemapper.LogLevelFatal, devicemapper.LogLevelDebug) 2791 } 2792 // Register a new logging callback with the specified level. 2793 devicemapper.LogInit(devicemapper.DefaultLogger{ 2794 Level: int(level), 2795 }) 2796 default: 2797 return nil, fmt.Errorf("devmapper: Unknown option %s", key) 2798 } 2799 } 2800 2801 if err := validateLVMConfig(lvmSetupConfig); err != nil { 2802 return nil, err 2803 } 2804 2805 devices.lvmSetupConfig = lvmSetupConfig 2806 2807 // By default, don't do blk discard hack on raw devices, its rarely useful and is expensive 2808 if !foundBlkDiscard && (devices.dataDevice != "" || devices.thinPoolDevice != "") { 2809 devices.doBlkDiscard = false 2810 } 2811 2812 if err := devices.initDevmapper(doInit); err != nil { 2813 return nil, err 2814 } 2815 2816 return devices, nil 2817 }