gopkg.in/docker/docker.v20@v20.10.27/layer/layer_store.go (about) 1 package layer // import "github.com/docker/docker/layer" 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "sync" 10 11 "github.com/docker/distribution" 12 "github.com/docker/docker/daemon/graphdriver" 13 "github.com/docker/docker/pkg/idtools" 14 "github.com/docker/docker/pkg/plugingetter" 15 "github.com/docker/docker/pkg/stringid" 16 "github.com/docker/docker/pkg/system" 17 "github.com/moby/locker" 18 digest "github.com/opencontainers/go-digest" 19 "github.com/sirupsen/logrus" 20 "github.com/vbatts/tar-split/tar/asm" 21 "github.com/vbatts/tar-split/tar/storage" 22 ) 23 24 // maxLayerDepth represents the maximum number of 25 // layers which can be chained together. 125 was 26 // chosen to account for the 127 max in some 27 // graphdrivers plus the 2 additional layers 28 // used to create a rwlayer. 29 const maxLayerDepth = 125 30 31 type layerStore struct { 32 store *fileMetadataStore 33 driver graphdriver.Driver 34 useTarSplit bool 35 36 layerMap map[ChainID]*roLayer 37 layerL sync.Mutex 38 39 mounts map[string]*mountedLayer 40 mountL sync.Mutex 41 42 // protect *RWLayer() methods from operating on the same name/id 43 locker *locker.Locker 44 45 os string 46 } 47 48 // StoreOptions are the options used to create a new Store instance 49 type StoreOptions struct { 50 Root string 51 MetadataStorePathTemplate string 52 GraphDriver string 53 GraphDriverOptions []string 54 IDMapping *idtools.IdentityMapping 55 PluginGetter plugingetter.PluginGetter 56 ExperimentalEnabled bool 57 OS string 58 } 59 60 // NewStoreFromOptions creates a new Store instance 61 func NewStoreFromOptions(options StoreOptions) (Store, error) { 62 driver, err := graphdriver.New(options.GraphDriver, options.PluginGetter, graphdriver.Options{ 63 Root: options.Root, 64 DriverOptions: options.GraphDriverOptions, 65 UIDMaps: options.IDMapping.UIDs(), 66 GIDMaps: options.IDMapping.GIDs(), 67 ExperimentalEnabled: options.ExperimentalEnabled, 68 }) 69 if err != nil { 70 return nil, fmt.Errorf("error initializing graphdriver: %v", err) 71 } 72 logrus.Debugf("Initialized graph driver %s", driver) 73 74 root := fmt.Sprintf(options.MetadataStorePathTemplate, driver) 75 76 return newStoreFromGraphDriver(root, driver, options.OS) 77 } 78 79 // newStoreFromGraphDriver creates a new Store instance using the provided 80 // metadata store and graph driver. The metadata store will be used to restore 81 // the Store. 82 func newStoreFromGraphDriver(root string, driver graphdriver.Driver, os string) (Store, error) { 83 if !system.IsOSSupported(os) { 84 return nil, fmt.Errorf("failed to initialize layer store as operating system '%s' is not supported", os) 85 } 86 caps := graphdriver.Capabilities{} 87 if capDriver, ok := driver.(graphdriver.CapabilityDriver); ok { 88 caps = capDriver.Capabilities() 89 } 90 91 ms, err := newFSMetadataStore(root) 92 if err != nil { 93 return nil, err 94 } 95 96 ls := &layerStore{ 97 store: ms, 98 driver: driver, 99 layerMap: map[ChainID]*roLayer{}, 100 mounts: map[string]*mountedLayer{}, 101 locker: locker.New(), 102 useTarSplit: !caps.ReproducesExactDiffs, 103 os: os, 104 } 105 106 ids, mounts, err := ms.List() 107 if err != nil { 108 return nil, err 109 } 110 111 for _, id := range ids { 112 l, err := ls.loadLayer(id) 113 if err != nil { 114 logrus.Debugf("Failed to load layer %s: %s", id, err) 115 continue 116 } 117 if l.parent != nil { 118 l.parent.referenceCount++ 119 } 120 } 121 122 for _, mount := range mounts { 123 if err := ls.loadMount(mount); err != nil { 124 logrus.Debugf("Failed to load mount %s: %s", mount, err) 125 } 126 } 127 128 return ls, nil 129 } 130 131 func (ls *layerStore) Driver() graphdriver.Driver { 132 return ls.driver 133 } 134 135 func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) { 136 cl, ok := ls.layerMap[layer] 137 if ok { 138 return cl, nil 139 } 140 141 diff, err := ls.store.GetDiffID(layer) 142 if err != nil { 143 return nil, fmt.Errorf("failed to get diff id for %s: %s", layer, err) 144 } 145 146 size, err := ls.store.GetSize(layer) 147 if err != nil { 148 return nil, fmt.Errorf("failed to get size for %s: %s", layer, err) 149 } 150 151 cacheID, err := ls.store.GetCacheID(layer) 152 if err != nil { 153 return nil, fmt.Errorf("failed to get cache id for %s: %s", layer, err) 154 } 155 156 parent, err := ls.store.GetParent(layer) 157 if err != nil { 158 return nil, fmt.Errorf("failed to get parent for %s: %s", layer, err) 159 } 160 161 descriptor, err := ls.store.GetDescriptor(layer) 162 if err != nil { 163 return nil, fmt.Errorf("failed to get descriptor for %s: %s", layer, err) 164 } 165 166 os, err := ls.store.getOS(layer) 167 if err != nil { 168 return nil, fmt.Errorf("failed to get operating system for %s: %s", layer, err) 169 } 170 171 if os != ls.os { 172 return nil, fmt.Errorf("failed to load layer with os %s into layerstore for %s", os, ls.os) 173 } 174 175 cl = &roLayer{ 176 chainID: layer, 177 diffID: diff, 178 size: size, 179 cacheID: cacheID, 180 layerStore: ls, 181 references: map[Layer]struct{}{}, 182 descriptor: descriptor, 183 } 184 185 if parent != "" { 186 p, err := ls.loadLayer(parent) 187 if err != nil { 188 return nil, err 189 } 190 cl.parent = p 191 } 192 193 ls.layerMap[cl.chainID] = cl 194 195 return cl, nil 196 } 197 198 func (ls *layerStore) loadMount(mount string) error { 199 ls.mountL.Lock() 200 defer ls.mountL.Unlock() 201 if _, ok := ls.mounts[mount]; ok { 202 return nil 203 } 204 205 mountID, err := ls.store.GetMountID(mount) 206 if err != nil { 207 return err 208 } 209 210 initID, err := ls.store.GetInitID(mount) 211 if err != nil { 212 return err 213 } 214 215 parent, err := ls.store.GetMountParent(mount) 216 if err != nil { 217 return err 218 } 219 220 ml := &mountedLayer{ 221 name: mount, 222 mountID: mountID, 223 initID: initID, 224 layerStore: ls, 225 references: map[RWLayer]*referencedRWLayer{}, 226 } 227 228 if parent != "" { 229 p, err := ls.loadLayer(parent) 230 if err != nil { 231 return err 232 } 233 ml.parent = p 234 235 p.referenceCount++ 236 } 237 238 ls.mounts[ml.name] = ml 239 240 return nil 241 } 242 243 func (ls *layerStore) applyTar(tx *fileMetadataTransaction, ts io.Reader, parent string, layer *roLayer) error { 244 digester := digest.Canonical.Digester() 245 tr := io.TeeReader(ts, digester.Hash()) 246 247 rdr := tr 248 if ls.useTarSplit { 249 tsw, err := tx.TarSplitWriter(true) 250 if err != nil { 251 return err 252 } 253 metaPacker := storage.NewJSONPacker(tsw) 254 defer tsw.Close() 255 256 // we're passing nil here for the file putter, because the ApplyDiff will 257 // handle the extraction of the archive 258 rdr, err = asm.NewInputTarStream(tr, metaPacker, nil) 259 if err != nil { 260 return err 261 } 262 } 263 264 applySize, err := ls.driver.ApplyDiff(layer.cacheID, parent, rdr) 265 // discard trailing data but ensure metadata is picked up to reconstruct stream 266 // unconditionally call io.Copy here before checking err to ensure the resources 267 // allocated by NewInputTarStream above are always released 268 io.Copy(io.Discard, rdr) // ignore error as reader may be closed 269 if err != nil { 270 return err 271 } 272 273 layer.size = applySize 274 layer.diffID = DiffID(digester.Digest()) 275 276 logrus.Debugf("Applied tar %s to %s, size: %d", layer.diffID, layer.cacheID, applySize) 277 278 return nil 279 } 280 281 func (ls *layerStore) Register(ts io.Reader, parent ChainID) (Layer, error) { 282 return ls.registerWithDescriptor(ts, parent, distribution.Descriptor{}) 283 } 284 285 func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, descriptor distribution.Descriptor) (Layer, error) { 286 // err is used to hold the error which will always trigger 287 // cleanup of creates sources but may not be an error returned 288 // to the caller (already exists). 289 var err error 290 var pid string 291 var p *roLayer 292 293 if string(parent) != "" { 294 p = ls.get(parent) 295 if p == nil { 296 return nil, ErrLayerDoesNotExist 297 } 298 pid = p.cacheID 299 // Release parent chain if error 300 defer func() { 301 if err != nil { 302 ls.layerL.Lock() 303 ls.releaseLayer(p) 304 ls.layerL.Unlock() 305 } 306 }() 307 if p.depth() >= maxLayerDepth { 308 err = ErrMaxDepthExceeded 309 return nil, err 310 } 311 } 312 313 // Create new roLayer 314 layer := &roLayer{ 315 parent: p, 316 cacheID: stringid.GenerateRandomID(), 317 referenceCount: 1, 318 layerStore: ls, 319 references: map[Layer]struct{}{}, 320 descriptor: descriptor, 321 } 322 323 if err = ls.driver.Create(layer.cacheID, pid, nil); err != nil { 324 return nil, err 325 } 326 327 tx, err := ls.store.StartTransaction() 328 if err != nil { 329 return nil, err 330 } 331 332 defer func() { 333 if err != nil { 334 logrus.Debugf("Cleaning up layer %s: %v", layer.cacheID, err) 335 if err := ls.driver.Remove(layer.cacheID); err != nil { 336 logrus.Errorf("Error cleaning up cache layer %s: %v", layer.cacheID, err) 337 } 338 if err := tx.Cancel(); err != nil { 339 logrus.Errorf("Error canceling metadata transaction %q: %s", tx.String(), err) 340 } 341 } 342 }() 343 344 if err = ls.applyTar(tx, ts, pid, layer); err != nil { 345 return nil, err 346 } 347 348 if layer.parent == nil { 349 layer.chainID = ChainID(layer.diffID) 350 } else { 351 layer.chainID = createChainIDFromParent(layer.parent.chainID, layer.diffID) 352 } 353 354 if err = storeLayer(tx, layer); err != nil { 355 return nil, err 356 } 357 358 ls.layerL.Lock() 359 defer ls.layerL.Unlock() 360 361 if existingLayer := ls.getWithoutLock(layer.chainID); existingLayer != nil { 362 // Set error for cleanup, but do not return the error 363 err = errors.New("layer already exists") 364 return existingLayer.getReference(), nil 365 } 366 367 if err = tx.Commit(layer.chainID); err != nil { 368 return nil, err 369 } 370 371 ls.layerMap[layer.chainID] = layer 372 373 return layer.getReference(), nil 374 } 375 376 func (ls *layerStore) getWithoutLock(layer ChainID) *roLayer { 377 l, ok := ls.layerMap[layer] 378 if !ok { 379 return nil 380 } 381 382 l.referenceCount++ 383 384 return l 385 } 386 387 func (ls *layerStore) get(l ChainID) *roLayer { 388 ls.layerL.Lock() 389 defer ls.layerL.Unlock() 390 return ls.getWithoutLock(l) 391 } 392 393 func (ls *layerStore) Get(l ChainID) (Layer, error) { 394 ls.layerL.Lock() 395 defer ls.layerL.Unlock() 396 397 layer := ls.getWithoutLock(l) 398 if layer == nil { 399 return nil, ErrLayerDoesNotExist 400 } 401 402 return layer.getReference(), nil 403 } 404 405 func (ls *layerStore) Map() map[ChainID]Layer { 406 ls.layerL.Lock() 407 defer ls.layerL.Unlock() 408 409 layers := map[ChainID]Layer{} 410 411 for k, v := range ls.layerMap { 412 layers[k] = v 413 } 414 415 return layers 416 } 417 418 func (ls *layerStore) deleteLayer(layer *roLayer, metadata *Metadata) error { 419 // Rename layer digest folder first so we detect orphan layer(s) 420 // if ls.driver.Remove fails 421 var dir string 422 for { 423 dgst := digest.Digest(layer.chainID) 424 tmpID := fmt.Sprintf("%s-%s-removing", dgst.Hex(), stringid.GenerateRandomID()) 425 dir = filepath.Join(ls.store.root, string(dgst.Algorithm()), tmpID) 426 err := os.Rename(ls.store.getLayerDirectory(layer.chainID), dir) 427 if os.IsExist(err) { 428 continue 429 } 430 break 431 } 432 err := ls.driver.Remove(layer.cacheID) 433 if err != nil { 434 return err 435 } 436 err = os.RemoveAll(dir) 437 if err != nil { 438 return err 439 } 440 metadata.DiffID = layer.diffID 441 metadata.ChainID = layer.chainID 442 metadata.Size, err = layer.Size() 443 if err != nil { 444 return err 445 } 446 metadata.DiffSize = layer.size 447 448 return nil 449 } 450 451 func (ls *layerStore) releaseLayer(l *roLayer) ([]Metadata, error) { 452 depth := 0 453 removed := []Metadata{} 454 for { 455 if l.referenceCount == 0 { 456 panic("layer not retained") 457 } 458 l.referenceCount-- 459 if l.referenceCount != 0 { 460 return removed, nil 461 } 462 463 if len(removed) == 0 && depth > 0 { 464 panic("cannot remove layer with child") 465 } 466 if l.hasReferences() { 467 panic("cannot delete referenced layer") 468 } 469 // Remove layer from layer map first so it is not considered to exist 470 // when if ls.deleteLayer fails. 471 delete(ls.layerMap, l.chainID) 472 473 var metadata Metadata 474 if err := ls.deleteLayer(l, &metadata); err != nil { 475 return nil, err 476 } 477 removed = append(removed, metadata) 478 479 if l.parent == nil { 480 return removed, nil 481 } 482 483 depth++ 484 l = l.parent 485 } 486 } 487 488 func (ls *layerStore) Release(l Layer) ([]Metadata, error) { 489 ls.layerL.Lock() 490 defer ls.layerL.Unlock() 491 layer, ok := ls.layerMap[l.ChainID()] 492 if !ok { 493 return []Metadata{}, nil 494 } 495 if !layer.hasReference(l) { 496 return nil, ErrLayerNotRetained 497 } 498 499 layer.deleteReference(l) 500 501 return ls.releaseLayer(layer) 502 } 503 504 func (ls *layerStore) CreateRWLayer(name string, parent ChainID, opts *CreateRWLayerOpts) (_ RWLayer, err error) { 505 var ( 506 storageOpt map[string]string 507 initFunc MountInit 508 mountLabel string 509 ) 510 511 if opts != nil { 512 mountLabel = opts.MountLabel 513 storageOpt = opts.StorageOpt 514 initFunc = opts.InitFunc 515 } 516 517 ls.locker.Lock(name) 518 defer ls.locker.Unlock(name) 519 520 ls.mountL.Lock() 521 _, ok := ls.mounts[name] 522 ls.mountL.Unlock() 523 if ok { 524 return nil, ErrMountNameConflict 525 } 526 527 var pid string 528 var p *roLayer 529 if string(parent) != "" { 530 p = ls.get(parent) 531 if p == nil { 532 return nil, ErrLayerDoesNotExist 533 } 534 pid = p.cacheID 535 536 // Release parent chain if error 537 defer func() { 538 if err != nil { 539 ls.layerL.Lock() 540 ls.releaseLayer(p) 541 ls.layerL.Unlock() 542 } 543 }() 544 } 545 546 m := &mountedLayer{ 547 name: name, 548 parent: p, 549 mountID: ls.mountID(name), 550 layerStore: ls, 551 references: map[RWLayer]*referencedRWLayer{}, 552 } 553 554 if initFunc != nil { 555 pid, err = ls.initMount(m.mountID, pid, mountLabel, initFunc, storageOpt) 556 if err != nil { 557 return 558 } 559 m.initID = pid 560 } 561 562 createOpts := &graphdriver.CreateOpts{ 563 StorageOpt: storageOpt, 564 } 565 566 if err = ls.driver.CreateReadWrite(m.mountID, pid, createOpts); err != nil { 567 return 568 } 569 if err = ls.saveMount(m); err != nil { 570 return 571 } 572 573 return m.getReference(), nil 574 } 575 576 func (ls *layerStore) GetRWLayer(id string) (RWLayer, error) { 577 ls.locker.Lock(id) 578 defer ls.locker.Unlock(id) 579 580 ls.mountL.Lock() 581 mount := ls.mounts[id] 582 ls.mountL.Unlock() 583 if mount == nil { 584 return nil, ErrMountDoesNotExist 585 } 586 587 return mount.getReference(), nil 588 } 589 590 func (ls *layerStore) GetMountID(id string) (string, error) { 591 ls.mountL.Lock() 592 mount := ls.mounts[id] 593 ls.mountL.Unlock() 594 595 if mount == nil { 596 return "", ErrMountDoesNotExist 597 } 598 logrus.Debugf("GetMountID id: %s -> mountID: %s", id, mount.mountID) 599 600 return mount.mountID, nil 601 } 602 603 func (ls *layerStore) ReleaseRWLayer(l RWLayer) ([]Metadata, error) { 604 name := l.Name() 605 ls.locker.Lock(name) 606 defer ls.locker.Unlock(name) 607 608 ls.mountL.Lock() 609 m := ls.mounts[name] 610 ls.mountL.Unlock() 611 if m == nil { 612 return []Metadata{}, nil 613 } 614 615 if err := m.deleteReference(l); err != nil { 616 return nil, err 617 } 618 619 if m.hasReferences() { 620 return []Metadata{}, nil 621 } 622 623 if err := ls.driver.Remove(m.mountID); err != nil { 624 logrus.Errorf("Error removing mounted layer %s: %s", m.name, err) 625 m.retakeReference(l) 626 return nil, err 627 } 628 629 if m.initID != "" { 630 if err := ls.driver.Remove(m.initID); err != nil { 631 logrus.Errorf("Error removing init layer %s: %s", m.name, err) 632 m.retakeReference(l) 633 return nil, err 634 } 635 } 636 637 if err := ls.store.RemoveMount(m.name); err != nil { 638 logrus.Errorf("Error removing mount metadata: %s: %s", m.name, err) 639 m.retakeReference(l) 640 return nil, err 641 } 642 643 ls.mountL.Lock() 644 delete(ls.mounts, name) 645 ls.mountL.Unlock() 646 647 ls.layerL.Lock() 648 defer ls.layerL.Unlock() 649 if m.parent != nil { 650 return ls.releaseLayer(m.parent) 651 } 652 653 return []Metadata{}, nil 654 } 655 656 func (ls *layerStore) saveMount(mount *mountedLayer) error { 657 if err := ls.store.SetMountID(mount.name, mount.mountID); err != nil { 658 return err 659 } 660 661 if mount.initID != "" { 662 if err := ls.store.SetInitID(mount.name, mount.initID); err != nil { 663 return err 664 } 665 } 666 667 if mount.parent != nil { 668 if err := ls.store.SetMountParent(mount.name, mount.parent.chainID); err != nil { 669 return err 670 } 671 } 672 673 ls.mountL.Lock() 674 ls.mounts[mount.name] = mount 675 ls.mountL.Unlock() 676 677 return nil 678 } 679 680 func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc MountInit, storageOpt map[string]string) (string, error) { 681 // Use "<graph-id>-init" to maintain compatibility with graph drivers 682 // which are expecting this layer with this special name. If all 683 // graph drivers can be updated to not rely on knowing about this layer 684 // then the initID should be randomly generated. 685 initID := fmt.Sprintf("%s-init", graphID) 686 687 createOpts := &graphdriver.CreateOpts{ 688 MountLabel: mountLabel, 689 StorageOpt: storageOpt, 690 } 691 692 if err := ls.driver.CreateReadWrite(initID, parent, createOpts); err != nil { 693 return "", err 694 } 695 p, err := ls.driver.Get(initID, "") 696 if err != nil { 697 return "", err 698 } 699 700 if err := initFunc(p); err != nil { 701 ls.driver.Put(initID) 702 return "", err 703 } 704 705 if err := ls.driver.Put(initID); err != nil { 706 return "", err 707 } 708 709 return initID, nil 710 } 711 712 func (ls *layerStore) getTarStream(rl *roLayer) (io.ReadCloser, error) { 713 if !ls.useTarSplit { 714 var parentCacheID string 715 if rl.parent != nil { 716 parentCacheID = rl.parent.cacheID 717 } 718 719 return ls.driver.Diff(rl.cacheID, parentCacheID) 720 } 721 722 r, err := ls.store.TarSplitReader(rl.chainID) 723 if err != nil { 724 return nil, err 725 } 726 727 pr, pw := io.Pipe() 728 go func() { 729 err := ls.assembleTarTo(rl.cacheID, r, nil, pw) 730 if err != nil { 731 pw.CloseWithError(err) 732 } else { 733 pw.Close() 734 } 735 }() 736 737 return pr, nil 738 } 739 740 func (ls *layerStore) assembleTarTo(graphID string, metadata io.ReadCloser, size *int64, w io.Writer) error { 741 diffDriver, ok := ls.driver.(graphdriver.DiffGetterDriver) 742 if !ok { 743 diffDriver = &naiveDiffPathDriver{ls.driver} 744 } 745 746 defer metadata.Close() 747 748 // get our relative path to the container 749 fileGetCloser, err := diffDriver.DiffGetter(graphID) 750 if err != nil { 751 return err 752 } 753 defer fileGetCloser.Close() 754 755 metaUnpacker := storage.NewJSONUnpacker(metadata) 756 upackerCounter := &unpackSizeCounter{metaUnpacker, size} 757 logrus.Debugf("Assembling tar data for %s", graphID) 758 return asm.WriteOutputTarStream(fileGetCloser, upackerCounter, w) 759 } 760 761 func (ls *layerStore) Cleanup() error { 762 orphanLayers, err := ls.store.getOrphan() 763 if err != nil { 764 logrus.Errorf("Cannot get orphan layers: %v", err) 765 } 766 logrus.Debugf("found %v orphan layers", len(orphanLayers)) 767 for _, orphan := range orphanLayers { 768 logrus.Debugf("removing orphan layer, chain ID: %v , cache ID: %v", orphan.chainID, orphan.cacheID) 769 err = ls.driver.Remove(orphan.cacheID) 770 if err != nil && !os.IsNotExist(err) { 771 logrus.WithError(err).WithField("cache-id", orphan.cacheID).Error("cannot remove orphan layer") 772 continue 773 } 774 err = ls.store.Remove(orphan.chainID, orphan.cacheID) 775 if err != nil { 776 logrus.WithError(err).WithField("chain-id", orphan.chainID).Error("cannot remove orphan layer metadata") 777 } 778 } 779 return ls.driver.Cleanup() 780 } 781 782 func (ls *layerStore) DriverStatus() [][2]string { 783 return ls.driver.Status() 784 } 785 786 func (ls *layerStore) DriverName() string { 787 return ls.driver.String() 788 } 789 790 type naiveDiffPathDriver struct { 791 graphdriver.Driver 792 } 793 794 type fileGetPutter struct { 795 storage.FileGetter 796 driver graphdriver.Driver 797 id string 798 } 799 800 func (w *fileGetPutter) Close() error { 801 return w.driver.Put(w.id) 802 } 803 804 func (n *naiveDiffPathDriver) DiffGetter(id string) (graphdriver.FileGetCloser, error) { 805 p, err := n.Driver.Get(id, "") 806 if err != nil { 807 return nil, err 808 } 809 return &fileGetPutter{storage.NewPathFileGetter(p.Path()), n.Driver, id}, nil 810 }