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