github.com/afein/docker@v1.8.2/daemon/graphdriver/devmapper/deviceset.go (about) 1 // +build linux 2 3 package devmapper 4 5 import ( 6 "encoding/json" 7 "errors" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "os" 12 "os/exec" 13 "path" 14 "path/filepath" 15 "strconv" 16 "strings" 17 "sync" 18 "syscall" 19 "time" 20 21 "github.com/Sirupsen/logrus" 22 "github.com/docker/docker/daemon/graphdriver" 23 "github.com/docker/docker/pkg/devicemapper" 24 "github.com/docker/docker/pkg/parsers" 25 "github.com/docker/docker/pkg/units" 26 "github.com/opencontainers/runc/libcontainer/label" 27 ) 28 29 var ( 30 DefaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024 31 DefaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024 32 DefaultBaseFsSize uint64 = 100 * 1024 * 1024 * 1024 33 DefaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors 34 DefaultUdevSyncOverride bool = false 35 MaxDeviceId int = 0xffffff // 24 bit, pool limit 36 DeviceIdMapSz int = (MaxDeviceId + 1) / 8 37 // We retry device removal so many a times that even error messages 38 // will fill up console during normal operation. So only log Fatal 39 // messages by default. 40 DMLogLevel int = devicemapper.LogLevelFatal 41 DriverDeferredRemovalSupport bool = false 42 EnableDeferredRemoval bool = false 43 ) 44 45 const deviceSetMetaFile string = "deviceset-metadata" 46 const transactionMetaFile string = "transaction-metadata" 47 48 type Transaction struct { 49 OpenTransactionId uint64 `json:"open_transaction_id"` 50 DeviceIdHash string `json:"device_hash"` 51 DeviceId int `json:"device_id"` 52 } 53 54 type DevInfo struct { 55 Hash string `json:"-"` 56 DeviceId int `json:"device_id"` 57 Size uint64 `json:"size"` 58 TransactionId uint64 `json:"transaction_id"` 59 Initialized bool `json:"initialized"` 60 devices *DeviceSet 61 62 mountCount int 63 mountPath string 64 65 // The global DeviceSet lock guarantees that we serialize all 66 // the calls to libdevmapper (which is not threadsafe), but we 67 // sometimes release that lock while sleeping. In that case 68 // this per-device lock is still held, protecting against 69 // other accesses to the device that we're doing the wait on. 70 // 71 // WARNING: In order to avoid AB-BA deadlocks when releasing 72 // the global lock while holding the per-device locks all 73 // device locks must be aquired *before* the device lock, and 74 // multiple device locks should be aquired parent before child. 75 lock sync.Mutex 76 } 77 78 type MetaData struct { 79 Devices map[string]*DevInfo `json:"Devices"` 80 devicesLock sync.Mutex // Protects all read/writes to Devices map 81 } 82 83 type DeviceSet struct { 84 MetaData `json:"-"` 85 sync.Mutex `json:"-"` // Protects Devices map and serializes calls into libdevmapper 86 root string 87 devicePrefix string 88 TransactionId uint64 `json:"-"` 89 NextDeviceId int `json:"next_device_id"` 90 deviceIdMap []byte 91 92 // Options 93 dataLoopbackSize int64 94 metaDataLoopbackSize int64 95 baseFsSize uint64 96 filesystem string 97 mountOptions string 98 mkfsArgs []string 99 dataDevice string // block or loop dev 100 dataLoopFile string // loopback file, if used 101 metadataDevice string // block or loop dev 102 metadataLoopFile string // loopback file, if used 103 doBlkDiscard bool 104 thinpBlockSize uint32 105 thinPoolDevice string 106 Transaction `json:"-"` 107 overrideUdevSyncCheck bool 108 deferredRemove bool // use deferred removal 109 BaseDeviceUUID string //save UUID of base device 110 } 111 112 type DiskUsage struct { 113 Used uint64 114 Total uint64 115 Available uint64 116 } 117 118 type Status struct { 119 PoolName string 120 DataFile string // actual block device for data 121 DataLoopback string // loopback file, if used 122 MetadataFile string // actual block device for metadata 123 MetadataLoopback string // loopback file, if used 124 Data DiskUsage 125 Metadata DiskUsage 126 SectorSize uint64 127 UdevSyncSupported bool 128 DeferredRemoveEnabled bool 129 } 130 131 // Structure used to export image/container metadata in docker inspect. 132 type DeviceMetadata struct { 133 deviceId int 134 deviceSize uint64 // size in bytes 135 deviceName string // Device name as used during activation 136 } 137 138 type DevStatus struct { 139 DeviceId int 140 Size uint64 141 TransactionId uint64 142 SizeInSectors uint64 143 MappedSectors uint64 144 HighestMappedSector uint64 145 } 146 147 func getDevName(name string) string { 148 return "/dev/mapper/" + name 149 } 150 151 func (info *DevInfo) Name() string { 152 hash := info.Hash 153 if hash == "" { 154 hash = "base" 155 } 156 return fmt.Sprintf("%s-%s", info.devices.devicePrefix, hash) 157 } 158 159 func (info *DevInfo) DevName() string { 160 return getDevName(info.Name()) 161 } 162 163 func (devices *DeviceSet) loopbackDir() string { 164 return path.Join(devices.root, "devicemapper") 165 } 166 167 func (devices *DeviceSet) metadataDir() string { 168 return path.Join(devices.root, "metadata") 169 } 170 171 func (devices *DeviceSet) metadataFile(info *DevInfo) string { 172 file := info.Hash 173 if file == "" { 174 file = "base" 175 } 176 return path.Join(devices.metadataDir(), file) 177 } 178 179 func (devices *DeviceSet) transactionMetaFile() string { 180 return path.Join(devices.metadataDir(), transactionMetaFile) 181 } 182 183 func (devices *DeviceSet) deviceSetMetaFile() string { 184 return path.Join(devices.metadataDir(), deviceSetMetaFile) 185 } 186 187 func (devices *DeviceSet) oldMetadataFile() string { 188 return path.Join(devices.loopbackDir(), "json") 189 } 190 191 func (devices *DeviceSet) getPoolName() string { 192 if devices.thinPoolDevice == "" { 193 return devices.devicePrefix + "-pool" 194 } 195 return devices.thinPoolDevice 196 } 197 198 func (devices *DeviceSet) getPoolDevName() string { 199 return getDevName(devices.getPoolName()) 200 } 201 202 func (devices *DeviceSet) hasImage(name string) bool { 203 dirname := devices.loopbackDir() 204 filename := path.Join(dirname, name) 205 206 _, err := os.Stat(filename) 207 return err == nil 208 } 209 210 // ensureImage creates a sparse file of <size> bytes at the path 211 // <root>/devicemapper/<name>. 212 // If the file already exists, it does nothing. 213 // Either way it returns the full path. 214 func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) { 215 dirname := devices.loopbackDir() 216 filename := path.Join(dirname, name) 217 218 if err := os.MkdirAll(dirname, 0700); err != nil && !os.IsExist(err) { 219 return "", err 220 } 221 222 if _, err := os.Stat(filename); err != nil { 223 if !os.IsNotExist(err) { 224 return "", err 225 } 226 logrus.Debugf("Creating loopback file %s for device-manage use", filename) 227 file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600) 228 if err != nil { 229 return "", err 230 } 231 defer file.Close() 232 233 if err := file.Truncate(size); err != nil { 234 return "", err 235 } 236 } 237 return filename, nil 238 } 239 240 func (devices *DeviceSet) allocateTransactionId() uint64 { 241 devices.OpenTransactionId = devices.TransactionId + 1 242 return devices.OpenTransactionId 243 } 244 245 func (devices *DeviceSet) updatePoolTransactionId() error { 246 if err := devicemapper.SetTransactionId(devices.getPoolDevName(), devices.TransactionId, devices.OpenTransactionId); err != nil { 247 return fmt.Errorf("Error setting devmapper transaction ID: %s", err) 248 } 249 devices.TransactionId = devices.OpenTransactionId 250 return nil 251 } 252 253 func (devices *DeviceSet) removeMetadata(info *DevInfo) error { 254 if err := os.RemoveAll(devices.metadataFile(info)); err != nil { 255 return fmt.Errorf("Error removing metadata file %s: %s", devices.metadataFile(info), err) 256 } 257 return nil 258 } 259 260 // Given json data and file path, write it to disk 261 func (devices *DeviceSet) writeMetaFile(jsonData []byte, filePath string) error { 262 tmpFile, err := ioutil.TempFile(devices.metadataDir(), ".tmp") 263 if err != nil { 264 return fmt.Errorf("Error creating metadata file: %s", err) 265 } 266 267 n, err := tmpFile.Write(jsonData) 268 if err != nil { 269 return fmt.Errorf("Error writing metadata to %s: %s", tmpFile.Name(), err) 270 } 271 if n < len(jsonData) { 272 return io.ErrShortWrite 273 } 274 if err := tmpFile.Sync(); err != nil { 275 return fmt.Errorf("Error syncing metadata file %s: %s", tmpFile.Name(), err) 276 } 277 if err := tmpFile.Close(); err != nil { 278 return fmt.Errorf("Error closing metadata file %s: %s", tmpFile.Name(), err) 279 } 280 if err := os.Rename(tmpFile.Name(), filePath); err != nil { 281 return fmt.Errorf("Error committing metadata file %s: %s", tmpFile.Name(), err) 282 } 283 284 return nil 285 } 286 287 func (devices *DeviceSet) saveMetadata(info *DevInfo) error { 288 jsonData, err := json.Marshal(info) 289 if err != nil { 290 return fmt.Errorf("Error encoding metadata to json: %s", err) 291 } 292 if err := devices.writeMetaFile(jsonData, devices.metadataFile(info)); err != nil { 293 return err 294 } 295 return nil 296 } 297 298 func (devices *DeviceSet) markDeviceIdUsed(deviceId int) { 299 var mask byte 300 i := deviceId % 8 301 mask = 1 << uint(i) 302 devices.deviceIdMap[deviceId/8] = devices.deviceIdMap[deviceId/8] | mask 303 } 304 305 func (devices *DeviceSet) markDeviceIdFree(deviceId int) { 306 var mask byte 307 i := deviceId % 8 308 mask = ^(1 << uint(i)) 309 devices.deviceIdMap[deviceId/8] = devices.deviceIdMap[deviceId/8] & mask 310 } 311 312 func (devices *DeviceSet) isDeviceIdFree(deviceId int) bool { 313 var mask byte 314 i := deviceId % 8 315 mask = (1 << uint(i)) 316 if (devices.deviceIdMap[deviceId/8] & mask) != 0 { 317 return false 318 } 319 return true 320 } 321 322 func (devices *DeviceSet) lookupDevice(hash string) (*DevInfo, error) { 323 devices.devicesLock.Lock() 324 defer devices.devicesLock.Unlock() 325 info := devices.Devices[hash] 326 if info == nil { 327 info = devices.loadMetadata(hash) 328 if info == nil { 329 return nil, fmt.Errorf("Unknown device %s", hash) 330 } 331 332 devices.Devices[hash] = info 333 } 334 return info, nil 335 } 336 337 func (devices *DeviceSet) deviceFileWalkFunction(path string, finfo os.FileInfo) error { 338 339 // Skip some of the meta files which are not device files. 340 if strings.HasSuffix(finfo.Name(), ".migrated") { 341 logrus.Debugf("Skipping file %s", path) 342 return nil 343 } 344 345 if strings.HasPrefix(finfo.Name(), ".") { 346 logrus.Debugf("Skipping file %s", path) 347 return nil 348 } 349 350 if finfo.Name() == deviceSetMetaFile { 351 logrus.Debugf("Skipping file %s", path) 352 return nil 353 } 354 355 logrus.Debugf("Loading data for file %s", path) 356 357 hash := finfo.Name() 358 if hash == "base" { 359 hash = "" 360 } 361 362 dinfo := devices.loadMetadata(hash) 363 if dinfo == nil { 364 return fmt.Errorf("Error loading device metadata file %s", hash) 365 } 366 367 if dinfo.DeviceId > MaxDeviceId { 368 logrus.Errorf("Ignoring Invalid DeviceId=%d", dinfo.DeviceId) 369 return nil 370 } 371 372 devices.Lock() 373 devices.markDeviceIdUsed(dinfo.DeviceId) 374 devices.Unlock() 375 376 logrus.Debugf("Added deviceId=%d to DeviceIdMap", dinfo.DeviceId) 377 return nil 378 } 379 380 func (devices *DeviceSet) constructDeviceIdMap() error { 381 logrus.Debugf("[deviceset] constructDeviceIdMap()") 382 defer logrus.Debugf("[deviceset] constructDeviceIdMap() END") 383 384 var scan = func(path string, info os.FileInfo, err error) error { 385 if err != nil { 386 logrus.Debugf("Can't walk the file %s", path) 387 return nil 388 } 389 390 // Skip any directories 391 if info.IsDir() { 392 return nil 393 } 394 395 return devices.deviceFileWalkFunction(path, info) 396 } 397 398 return filepath.Walk(devices.metadataDir(), scan) 399 } 400 401 func (devices *DeviceSet) unregisterDevice(id int, hash string) error { 402 logrus.Debugf("unregisterDevice(%v, %v)", id, hash) 403 info := &DevInfo{ 404 Hash: hash, 405 DeviceId: id, 406 } 407 408 devices.devicesLock.Lock() 409 delete(devices.Devices, hash) 410 devices.devicesLock.Unlock() 411 412 if err := devices.removeMetadata(info); err != nil { 413 logrus.Debugf("Error removing metadata: %s", err) 414 return err 415 } 416 417 return nil 418 } 419 420 func (devices *DeviceSet) registerDevice(id int, hash string, size uint64, transactionId uint64) (*DevInfo, error) { 421 logrus.Debugf("registerDevice(%v, %v)", id, hash) 422 info := &DevInfo{ 423 Hash: hash, 424 DeviceId: id, 425 Size: size, 426 TransactionId: transactionId, 427 Initialized: false, 428 devices: devices, 429 } 430 431 devices.devicesLock.Lock() 432 devices.Devices[hash] = info 433 devices.devicesLock.Unlock() 434 435 if err := devices.saveMetadata(info); err != nil { 436 // Try to remove unused device 437 devices.devicesLock.Lock() 438 delete(devices.Devices, hash) 439 devices.devicesLock.Unlock() 440 return nil, err 441 } 442 443 return info, nil 444 } 445 446 func (devices *DeviceSet) activateDeviceIfNeeded(info *DevInfo) error { 447 logrus.Debugf("activateDeviceIfNeeded(%v)", info.Hash) 448 449 // Make sure deferred removal on device is canceled, if one was 450 // scheduled. 451 if err := devices.cancelDeferredRemoval(info); err != nil { 452 return fmt.Errorf("Deivce Deferred Removal Cancellation Failed: %s", err) 453 } 454 455 if devinfo, _ := devicemapper.GetInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 { 456 return nil 457 } 458 459 return devicemapper.ActivateDevice(devices.getPoolDevName(), info.Name(), info.DeviceId, info.Size) 460 } 461 462 func (devices *DeviceSet) createFilesystem(info *DevInfo) error { 463 devname := info.DevName() 464 465 args := []string{} 466 for _, arg := range devices.mkfsArgs { 467 args = append(args, arg) 468 } 469 470 args = append(args, devname) 471 472 var err error 473 switch devices.filesystem { 474 case "xfs": 475 err = exec.Command("mkfs.xfs", args...).Run() 476 case "ext4": 477 err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0"}, args...)...).Run() 478 if err != nil { 479 err = exec.Command("mkfs.ext4", append([]string{"-E", "nodiscard,lazy_itable_init=0"}, args...)...).Run() 480 } 481 if err != nil { 482 return err 483 } 484 err = exec.Command("tune2fs", append([]string{"-c", "-1", "-i", "0"}, devname)...).Run() 485 default: 486 err = fmt.Errorf("Unsupported filesystem type %s", devices.filesystem) 487 } 488 if err != nil { 489 return err 490 } 491 492 return nil 493 } 494 495 func (devices *DeviceSet) migrateOldMetaData() error { 496 // Migrate old metadata file 497 jsonData, err := ioutil.ReadFile(devices.oldMetadataFile()) 498 if err != nil && !os.IsNotExist(err) { 499 return err 500 } 501 502 if jsonData != nil { 503 m := MetaData{Devices: make(map[string]*DevInfo)} 504 505 if err := json.Unmarshal(jsonData, &m); err != nil { 506 return err 507 } 508 509 for hash, info := range m.Devices { 510 info.Hash = hash 511 devices.saveMetadata(info) 512 } 513 if err := os.Rename(devices.oldMetadataFile(), devices.oldMetadataFile()+".migrated"); err != nil { 514 return err 515 } 516 517 } 518 519 return nil 520 } 521 522 func (devices *DeviceSet) initMetaData() error { 523 if err := devices.migrateOldMetaData(); err != nil { 524 return err 525 } 526 527 _, transactionId, _, _, _, _, err := devices.poolStatus() 528 if err != nil { 529 return err 530 } 531 532 devices.TransactionId = transactionId 533 534 if err := devices.constructDeviceIdMap(); err != nil { 535 return err 536 } 537 538 if err := devices.processPendingTransaction(); err != nil { 539 return err 540 } 541 return nil 542 } 543 544 func (devices *DeviceSet) incNextDeviceId() { 545 // Ids are 24bit, so wrap around 546 devices.NextDeviceId = (devices.NextDeviceId + 1) & MaxDeviceId 547 } 548 549 func (devices *DeviceSet) getNextFreeDeviceId() (int, error) { 550 devices.incNextDeviceId() 551 for i := 0; i <= MaxDeviceId; i++ { 552 if devices.isDeviceIdFree(devices.NextDeviceId) { 553 devices.markDeviceIdUsed(devices.NextDeviceId) 554 return devices.NextDeviceId, nil 555 } 556 devices.incNextDeviceId() 557 } 558 559 return 0, fmt.Errorf("Unable to find a free device Id") 560 } 561 562 func (devices *DeviceSet) createRegisterDevice(hash string) (*DevInfo, error) { 563 deviceId, err := devices.getNextFreeDeviceId() 564 if err != nil { 565 return nil, err 566 } 567 568 if err := devices.openTransaction(hash, deviceId); err != nil { 569 logrus.Debugf("Error opening transaction hash = %s deviceId = %d", hash, deviceId) 570 devices.markDeviceIdFree(deviceId) 571 return nil, err 572 } 573 574 for { 575 if err := devicemapper.CreateDevice(devices.getPoolDevName(), deviceId); err != nil { 576 if devicemapper.DeviceIdExists(err) { 577 // Device Id already exists. This should not 578 // happen. Now we have a mechianism to find 579 // a free device Id. So something is not right. 580 // Give a warning and continue. 581 logrus.Errorf("Device Id %d exists in pool but it is supposed to be unused", deviceId) 582 deviceId, err = devices.getNextFreeDeviceId() 583 if err != nil { 584 return nil, err 585 } 586 // Save new device id into transaction 587 devices.refreshTransaction(deviceId) 588 continue 589 } 590 logrus.Debugf("Error creating device: %s", err) 591 devices.markDeviceIdFree(deviceId) 592 return nil, err 593 } 594 break 595 } 596 597 logrus.Debugf("Registering device (id %v) with FS size %v", deviceId, devices.baseFsSize) 598 info, err := devices.registerDevice(deviceId, hash, devices.baseFsSize, devices.OpenTransactionId) 599 if err != nil { 600 _ = devicemapper.DeleteDevice(devices.getPoolDevName(), deviceId) 601 devices.markDeviceIdFree(deviceId) 602 return nil, err 603 } 604 605 if err := devices.closeTransaction(); err != nil { 606 devices.unregisterDevice(deviceId, hash) 607 devicemapper.DeleteDevice(devices.getPoolDevName(), deviceId) 608 devices.markDeviceIdFree(deviceId) 609 return nil, err 610 } 611 return info, nil 612 } 613 614 func (devices *DeviceSet) createRegisterSnapDevice(hash string, baseInfo *DevInfo) error { 615 deviceId, err := devices.getNextFreeDeviceId() 616 if err != nil { 617 return err 618 } 619 620 if err := devices.openTransaction(hash, deviceId); err != nil { 621 logrus.Debugf("Error opening transaction hash = %s deviceId = %d", hash, deviceId) 622 devices.markDeviceIdFree(deviceId) 623 return err 624 } 625 626 for { 627 if err := devicemapper.CreateSnapDevice(devices.getPoolDevName(), deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil { 628 if devicemapper.DeviceIdExists(err) { 629 // Device Id already exists. This should not 630 // happen. Now we have a mechianism to find 631 // a free device Id. So something is not right. 632 // Give a warning and continue. 633 logrus.Errorf("Device Id %d exists in pool but it is supposed to be unused", deviceId) 634 deviceId, err = devices.getNextFreeDeviceId() 635 if err != nil { 636 return err 637 } 638 // Save new device id into transaction 639 devices.refreshTransaction(deviceId) 640 continue 641 } 642 logrus.Debugf("Error creating snap device: %s", err) 643 devices.markDeviceIdFree(deviceId) 644 return err 645 } 646 break 647 } 648 649 if _, err := devices.registerDevice(deviceId, hash, baseInfo.Size, devices.OpenTransactionId); err != nil { 650 devicemapper.DeleteDevice(devices.getPoolDevName(), deviceId) 651 devices.markDeviceIdFree(deviceId) 652 logrus.Debugf("Error registering device: %s", err) 653 return err 654 } 655 656 if err := devices.closeTransaction(); err != nil { 657 devices.unregisterDevice(deviceId, hash) 658 devicemapper.DeleteDevice(devices.getPoolDevName(), deviceId) 659 devices.markDeviceIdFree(deviceId) 660 return err 661 } 662 return nil 663 } 664 665 func (devices *DeviceSet) loadMetadata(hash string) *DevInfo { 666 info := &DevInfo{Hash: hash, devices: devices} 667 668 jsonData, err := ioutil.ReadFile(devices.metadataFile(info)) 669 if err != nil { 670 return nil 671 } 672 673 if err := json.Unmarshal(jsonData, &info); err != nil { 674 return nil 675 } 676 677 return info 678 } 679 680 func getDeviceUUID(device string) (string, error) { 681 out, err := exec.Command("blkid", "-s", "UUID", "-o", "value", device).Output() 682 if err != nil { 683 logrus.Debugf("Failed to find uuid for device %s:%v", device, err) 684 return "", err 685 } 686 687 uuid := strings.TrimSuffix(string(out), "\n") 688 uuid = strings.TrimSpace(uuid) 689 logrus.Debugf("UUID for device: %s is:%s", device, uuid) 690 return uuid, nil 691 } 692 693 func (devices *DeviceSet) verifyBaseDeviceUUID(baseInfo *DevInfo) error { 694 devices.Lock() 695 defer devices.Unlock() 696 697 if err := devices.activateDeviceIfNeeded(baseInfo); err != nil { 698 return err 699 } 700 701 defer devices.deactivateDevice(baseInfo) 702 703 uuid, err := getDeviceUUID(baseInfo.DevName()) 704 if err != nil { 705 return err 706 } 707 708 if devices.BaseDeviceUUID != uuid { 709 return fmt.Errorf("Current Base Device UUID:%s does not match with stored UUID:%s", uuid, devices.BaseDeviceUUID) 710 } 711 712 return nil 713 } 714 715 func (devices *DeviceSet) saveBaseDeviceUUID(baseInfo *DevInfo) error { 716 devices.Lock() 717 defer devices.Unlock() 718 719 if err := devices.activateDeviceIfNeeded(baseInfo); err != nil { 720 return err 721 } 722 723 defer devices.deactivateDevice(baseInfo) 724 725 uuid, err := getDeviceUUID(baseInfo.DevName()) 726 if err != nil { 727 return err 728 } 729 730 devices.BaseDeviceUUID = uuid 731 devices.saveDeviceSetMetaData() 732 return nil 733 } 734 735 func (devices *DeviceSet) setupBaseImage() error { 736 oldInfo, _ := devices.lookupDevice("") 737 if oldInfo != nil && oldInfo.Initialized { 738 // If BaseDeviceUUID is nil (upgrade case), save it and 739 // return success. 740 if devices.BaseDeviceUUID == "" { 741 if err := devices.saveBaseDeviceUUID(oldInfo); err != nil { 742 return fmt.Errorf("Could not query and save base device UUID:%v", err) 743 } 744 return nil 745 } 746 747 if err := devices.verifyBaseDeviceUUID(oldInfo); err != nil { 748 return fmt.Errorf("Base Device UUID verification failed. Possibly using a different thin pool then last invocation:%v", err) 749 } 750 return nil 751 } 752 753 if oldInfo != nil && !oldInfo.Initialized { 754 logrus.Debugf("Removing uninitialized base image") 755 if err := devices.DeleteDevice(""); err != nil { 756 return err 757 } 758 } 759 760 if devices.thinPoolDevice != "" && oldInfo == nil { 761 _, transactionId, dataUsed, _, _, _, err := devices.poolStatus() 762 if err != nil { 763 return err 764 } 765 if dataUsed != 0 { 766 return fmt.Errorf("Unable to take ownership of thin-pool (%s) that already has used data blocks", 767 devices.thinPoolDevice) 768 } 769 if transactionId != 0 { 770 return fmt.Errorf("Unable to take ownership of thin-pool (%s) with non-zero transaction Id", 771 devices.thinPoolDevice) 772 } 773 } 774 775 logrus.Debugf("Initializing base device-mapper thin volume") 776 777 // Create initial device 778 info, err := devices.createRegisterDevice("") 779 if err != nil { 780 return err 781 } 782 783 logrus.Debugf("Creating filesystem on base device-mapper thin volume") 784 785 if err := devices.activateDeviceIfNeeded(info); err != nil { 786 return err 787 } 788 789 if err := devices.createFilesystem(info); err != nil { 790 return err 791 } 792 793 info.Initialized = true 794 if err := devices.saveMetadata(info); err != nil { 795 info.Initialized = false 796 return err 797 } 798 799 if err := devices.saveBaseDeviceUUID(info); err != nil { 800 return fmt.Errorf("Could not query and save base device UUID:%v", err) 801 } 802 803 return nil 804 } 805 806 func setCloseOnExec(name string) { 807 if fileInfos, _ := ioutil.ReadDir("/proc/self/fd"); fileInfos != nil { 808 for _, i := range fileInfos { 809 link, _ := os.Readlink(filepath.Join("/proc/self/fd", i.Name())) 810 if link == name { 811 fd, err := strconv.Atoi(i.Name()) 812 if err == nil { 813 syscall.CloseOnExec(fd) 814 } 815 } 816 } 817 } 818 } 819 820 func (devices *DeviceSet) DMLog(level int, file string, line int, dmError int, message string) { 821 // By default libdm sends us all the messages including debug ones. 822 // We need to filter out messages here and figure out which one 823 // should be printed. 824 if level > DMLogLevel { 825 return 826 } 827 828 // FIXME(vbatts) push this back into ./pkg/devicemapper/ 829 if level <= devicemapper.LogLevelErr { 830 logrus.Errorf("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message) 831 } else if level <= devicemapper.LogLevelInfo { 832 logrus.Infof("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message) 833 } else { 834 // FIXME(vbatts) push this back into ./pkg/devicemapper/ 835 logrus.Debugf("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message) 836 } 837 } 838 839 func major(device uint64) uint64 { 840 return (device >> 8) & 0xfff 841 } 842 843 func minor(device uint64) uint64 { 844 return (device & 0xff) | ((device >> 12) & 0xfff00) 845 } 846 847 func (devices *DeviceSet) ResizePool(size int64) error { 848 dirname := devices.loopbackDir() 849 datafilename := path.Join(dirname, "data") 850 if len(devices.dataDevice) > 0 { 851 datafilename = devices.dataDevice 852 } 853 metadatafilename := path.Join(dirname, "metadata") 854 if len(devices.metadataDevice) > 0 { 855 metadatafilename = devices.metadataDevice 856 } 857 858 datafile, err := os.OpenFile(datafilename, os.O_RDWR, 0) 859 if datafile == nil { 860 return err 861 } 862 defer datafile.Close() 863 864 fi, err := datafile.Stat() 865 if fi == nil { 866 return err 867 } 868 869 if fi.Size() > size { 870 return fmt.Errorf("Can't shrink file") 871 } 872 873 dataloopback := devicemapper.FindLoopDeviceFor(datafile) 874 if dataloopback == nil { 875 return fmt.Errorf("Unable to find loopback mount for: %s", datafilename) 876 } 877 defer dataloopback.Close() 878 879 metadatafile, err := os.OpenFile(metadatafilename, os.O_RDWR, 0) 880 if metadatafile == nil { 881 return err 882 } 883 defer metadatafile.Close() 884 885 metadataloopback := devicemapper.FindLoopDeviceFor(metadatafile) 886 if metadataloopback == nil { 887 return fmt.Errorf("Unable to find loopback mount for: %s", metadatafilename) 888 } 889 defer metadataloopback.Close() 890 891 // Grow loopback file 892 if err := datafile.Truncate(size); err != nil { 893 return fmt.Errorf("Unable to grow loopback file: %s", err) 894 } 895 896 // Reload size for loopback device 897 if err := devicemapper.LoopbackSetCapacity(dataloopback); err != nil { 898 return fmt.Errorf("Unable to update loopback capacity: %s", err) 899 } 900 901 // Suspend the pool 902 if err := devicemapper.SuspendDevice(devices.getPoolName()); err != nil { 903 return fmt.Errorf("Unable to suspend pool: %s", err) 904 } 905 906 // Reload with the new block sizes 907 if err := devicemapper.ReloadPool(devices.getPoolName(), dataloopback, metadataloopback, devices.thinpBlockSize); err != nil { 908 return fmt.Errorf("Unable to reload pool: %s", err) 909 } 910 911 // Resume the pool 912 if err := devicemapper.ResumeDevice(devices.getPoolName()); err != nil { 913 return fmt.Errorf("Unable to resume pool: %s", err) 914 } 915 916 return nil 917 } 918 919 func (devices *DeviceSet) loadTransactionMetaData() error { 920 jsonData, err := ioutil.ReadFile(devices.transactionMetaFile()) 921 if err != nil { 922 // There is no active transaction. This will be the case 923 // during upgrade. 924 if os.IsNotExist(err) { 925 devices.OpenTransactionId = devices.TransactionId 926 return nil 927 } 928 return err 929 } 930 931 json.Unmarshal(jsonData, &devices.Transaction) 932 return nil 933 } 934 935 func (devices *DeviceSet) saveTransactionMetaData() error { 936 jsonData, err := json.Marshal(&devices.Transaction) 937 if err != nil { 938 return fmt.Errorf("Error encoding metadata to json: %s", err) 939 } 940 941 return devices.writeMetaFile(jsonData, devices.transactionMetaFile()) 942 } 943 944 func (devices *DeviceSet) removeTransactionMetaData() error { 945 if err := os.RemoveAll(devices.transactionMetaFile()); err != nil { 946 return err 947 } 948 return nil 949 } 950 951 func (devices *DeviceSet) rollbackTransaction() error { 952 logrus.Debugf("Rolling back open transaction: TransactionId=%d hash=%s device_id=%d", devices.OpenTransactionId, devices.DeviceIdHash, devices.DeviceId) 953 954 // A device id might have already been deleted before transaction 955 // closed. In that case this call will fail. Just leave a message 956 // in case of failure. 957 if err := devicemapper.DeleteDevice(devices.getPoolDevName(), devices.DeviceId); err != nil { 958 logrus.Errorf("Unable to delete device: %s", err) 959 } 960 961 dinfo := &DevInfo{Hash: devices.DeviceIdHash} 962 if err := devices.removeMetadata(dinfo); err != nil { 963 logrus.Errorf("Unable to remove metadata: %s", err) 964 } else { 965 devices.markDeviceIdFree(devices.DeviceId) 966 } 967 968 if err := devices.removeTransactionMetaData(); err != nil { 969 logrus.Errorf("Unable to remove transaction meta file %s: %s", devices.transactionMetaFile(), err) 970 } 971 972 return nil 973 } 974 975 func (devices *DeviceSet) processPendingTransaction() error { 976 if err := devices.loadTransactionMetaData(); err != nil { 977 return err 978 } 979 980 // If there was open transaction but pool transaction Id is same 981 // as open transaction Id, nothing to roll back. 982 if devices.TransactionId == devices.OpenTransactionId { 983 return nil 984 } 985 986 // If open transaction Id is less than pool transaction Id, something 987 // is wrong. Bail out. 988 if devices.OpenTransactionId < devices.TransactionId { 989 logrus.Errorf("Open Transaction id %d is less than pool transaction id %d", devices.OpenTransactionId, devices.TransactionId) 990 return nil 991 } 992 993 // Pool transaction Id is not same as open transaction. There is 994 // a transaction which was not completed. 995 if err := devices.rollbackTransaction(); err != nil { 996 return fmt.Errorf("Rolling back open transaction failed: %s", err) 997 } 998 999 devices.OpenTransactionId = devices.TransactionId 1000 return nil 1001 } 1002 1003 func (devices *DeviceSet) loadDeviceSetMetaData() error { 1004 jsonData, err := ioutil.ReadFile(devices.deviceSetMetaFile()) 1005 if err != nil { 1006 // For backward compatibility return success if file does 1007 // not exist. 1008 if os.IsNotExist(err) { 1009 return nil 1010 } 1011 return err 1012 } 1013 1014 return json.Unmarshal(jsonData, devices) 1015 } 1016 1017 func (devices *DeviceSet) saveDeviceSetMetaData() error { 1018 jsonData, err := json.Marshal(devices) 1019 if err != nil { 1020 return fmt.Errorf("Error encoding metadata to json: %s", err) 1021 } 1022 1023 return devices.writeMetaFile(jsonData, devices.deviceSetMetaFile()) 1024 } 1025 1026 func (devices *DeviceSet) openTransaction(hash string, DeviceId int) error { 1027 devices.allocateTransactionId() 1028 devices.DeviceIdHash = hash 1029 devices.DeviceId = DeviceId 1030 if err := devices.saveTransactionMetaData(); err != nil { 1031 return fmt.Errorf("Error saving transaction metadata: %s", err) 1032 } 1033 return nil 1034 } 1035 1036 func (devices *DeviceSet) refreshTransaction(DeviceId int) error { 1037 devices.DeviceId = DeviceId 1038 if err := devices.saveTransactionMetaData(); err != nil { 1039 return fmt.Errorf("Error saving transaction metadata: %s", err) 1040 } 1041 return nil 1042 } 1043 1044 func (devices *DeviceSet) closeTransaction() error { 1045 if err := devices.updatePoolTransactionId(); err != nil { 1046 logrus.Debugf("Failed to close Transaction") 1047 return err 1048 } 1049 return nil 1050 } 1051 1052 func determineDriverCapabilities(version string) error { 1053 /* 1054 * Driver version 4.27.0 and greater support deferred activation 1055 * feature. 1056 */ 1057 1058 logrus.Debugf("devicemapper: driver version is %s", version) 1059 1060 versionSplit := strings.Split(version, ".") 1061 major, err := strconv.Atoi(versionSplit[0]) 1062 if err != nil { 1063 return graphdriver.ErrNotSupported 1064 } 1065 1066 if major > 4 { 1067 DriverDeferredRemovalSupport = true 1068 return nil 1069 } 1070 1071 if major < 4 { 1072 return nil 1073 } 1074 1075 minor, err := strconv.Atoi(versionSplit[1]) 1076 if err != nil { 1077 return graphdriver.ErrNotSupported 1078 } 1079 1080 /* 1081 * If major is 4 and minor is 27, then there is no need to 1082 * check for patch level as it can not be less than 0. 1083 */ 1084 if minor >= 27 { 1085 DriverDeferredRemovalSupport = true 1086 return nil 1087 } 1088 1089 return nil 1090 } 1091 1092 // Determine the major and minor number of loopback device 1093 func getDeviceMajorMinor(file *os.File) (uint64, uint64, error) { 1094 stat, err := file.Stat() 1095 if err != nil { 1096 return 0, 0, err 1097 } 1098 1099 dev := stat.Sys().(*syscall.Stat_t).Rdev 1100 majorNum := major(dev) 1101 minorNum := minor(dev) 1102 1103 logrus.Debugf("[devmapper]: Major:Minor for device: %s is:%v:%v", file.Name(), majorNum, minorNum) 1104 return majorNum, minorNum, nil 1105 } 1106 1107 // Given a file which is backing file of a loop back device, find the 1108 // loopback device name and its major/minor number. 1109 func getLoopFileDeviceMajMin(filename string) (string, uint64, uint64, error) { 1110 file, err := os.Open(filename) 1111 if err != nil { 1112 logrus.Debugf("[devmapper]: Failed to open file %s", filename) 1113 return "", 0, 0, err 1114 } 1115 1116 defer file.Close() 1117 loopbackDevice := devicemapper.FindLoopDeviceFor(file) 1118 if loopbackDevice == nil { 1119 return "", 0, 0, fmt.Errorf("[devmapper]: Unable to find loopback mount for: %s", filename) 1120 } 1121 defer loopbackDevice.Close() 1122 1123 Major, Minor, err := getDeviceMajorMinor(loopbackDevice) 1124 if err != nil { 1125 return "", 0, 0, err 1126 } 1127 return loopbackDevice.Name(), Major, Minor, nil 1128 } 1129 1130 // Get the major/minor numbers of thin pool data and metadata devices 1131 func (devices *DeviceSet) getThinPoolDataMetaMajMin() (uint64, uint64, uint64, uint64, error) { 1132 var params, poolDataMajMin, poolMetadataMajMin string 1133 1134 _, _, _, params, err := devicemapper.GetTable(devices.getPoolName()) 1135 if err != nil { 1136 return 0, 0, 0, 0, err 1137 } 1138 1139 if _, err = fmt.Sscanf(params, "%s %s", &poolMetadataMajMin, &poolDataMajMin); err != nil { 1140 return 0, 0, 0, 0, err 1141 } 1142 1143 logrus.Debugf("[devmapper]: poolDataMajMin=%s poolMetaMajMin=%s\n", poolDataMajMin, poolMetadataMajMin) 1144 1145 poolDataMajMinorSplit := strings.Split(poolDataMajMin, ":") 1146 poolDataMajor, err := strconv.ParseUint(poolDataMajMinorSplit[0], 10, 32) 1147 if err != nil { 1148 return 0, 0, 0, 0, err 1149 } 1150 1151 poolDataMinor, err := strconv.ParseUint(poolDataMajMinorSplit[1], 10, 32) 1152 if err != nil { 1153 return 0, 0, 0, 0, err 1154 } 1155 1156 poolMetadataMajMinorSplit := strings.Split(poolMetadataMajMin, ":") 1157 poolMetadataMajor, err := strconv.ParseUint(poolMetadataMajMinorSplit[0], 10, 32) 1158 if err != nil { 1159 return 0, 0, 0, 0, err 1160 } 1161 1162 poolMetadataMinor, err := strconv.ParseUint(poolMetadataMajMinorSplit[1], 10, 32) 1163 if err != nil { 1164 return 0, 0, 0, 0, err 1165 } 1166 1167 return poolDataMajor, poolDataMinor, poolMetadataMajor, poolMetadataMinor, nil 1168 } 1169 1170 func (devices *DeviceSet) loadThinPoolLoopBackInfo() error { 1171 poolDataMajor, poolDataMinor, poolMetadataMajor, poolMetadataMinor, err := devices.getThinPoolDataMetaMajMin() 1172 if err != nil { 1173 return err 1174 } 1175 1176 dirname := devices.loopbackDir() 1177 1178 // data device has not been passed in. So there should be a data file 1179 // which is being mounted as loop device. 1180 if devices.dataDevice == "" { 1181 datafilename := path.Join(dirname, "data") 1182 dataLoopDevice, dataMajor, dataMinor, err := getLoopFileDeviceMajMin(datafilename) 1183 if err != nil { 1184 return err 1185 } 1186 1187 // Compare the two 1188 if poolDataMajor == dataMajor && poolDataMinor == dataMinor { 1189 devices.dataDevice = dataLoopDevice 1190 devices.dataLoopFile = datafilename 1191 } 1192 1193 } 1194 1195 // metadata device has not been passed in. So there should be a 1196 // metadata file which is being mounted as loop device. 1197 if devices.metadataDevice == "" { 1198 metadatafilename := path.Join(dirname, "metadata") 1199 metadataLoopDevice, metadataMajor, metadataMinor, err := getLoopFileDeviceMajMin(metadatafilename) 1200 if err != nil { 1201 return err 1202 } 1203 if poolMetadataMajor == metadataMajor && poolMetadataMinor == metadataMinor { 1204 devices.metadataDevice = metadataLoopDevice 1205 devices.metadataLoopFile = metadatafilename 1206 } 1207 } 1208 1209 return nil 1210 } 1211 1212 func (devices *DeviceSet) initDevmapper(doInit bool) error { 1213 // give ourselves to libdm as a log handler 1214 devicemapper.LogInit(devices) 1215 1216 version, err := devicemapper.GetDriverVersion() 1217 if err != nil { 1218 // Can't even get driver version, assume not supported 1219 return graphdriver.ErrNotSupported 1220 } 1221 1222 if err := determineDriverCapabilities(version); err != nil { 1223 return graphdriver.ErrNotSupported 1224 } 1225 1226 // If user asked for deferred removal and both library and driver 1227 // supports deferred removal use it. 1228 if EnableDeferredRemoval && DriverDeferredRemovalSupport && devicemapper.LibraryDeferredRemovalSupport == true { 1229 logrus.Debugf("devmapper: Deferred removal support enabled.") 1230 devices.deferredRemove = true 1231 } 1232 1233 // https://github.com/docker/docker/issues/4036 1234 if supported := devicemapper.UdevSetSyncSupport(true); !supported { 1235 logrus.Warn("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/cli/#daemon-storage-driver-option") 1236 } 1237 1238 if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) { 1239 return err 1240 } 1241 1242 // Set the device prefix from the device id and inode of the docker root dir 1243 1244 st, err := os.Stat(devices.root) 1245 if err != nil { 1246 return fmt.Errorf("Error looking up dir %s: %s", devices.root, err) 1247 } 1248 sysSt := st.Sys().(*syscall.Stat_t) 1249 // "reg-" stands for "regular file". 1250 // In the future we might use "dev-" for "device file", etc. 1251 // docker-maj,min[-inode] stands for: 1252 // - Managed by docker 1253 // - The target of this device is at major <maj> and minor <min> 1254 // - If <inode> is defined, use that file inside the device as a loopback image. Otherwise use the device itself. 1255 devices.devicePrefix = fmt.Sprintf("docker-%d:%d-%d", major(sysSt.Dev), minor(sysSt.Dev), sysSt.Ino) 1256 logrus.Debugf("Generated prefix: %s", devices.devicePrefix) 1257 1258 // Check for the existence of the thin-pool device 1259 logrus.Debugf("Checking for existence of the pool '%s'", devices.getPoolName()) 1260 info, err := devicemapper.GetInfo(devices.getPoolName()) 1261 if info == nil { 1262 logrus.Debugf("Error device devicemapper.GetInfo: %s", err) 1263 return err 1264 } 1265 1266 // It seems libdevmapper opens this without O_CLOEXEC, and go exec will not close files 1267 // that are not Close-on-exec, and lxc-start will die if it inherits any unexpected files, 1268 // so we add this badhack to make sure it closes itself 1269 setCloseOnExec("/dev/mapper/control") 1270 1271 // Make sure the sparse images exist in <root>/devicemapper/data and 1272 // <root>/devicemapper/metadata 1273 1274 createdLoopback := false 1275 1276 // If the pool doesn't exist, create it 1277 if info.Exists == 0 && devices.thinPoolDevice == "" { 1278 logrus.Debugf("Pool doesn't exist. Creating it.") 1279 1280 var ( 1281 dataFile *os.File 1282 metadataFile *os.File 1283 ) 1284 1285 if devices.dataDevice == "" { 1286 // Make sure the sparse images exist in <root>/devicemapper/data 1287 1288 hasData := devices.hasImage("data") 1289 1290 if !doInit && !hasData { 1291 return errors.New("Loopback data file not found") 1292 } 1293 1294 if !hasData { 1295 createdLoopback = true 1296 } 1297 1298 data, err := devices.ensureImage("data", devices.dataLoopbackSize) 1299 if err != nil { 1300 logrus.Debugf("Error device ensureImage (data): %s", err) 1301 return err 1302 } 1303 1304 dataFile, err = devicemapper.AttachLoopDevice(data) 1305 if err != nil { 1306 return err 1307 } 1308 devices.dataLoopFile = data 1309 devices.dataDevice = dataFile.Name() 1310 } else { 1311 dataFile, err = os.OpenFile(devices.dataDevice, os.O_RDWR, 0600) 1312 if err != nil { 1313 return err 1314 } 1315 } 1316 defer dataFile.Close() 1317 1318 if devices.metadataDevice == "" { 1319 // Make sure the sparse images exist in <root>/devicemapper/metadata 1320 1321 hasMetadata := devices.hasImage("metadata") 1322 1323 if !doInit && !hasMetadata { 1324 return errors.New("Loopback metadata file not found") 1325 } 1326 1327 if !hasMetadata { 1328 createdLoopback = true 1329 } 1330 1331 metadata, err := devices.ensureImage("metadata", devices.metaDataLoopbackSize) 1332 if err != nil { 1333 logrus.Debugf("Error device ensureImage (metadata): %s", err) 1334 return err 1335 } 1336 1337 metadataFile, err = devicemapper.AttachLoopDevice(metadata) 1338 if err != nil { 1339 return err 1340 } 1341 devices.metadataLoopFile = metadata 1342 devices.metadataDevice = metadataFile.Name() 1343 } else { 1344 metadataFile, err = os.OpenFile(devices.metadataDevice, os.O_RDWR, 0600) 1345 if err != nil { 1346 return err 1347 } 1348 } 1349 defer metadataFile.Close() 1350 1351 if err := devicemapper.CreatePool(devices.getPoolName(), dataFile, metadataFile, devices.thinpBlockSize); err != nil { 1352 return err 1353 } 1354 } 1355 1356 // Pool already exists and caller did not pass us a pool. That means 1357 // we probably created pool earlier and could not remove it as some 1358 // containers were still using it. Detect some of the properties of 1359 // pool, like is it using loop devices. 1360 if info.Exists != 0 && devices.thinPoolDevice == "" { 1361 if err := devices.loadThinPoolLoopBackInfo(); err != nil { 1362 logrus.Debugf("Failed to load thin pool loopback device information:%v", err) 1363 return err 1364 } 1365 } 1366 1367 // If we didn't just create the data or metadata image, we need to 1368 // load the transaction id and migrate old metadata 1369 if !createdLoopback { 1370 if err := devices.initMetaData(); err != nil { 1371 return err 1372 } 1373 } 1374 1375 // Right now this loads only NextDeviceId. If there is more metadata 1376 // down the line, we might have to move it earlier. 1377 if err := devices.loadDeviceSetMetaData(); err != nil { 1378 return err 1379 } 1380 1381 // Setup the base image 1382 if doInit { 1383 if err := devices.setupBaseImage(); err != nil { 1384 logrus.Debugf("Error device setupBaseImage: %s", err) 1385 return err 1386 } 1387 } 1388 1389 return nil 1390 } 1391 1392 func (devices *DeviceSet) AddDevice(hash, baseHash string) error { 1393 logrus.Debugf("[deviceset] AddDevice(hash=%s basehash=%s)", hash, baseHash) 1394 defer logrus.Debugf("[deviceset] AddDevice(hash=%s basehash=%s) END", hash, baseHash) 1395 1396 baseInfo, err := devices.lookupDevice(baseHash) 1397 if err != nil { 1398 return err 1399 } 1400 1401 baseInfo.lock.Lock() 1402 defer baseInfo.lock.Unlock() 1403 1404 devices.Lock() 1405 defer devices.Unlock() 1406 1407 if info, _ := devices.lookupDevice(hash); info != nil { 1408 return fmt.Errorf("device %s already exists", hash) 1409 } 1410 1411 if err := devices.createRegisterSnapDevice(hash, baseInfo); err != nil { 1412 return err 1413 } 1414 1415 return nil 1416 } 1417 1418 func (devices *DeviceSet) deleteDevice(info *DevInfo) error { 1419 if devices.doBlkDiscard { 1420 // This is a workaround for the kernel not discarding block so 1421 // on the thin pool when we remove a thinp device, so we do it 1422 // manually 1423 if err := devices.activateDeviceIfNeeded(info); err == nil { 1424 if err := devicemapper.BlockDeviceDiscard(info.DevName()); err != nil { 1425 logrus.Debugf("Error discarding block on device: %s (ignoring)", err) 1426 } 1427 } 1428 } 1429 1430 devinfo, _ := devicemapper.GetInfo(info.Name()) 1431 if devinfo != nil && devinfo.Exists != 0 { 1432 if err := devices.removeDevice(info.Name()); err != nil { 1433 logrus.Debugf("Error removing device: %s", err) 1434 return err 1435 } 1436 } 1437 1438 if err := devices.openTransaction(info.Hash, info.DeviceId); err != nil { 1439 logrus.Debugf("Error opening transaction hash = %s deviceId = %d", "", info.DeviceId) 1440 return err 1441 } 1442 1443 if err := devicemapper.DeleteDevice(devices.getPoolDevName(), info.DeviceId); err != nil { 1444 logrus.Debugf("Error deleting device: %s", err) 1445 return err 1446 } 1447 1448 if err := devices.unregisterDevice(info.DeviceId, info.Hash); err != nil { 1449 return err 1450 } 1451 1452 if err := devices.closeTransaction(); err != nil { 1453 return err 1454 } 1455 1456 devices.markDeviceIdFree(info.DeviceId) 1457 1458 return nil 1459 } 1460 1461 func (devices *DeviceSet) DeleteDevice(hash string) error { 1462 info, err := devices.lookupDevice(hash) 1463 if err != nil { 1464 return err 1465 } 1466 1467 info.lock.Lock() 1468 defer info.lock.Unlock() 1469 1470 devices.Lock() 1471 defer devices.Unlock() 1472 1473 return devices.deleteDevice(info) 1474 } 1475 1476 func (devices *DeviceSet) deactivatePool() error { 1477 logrus.Debugf("[devmapper] deactivatePool()") 1478 defer logrus.Debugf("[devmapper] deactivatePool END") 1479 devname := devices.getPoolDevName() 1480 1481 devinfo, err := devicemapper.GetInfo(devname) 1482 if err != nil { 1483 return err 1484 } 1485 if d, err := devicemapper.GetDeps(devname); err == nil { 1486 // Access to more Debug output 1487 logrus.Debugf("[devmapper] devicemapper.GetDeps() %s: %#v", devname, d) 1488 } 1489 if devinfo.Exists != 0 { 1490 return devicemapper.RemoveDevice(devname) 1491 } 1492 1493 return nil 1494 } 1495 1496 func (devices *DeviceSet) deactivateDevice(info *DevInfo) error { 1497 logrus.Debugf("[devmapper] deactivateDevice(%s)", info.Hash) 1498 defer logrus.Debugf("[devmapper] deactivateDevice END(%s)", info.Hash) 1499 1500 devinfo, err := devicemapper.GetInfo(info.Name()) 1501 if err != nil { 1502 return err 1503 } 1504 1505 if devinfo.Exists == 0 { 1506 return nil 1507 } 1508 1509 if devices.deferredRemove { 1510 if err := devicemapper.RemoveDeviceDeferred(info.Name()); err != nil { 1511 return err 1512 } 1513 } else { 1514 if err := devices.removeDevice(info.Name()); err != nil { 1515 return err 1516 } 1517 } 1518 return nil 1519 } 1520 1521 // Issues the underlying dm remove operation. 1522 func (devices *DeviceSet) removeDevice(devname string) error { 1523 var err error 1524 1525 logrus.Debugf("[devmapper] removeDevice START(%s)", devname) 1526 defer logrus.Debugf("[devmapper] removeDevice END(%s)", devname) 1527 1528 for i := 0; i < 200; i++ { 1529 err = devicemapper.RemoveDevice(devname) 1530 if err == nil { 1531 break 1532 } 1533 if err != devicemapper.ErrBusy { 1534 return err 1535 } 1536 1537 // If we see EBUSY it may be a transient error, 1538 // sleep a bit a retry a few times. 1539 devices.Unlock() 1540 time.Sleep(100 * time.Millisecond) 1541 devices.Lock() 1542 } 1543 1544 return err 1545 } 1546 1547 func (devices *DeviceSet) cancelDeferredRemoval(info *DevInfo) error { 1548 if !devices.deferredRemove { 1549 return nil 1550 } 1551 1552 logrus.Debugf("[devmapper] cancelDeferredRemoval START(%s)", info.Name()) 1553 defer logrus.Debugf("[devmapper] cancelDeferredRemoval END(%s)", info.Name()) 1554 1555 devinfo, err := devicemapper.GetInfoWithDeferred(info.Name()) 1556 1557 if devinfo != nil && devinfo.DeferredRemove == 0 { 1558 return nil 1559 } 1560 1561 // Cancel deferred remove 1562 for i := 0; i < 100; i++ { 1563 err = devicemapper.CancelDeferredRemove(info.Name()) 1564 if err == nil { 1565 break 1566 } 1567 1568 if err == devicemapper.ErrEnxio { 1569 // Device is probably already gone. Return success. 1570 return nil 1571 } 1572 1573 if err != devicemapper.ErrBusy { 1574 return err 1575 } 1576 1577 // If we see EBUSY it may be a transient error, 1578 // sleep a bit a retry a few times. 1579 devices.Unlock() 1580 time.Sleep(100 * time.Millisecond) 1581 devices.Lock() 1582 } 1583 return err 1584 } 1585 1586 func (devices *DeviceSet) Shutdown() error { 1587 logrus.Debugf("[deviceset %s] Shutdown()", devices.devicePrefix) 1588 logrus.Debugf("[devmapper] Shutting down DeviceSet: %s", devices.root) 1589 defer logrus.Debugf("[deviceset %s] Shutdown() END", devices.devicePrefix) 1590 1591 var devs []*DevInfo 1592 1593 devices.devicesLock.Lock() 1594 for _, info := range devices.Devices { 1595 devs = append(devs, info) 1596 } 1597 devices.devicesLock.Unlock() 1598 1599 for _, info := range devs { 1600 info.lock.Lock() 1601 if info.mountCount > 0 { 1602 // We use MNT_DETACH here in case it is still busy in some running 1603 // container. This means it'll go away from the global scope directly, 1604 // and the device will be released when that container dies. 1605 if err := syscall.Unmount(info.mountPath, syscall.MNT_DETACH); err != nil { 1606 logrus.Debugf("Shutdown unmounting %s, error: %s", info.mountPath, err) 1607 } 1608 1609 devices.Lock() 1610 if err := devices.deactivateDevice(info); err != nil { 1611 logrus.Debugf("Shutdown deactivate %s , error: %s", info.Hash, err) 1612 } 1613 devices.Unlock() 1614 } 1615 info.lock.Unlock() 1616 } 1617 1618 info, _ := devices.lookupDevice("") 1619 if info != nil { 1620 info.lock.Lock() 1621 devices.Lock() 1622 if err := devices.deactivateDevice(info); err != nil { 1623 logrus.Debugf("Shutdown deactivate base , error: %s", err) 1624 } 1625 devices.Unlock() 1626 info.lock.Unlock() 1627 } 1628 1629 devices.Lock() 1630 if devices.thinPoolDevice == "" { 1631 if err := devices.deactivatePool(); err != nil { 1632 logrus.Debugf("Shutdown deactivate pool , error: %s", err) 1633 } 1634 } 1635 1636 devices.saveDeviceSetMetaData() 1637 devices.Unlock() 1638 1639 return nil 1640 } 1641 1642 func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { 1643 info, err := devices.lookupDevice(hash) 1644 if err != nil { 1645 return err 1646 } 1647 1648 info.lock.Lock() 1649 defer info.lock.Unlock() 1650 1651 devices.Lock() 1652 defer devices.Unlock() 1653 1654 if info.mountCount > 0 { 1655 if path != info.mountPath { 1656 return fmt.Errorf("Trying to mount devmapper device in multiple places (%s, %s)", info.mountPath, path) 1657 } 1658 1659 info.mountCount++ 1660 return nil 1661 } 1662 1663 if err := devices.activateDeviceIfNeeded(info); err != nil { 1664 return fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err) 1665 } 1666 1667 var flags uintptr = syscall.MS_MGC_VAL 1668 1669 fstype, err := ProbeFsType(info.DevName()) 1670 if err != nil { 1671 return err 1672 } 1673 1674 options := "" 1675 1676 if fstype == "xfs" { 1677 // XFS needs nouuid or it can't mount filesystems with the same fs 1678 options = joinMountOptions(options, "nouuid") 1679 } 1680 1681 options = joinMountOptions(options, devices.mountOptions) 1682 options = joinMountOptions(options, label.FormatMountLabel("", mountLabel)) 1683 1684 if err := syscall.Mount(info.DevName(), path, fstype, flags, options); err != nil { 1685 return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err) 1686 } 1687 1688 info.mountCount = 1 1689 info.mountPath = path 1690 1691 return nil 1692 } 1693 1694 func (devices *DeviceSet) UnmountDevice(hash string) error { 1695 logrus.Debugf("[devmapper] UnmountDevice(hash=%s)", hash) 1696 defer logrus.Debugf("[devmapper] UnmountDevice(hash=%s) END", hash) 1697 1698 info, err := devices.lookupDevice(hash) 1699 if err != nil { 1700 return err 1701 } 1702 1703 info.lock.Lock() 1704 defer info.lock.Unlock() 1705 1706 devices.Lock() 1707 defer devices.Unlock() 1708 1709 if info.mountCount == 0 { 1710 return fmt.Errorf("UnmountDevice: device not-mounted id %s", hash) 1711 } 1712 1713 info.mountCount-- 1714 if info.mountCount > 0 { 1715 return nil 1716 } 1717 1718 logrus.Debugf("[devmapper] Unmount(%s)", info.mountPath) 1719 if err := syscall.Unmount(info.mountPath, syscall.MNT_DETACH); err != nil { 1720 return err 1721 } 1722 logrus.Debugf("[devmapper] Unmount done") 1723 1724 if err := devices.deactivateDevice(info); err != nil { 1725 return err 1726 } 1727 1728 info.mountPath = "" 1729 1730 return nil 1731 } 1732 1733 func (devices *DeviceSet) HasDevice(hash string) bool { 1734 devices.Lock() 1735 defer devices.Unlock() 1736 1737 info, _ := devices.lookupDevice(hash) 1738 return info != nil 1739 } 1740 1741 func (devices *DeviceSet) HasActivatedDevice(hash string) bool { 1742 info, _ := devices.lookupDevice(hash) 1743 if info == nil { 1744 return false 1745 } 1746 1747 info.lock.Lock() 1748 defer info.lock.Unlock() 1749 1750 devices.Lock() 1751 defer devices.Unlock() 1752 1753 devinfo, _ := devicemapper.GetInfo(info.Name()) 1754 return devinfo != nil && devinfo.Exists != 0 1755 } 1756 1757 func (devices *DeviceSet) List() []string { 1758 devices.Lock() 1759 defer devices.Unlock() 1760 1761 devices.devicesLock.Lock() 1762 ids := make([]string, len(devices.Devices)) 1763 i := 0 1764 for k := range devices.Devices { 1765 ids[i] = k 1766 i++ 1767 } 1768 devices.devicesLock.Unlock() 1769 1770 return ids 1771 } 1772 1773 func (devices *DeviceSet) deviceStatus(devName string) (sizeInSectors, mappedSectors, highestMappedSector uint64, err error) { 1774 var params string 1775 _, sizeInSectors, _, params, err = devicemapper.GetStatus(devName) 1776 if err != nil { 1777 return 1778 } 1779 if _, err = fmt.Sscanf(params, "%d %d", &mappedSectors, &highestMappedSector); err == nil { 1780 return 1781 } 1782 return 1783 } 1784 1785 func (devices *DeviceSet) GetDeviceStatus(hash string) (*DevStatus, error) { 1786 info, err := devices.lookupDevice(hash) 1787 if err != nil { 1788 return nil, err 1789 } 1790 1791 info.lock.Lock() 1792 defer info.lock.Unlock() 1793 1794 devices.Lock() 1795 defer devices.Unlock() 1796 1797 status := &DevStatus{ 1798 DeviceId: info.DeviceId, 1799 Size: info.Size, 1800 TransactionId: info.TransactionId, 1801 } 1802 1803 if err := devices.activateDeviceIfNeeded(info); err != nil { 1804 return nil, fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err) 1805 } 1806 1807 sizeInSectors, mappedSectors, highestMappedSector, err := devices.deviceStatus(info.DevName()) 1808 1809 if err != nil { 1810 return nil, err 1811 } 1812 1813 status.SizeInSectors = sizeInSectors 1814 status.MappedSectors = mappedSectors 1815 status.HighestMappedSector = highestMappedSector 1816 1817 return status, nil 1818 } 1819 1820 func (devices *DeviceSet) poolStatus() (totalSizeInSectors, transactionId, dataUsed, dataTotal, metadataUsed, metadataTotal uint64, err error) { 1821 var params string 1822 if _, totalSizeInSectors, _, params, err = devicemapper.GetStatus(devices.getPoolName()); err == nil { 1823 _, err = fmt.Sscanf(params, "%d %d/%d %d/%d", &transactionId, &metadataUsed, &metadataTotal, &dataUsed, &dataTotal) 1824 } 1825 return 1826 } 1827 1828 // DataDevicePath returns the path to the data storage for this deviceset, 1829 // regardless of loopback or block device 1830 func (devices *DeviceSet) DataDevicePath() string { 1831 return devices.dataDevice 1832 } 1833 1834 // MetadataDevicePath returns the path to the metadata storage for this deviceset, 1835 // regardless of loopback or block device 1836 func (devices *DeviceSet) MetadataDevicePath() string { 1837 return devices.metadataDevice 1838 } 1839 1840 func (devices *DeviceSet) getUnderlyingAvailableSpace(loopFile string) (uint64, error) { 1841 buf := new(syscall.Statfs_t) 1842 if err := syscall.Statfs(loopFile, buf); err != nil { 1843 logrus.Warnf("Couldn't stat loopfile filesystem %v: %v", loopFile, err) 1844 return 0, err 1845 } 1846 return buf.Bfree * uint64(buf.Bsize), nil 1847 } 1848 1849 func (devices *DeviceSet) isRealFile(loopFile string) (bool, error) { 1850 if loopFile != "" { 1851 fi, err := os.Stat(loopFile) 1852 if err != nil { 1853 logrus.Warnf("Couldn't stat loopfile %v: %v", loopFile, err) 1854 return false, err 1855 } 1856 return fi.Mode().IsRegular(), nil 1857 } 1858 return false, nil 1859 } 1860 1861 // Status returns the current status of this deviceset 1862 func (devices *DeviceSet) Status() *Status { 1863 devices.Lock() 1864 defer devices.Unlock() 1865 1866 status := &Status{} 1867 1868 status.PoolName = devices.getPoolName() 1869 status.DataFile = devices.DataDevicePath() 1870 status.DataLoopback = devices.dataLoopFile 1871 status.MetadataFile = devices.MetadataDevicePath() 1872 status.MetadataLoopback = devices.metadataLoopFile 1873 status.UdevSyncSupported = devicemapper.UdevSyncSupported() 1874 status.DeferredRemoveEnabled = devices.deferredRemove 1875 1876 totalSizeInSectors, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus() 1877 if err == nil { 1878 // Convert from blocks to bytes 1879 blockSizeInSectors := totalSizeInSectors / dataTotal 1880 1881 status.Data.Used = dataUsed * blockSizeInSectors * 512 1882 status.Data.Total = dataTotal * blockSizeInSectors * 512 1883 status.Data.Available = status.Data.Total - status.Data.Used 1884 1885 // metadata blocks are always 4k 1886 status.Metadata.Used = metadataUsed * 4096 1887 status.Metadata.Total = metadataTotal * 4096 1888 status.Metadata.Available = status.Metadata.Total - status.Metadata.Used 1889 1890 status.SectorSize = blockSizeInSectors * 512 1891 1892 if check, _ := devices.isRealFile(devices.dataLoopFile); check { 1893 actualSpace, err := devices.getUnderlyingAvailableSpace(devices.dataLoopFile) 1894 if err == nil && actualSpace < status.Data.Available { 1895 status.Data.Available = actualSpace 1896 } 1897 } 1898 1899 if check, _ := devices.isRealFile(devices.metadataLoopFile); check { 1900 actualSpace, err := devices.getUnderlyingAvailableSpace(devices.metadataLoopFile) 1901 if err == nil && actualSpace < status.Metadata.Available { 1902 status.Metadata.Available = actualSpace 1903 } 1904 } 1905 } 1906 1907 return status 1908 } 1909 1910 // Status returns the current status of this deviceset 1911 func (devices *DeviceSet) ExportDeviceMetadata(hash string) (*DeviceMetadata, error) { 1912 info, err := devices.lookupDevice(hash) 1913 if err != nil { 1914 return nil, err 1915 } 1916 1917 info.lock.Lock() 1918 defer info.lock.Unlock() 1919 1920 metadata := &DeviceMetadata{info.DeviceId, info.Size, info.Name()} 1921 return metadata, nil 1922 } 1923 1924 func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error) { 1925 devicemapper.SetDevDir("/dev") 1926 1927 devices := &DeviceSet{ 1928 root: root, 1929 MetaData: MetaData{Devices: make(map[string]*DevInfo)}, 1930 dataLoopbackSize: DefaultDataLoopbackSize, 1931 metaDataLoopbackSize: DefaultMetaDataLoopbackSize, 1932 baseFsSize: DefaultBaseFsSize, 1933 overrideUdevSyncCheck: DefaultUdevSyncOverride, 1934 filesystem: "ext4", 1935 doBlkDiscard: true, 1936 thinpBlockSize: DefaultThinpBlockSize, 1937 deviceIdMap: make([]byte, DeviceIdMapSz), 1938 } 1939 1940 foundBlkDiscard := false 1941 for _, option := range options { 1942 key, val, err := parsers.ParseKeyValueOpt(option) 1943 if err != nil { 1944 return nil, err 1945 } 1946 key = strings.ToLower(key) 1947 switch key { 1948 case "dm.basesize": 1949 size, err := units.RAMInBytes(val) 1950 if err != nil { 1951 return nil, err 1952 } 1953 devices.baseFsSize = uint64(size) 1954 case "dm.loopdatasize": 1955 size, err := units.RAMInBytes(val) 1956 if err != nil { 1957 return nil, err 1958 } 1959 devices.dataLoopbackSize = size 1960 case "dm.loopmetadatasize": 1961 size, err := units.RAMInBytes(val) 1962 if err != nil { 1963 return nil, err 1964 } 1965 devices.metaDataLoopbackSize = size 1966 case "dm.fs": 1967 if val != "ext4" && val != "xfs" { 1968 return nil, fmt.Errorf("Unsupported filesystem %s\n", val) 1969 } 1970 devices.filesystem = val 1971 case "dm.mkfsarg": 1972 devices.mkfsArgs = append(devices.mkfsArgs, val) 1973 case "dm.mountopt": 1974 devices.mountOptions = joinMountOptions(devices.mountOptions, val) 1975 case "dm.metadatadev": 1976 devices.metadataDevice = val 1977 case "dm.datadev": 1978 devices.dataDevice = val 1979 case "dm.thinpooldev": 1980 devices.thinPoolDevice = strings.TrimPrefix(val, "/dev/mapper/") 1981 case "dm.blkdiscard": 1982 foundBlkDiscard = true 1983 devices.doBlkDiscard, err = strconv.ParseBool(val) 1984 if err != nil { 1985 return nil, err 1986 } 1987 case "dm.blocksize": 1988 size, err := units.RAMInBytes(val) 1989 if err != nil { 1990 return nil, err 1991 } 1992 // convert to 512b sectors 1993 devices.thinpBlockSize = uint32(size) >> 9 1994 case "dm.override_udev_sync_check": 1995 devices.overrideUdevSyncCheck, err = strconv.ParseBool(val) 1996 if err != nil { 1997 return nil, err 1998 } 1999 2000 case "dm.use_deferred_removal": 2001 EnableDeferredRemoval, err = strconv.ParseBool(val) 2002 if err != nil { 2003 return nil, err 2004 } 2005 2006 default: 2007 return nil, fmt.Errorf("Unknown option %s\n", key) 2008 } 2009 } 2010 2011 // By default, don't do blk discard hack on raw devices, its rarely useful and is expensive 2012 if !foundBlkDiscard && (devices.dataDevice != "" || devices.thinPoolDevice != "") { 2013 devices.doBlkDiscard = false 2014 } 2015 2016 if err := devices.initDevmapper(doInit); err != nil { 2017 return nil, err 2018 } 2019 2020 return devices, nil 2021 }