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