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