github.com/dpiddy/docker@v1.12.2-rc1/layer/layer_store.go (about) 1 package layer 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "sync" 9 10 "github.com/Sirupsen/logrus" 11 "github.com/docker/distribution" 12 "github.com/docker/distribution/digest" 13 "github.com/docker/docker/daemon/graphdriver" 14 "github.com/docker/docker/pkg/archive" 15 "github.com/docker/docker/pkg/idtools" 16 "github.com/docker/docker/pkg/stringid" 17 "github.com/vbatts/tar-split/tar/asm" 18 "github.com/vbatts/tar-split/tar/storage" 19 ) 20 21 // maxLayerDepth represents the maximum number of 22 // layers which can be chained together. 125 was 23 // chosen to account for the 127 max in some 24 // graphdrivers plus the 2 additional layers 25 // used to create a rwlayer. 26 const maxLayerDepth = 125 27 28 type layerStore struct { 29 store MetadataStore 30 driver graphdriver.Driver 31 32 layerMap map[ChainID]*roLayer 33 layerL sync.Mutex 34 35 mounts map[string]*mountedLayer 36 mountL sync.Mutex 37 } 38 39 // StoreOptions are the options used to create a new Store instance 40 type StoreOptions struct { 41 StorePath string 42 MetadataStorePathTemplate string 43 GraphDriver string 44 GraphDriverOptions []string 45 UIDMaps []idtools.IDMap 46 GIDMaps []idtools.IDMap 47 } 48 49 // NewStoreFromOptions creates a new Store instance 50 func NewStoreFromOptions(options StoreOptions) (Store, error) { 51 driver, err := graphdriver.New( 52 options.StorePath, 53 options.GraphDriver, 54 options.GraphDriverOptions, 55 options.UIDMaps, 56 options.GIDMaps) 57 if err != nil { 58 return nil, fmt.Errorf("error initializing graphdriver: %v", err) 59 } 60 logrus.Debugf("Using graph driver %s", driver) 61 62 fms, err := NewFSMetadataStore(fmt.Sprintf(options.MetadataStorePathTemplate, driver)) 63 if err != nil { 64 return nil, err 65 } 66 67 return NewStoreFromGraphDriver(fms, driver) 68 } 69 70 // NewStoreFromGraphDriver creates a new Store instance using the provided 71 // metadata store and graph driver. The metadata store will be used to restore 72 // the Store. 73 func NewStoreFromGraphDriver(store MetadataStore, driver graphdriver.Driver) (Store, error) { 74 ls := &layerStore{ 75 store: store, 76 driver: driver, 77 layerMap: map[ChainID]*roLayer{}, 78 mounts: map[string]*mountedLayer{}, 79 } 80 81 ids, mounts, err := store.List() 82 if err != nil { 83 return nil, err 84 } 85 86 for _, id := range ids { 87 l, err := ls.loadLayer(id) 88 if err != nil { 89 logrus.Debugf("Failed to load layer %s: %s", id, err) 90 continue 91 } 92 if l.parent != nil { 93 l.parent.referenceCount++ 94 } 95 } 96 97 for _, mount := range mounts { 98 if err := ls.loadMount(mount); err != nil { 99 logrus.Debugf("Failed to load mount %s: %s", mount, err) 100 } 101 } 102 103 return ls, nil 104 } 105 106 func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) { 107 cl, ok := ls.layerMap[layer] 108 if ok { 109 return cl, nil 110 } 111 112 diff, err := ls.store.GetDiffID(layer) 113 if err != nil { 114 return nil, fmt.Errorf("failed to get diff id for %s: %s", layer, err) 115 } 116 117 size, err := ls.store.GetSize(layer) 118 if err != nil { 119 return nil, fmt.Errorf("failed to get size for %s: %s", layer, err) 120 } 121 122 cacheID, err := ls.store.GetCacheID(layer) 123 if err != nil { 124 return nil, fmt.Errorf("failed to get cache id for %s: %s", layer, err) 125 } 126 127 parent, err := ls.store.GetParent(layer) 128 if err != nil { 129 return nil, fmt.Errorf("failed to get parent for %s: %s", layer, err) 130 } 131 132 descriptor, err := ls.store.GetDescriptor(layer) 133 if err != nil { 134 return nil, fmt.Errorf("failed to get descriptor for %s: %s", layer, err) 135 } 136 137 cl = &roLayer{ 138 chainID: layer, 139 diffID: diff, 140 size: size, 141 cacheID: cacheID, 142 layerStore: ls, 143 references: map[Layer]struct{}{}, 144 descriptor: descriptor, 145 } 146 147 if parent != "" { 148 p, err := ls.loadLayer(parent) 149 if err != nil { 150 return nil, err 151 } 152 cl.parent = p 153 } 154 155 ls.layerMap[cl.chainID] = cl 156 157 return cl, nil 158 } 159 160 func (ls *layerStore) loadMount(mount string) error { 161 if _, ok := ls.mounts[mount]; ok { 162 return nil 163 } 164 165 mountID, err := ls.store.GetMountID(mount) 166 if err != nil { 167 return err 168 } 169 170 initID, err := ls.store.GetInitID(mount) 171 if err != nil { 172 return err 173 } 174 175 parent, err := ls.store.GetMountParent(mount) 176 if err != nil { 177 return err 178 } 179 180 ml := &mountedLayer{ 181 name: mount, 182 mountID: mountID, 183 initID: initID, 184 layerStore: ls, 185 references: map[RWLayer]*referencedRWLayer{}, 186 } 187 188 if parent != "" { 189 p, err := ls.loadLayer(parent) 190 if err != nil { 191 return err 192 } 193 ml.parent = p 194 195 p.referenceCount++ 196 } 197 198 ls.mounts[ml.name] = ml 199 200 return nil 201 } 202 203 func (ls *layerStore) applyTar(tx MetadataTransaction, ts io.Reader, parent string, layer *roLayer) error { 204 digester := digest.Canonical.New() 205 tr := io.TeeReader(ts, digester.Hash()) 206 207 tsw, err := tx.TarSplitWriter(true) 208 if err != nil { 209 return err 210 } 211 metaPacker := storage.NewJSONPacker(tsw) 212 defer tsw.Close() 213 214 // we're passing nil here for the file putter, because the ApplyDiff will 215 // handle the extraction of the archive 216 rdr, err := asm.NewInputTarStream(tr, metaPacker, nil) 217 if err != nil { 218 return err 219 } 220 221 applySize, err := ls.driver.ApplyDiff(layer.cacheID, parent, archive.Reader(rdr)) 222 if err != nil { 223 return err 224 } 225 226 // Discard trailing data but ensure metadata is picked up to reconstruct stream 227 io.Copy(ioutil.Discard, rdr) // ignore error as reader may be closed 228 229 layer.size = applySize 230 layer.diffID = DiffID(digester.Digest()) 231 232 logrus.Debugf("Applied tar %s to %s, size: %d", layer.diffID, layer.cacheID, applySize) 233 234 return nil 235 } 236 237 func (ls *layerStore) Register(ts io.Reader, parent ChainID) (Layer, error) { 238 return ls.registerWithDescriptor(ts, parent, distribution.Descriptor{}) 239 } 240 241 func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, descriptor distribution.Descriptor) (Layer, error) { 242 // err is used to hold the error which will always trigger 243 // cleanup of creates sources but may not be an error returned 244 // to the caller (already exists). 245 var err error 246 var pid string 247 var p *roLayer 248 if string(parent) != "" { 249 p = ls.get(parent) 250 if p == nil { 251 return nil, ErrLayerDoesNotExist 252 } 253 pid = p.cacheID 254 // Release parent chain if error 255 defer func() { 256 if err != nil { 257 ls.layerL.Lock() 258 ls.releaseLayer(p) 259 ls.layerL.Unlock() 260 } 261 }() 262 if p.depth() >= maxLayerDepth { 263 err = ErrMaxDepthExceeded 264 return nil, err 265 } 266 } 267 268 // Create new roLayer 269 layer := &roLayer{ 270 parent: p, 271 cacheID: stringid.GenerateRandomID(), 272 referenceCount: 1, 273 layerStore: ls, 274 references: map[Layer]struct{}{}, 275 descriptor: descriptor, 276 } 277 278 if err = ls.driver.Create(layer.cacheID, pid, "", nil); err != nil { 279 return nil, err 280 } 281 282 tx, err := ls.store.StartTransaction() 283 if err != nil { 284 return nil, err 285 } 286 287 defer func() { 288 if err != nil { 289 logrus.Debugf("Cleaning up layer %s: %v", layer.cacheID, err) 290 if err := ls.driver.Remove(layer.cacheID); err != nil { 291 logrus.Errorf("Error cleaning up cache layer %s: %v", layer.cacheID, err) 292 } 293 if err := tx.Cancel(); err != nil { 294 logrus.Errorf("Error canceling metadata transaction %q: %s", tx.String(), err) 295 } 296 } 297 }() 298 299 if err = ls.applyTar(tx, ts, pid, layer); err != nil { 300 return nil, err 301 } 302 303 if layer.parent == nil { 304 layer.chainID = ChainID(layer.diffID) 305 } else { 306 layer.chainID = createChainIDFromParent(layer.parent.chainID, layer.diffID) 307 } 308 309 if err = storeLayer(tx, layer); err != nil { 310 return nil, err 311 } 312 313 ls.layerL.Lock() 314 defer ls.layerL.Unlock() 315 316 if existingLayer := ls.getWithoutLock(layer.chainID); existingLayer != nil { 317 // Set error for cleanup, but do not return the error 318 err = errors.New("layer already exists") 319 return existingLayer.getReference(), nil 320 } 321 322 if err = tx.Commit(layer.chainID); err != nil { 323 return nil, err 324 } 325 326 ls.layerMap[layer.chainID] = layer 327 328 return layer.getReference(), nil 329 } 330 331 func (ls *layerStore) getWithoutLock(layer ChainID) *roLayer { 332 l, ok := ls.layerMap[layer] 333 if !ok { 334 return nil 335 } 336 337 l.referenceCount++ 338 339 return l 340 } 341 342 func (ls *layerStore) get(l ChainID) *roLayer { 343 ls.layerL.Lock() 344 defer ls.layerL.Unlock() 345 return ls.getWithoutLock(l) 346 } 347 348 func (ls *layerStore) Get(l ChainID) (Layer, error) { 349 ls.layerL.Lock() 350 defer ls.layerL.Unlock() 351 352 layer := ls.getWithoutLock(l) 353 if layer == nil { 354 return nil, ErrLayerDoesNotExist 355 } 356 357 return layer.getReference(), nil 358 } 359 360 func (ls *layerStore) deleteLayer(layer *roLayer, metadata *Metadata) error { 361 err := ls.driver.Remove(layer.cacheID) 362 if err != nil { 363 return err 364 } 365 366 err = ls.store.Remove(layer.chainID) 367 if err != nil { 368 return err 369 } 370 metadata.DiffID = layer.diffID 371 metadata.ChainID = layer.chainID 372 metadata.Size, err = layer.Size() 373 if err != nil { 374 return err 375 } 376 metadata.DiffSize = layer.size 377 378 return nil 379 } 380 381 func (ls *layerStore) releaseLayer(l *roLayer) ([]Metadata, error) { 382 depth := 0 383 removed := []Metadata{} 384 for { 385 if l.referenceCount == 0 { 386 panic("layer not retained") 387 } 388 l.referenceCount-- 389 if l.referenceCount != 0 { 390 return removed, nil 391 } 392 393 if len(removed) == 0 && depth > 0 { 394 panic("cannot remove layer with child") 395 } 396 if l.hasReferences() { 397 panic("cannot delete referenced layer") 398 } 399 var metadata Metadata 400 if err := ls.deleteLayer(l, &metadata); err != nil { 401 return nil, err 402 } 403 404 delete(ls.layerMap, l.chainID) 405 removed = append(removed, metadata) 406 407 if l.parent == nil { 408 return removed, nil 409 } 410 411 depth++ 412 l = l.parent 413 } 414 } 415 416 func (ls *layerStore) Release(l Layer) ([]Metadata, error) { 417 ls.layerL.Lock() 418 defer ls.layerL.Unlock() 419 layer, ok := ls.layerMap[l.ChainID()] 420 if !ok { 421 return []Metadata{}, nil 422 } 423 if !layer.hasReference(l) { 424 return nil, ErrLayerNotRetained 425 } 426 427 layer.deleteReference(l) 428 429 return ls.releaseLayer(layer) 430 } 431 432 func (ls *layerStore) CreateRWLayer(name string, parent ChainID, mountLabel string, initFunc MountInit, storageOpt map[string]string) (RWLayer, error) { 433 ls.mountL.Lock() 434 defer ls.mountL.Unlock() 435 m, ok := ls.mounts[name] 436 if ok { 437 return nil, ErrMountNameConflict 438 } 439 440 var err error 441 var pid string 442 var p *roLayer 443 if string(parent) != "" { 444 p = ls.get(parent) 445 if p == nil { 446 return nil, ErrLayerDoesNotExist 447 } 448 pid = p.cacheID 449 450 // Release parent chain if error 451 defer func() { 452 if err != nil { 453 ls.layerL.Lock() 454 ls.releaseLayer(p) 455 ls.layerL.Unlock() 456 } 457 }() 458 } 459 460 m = &mountedLayer{ 461 name: name, 462 parent: p, 463 mountID: ls.mountID(name), 464 layerStore: ls, 465 references: map[RWLayer]*referencedRWLayer{}, 466 } 467 468 if initFunc != nil { 469 pid, err = ls.initMount(m.mountID, pid, mountLabel, initFunc, storageOpt) 470 if err != nil { 471 return nil, err 472 } 473 m.initID = pid 474 } 475 476 if err = ls.driver.CreateReadWrite(m.mountID, pid, "", storageOpt); err != nil { 477 return nil, err 478 } 479 480 if err = ls.saveMount(m); err != nil { 481 return nil, err 482 } 483 484 return m.getReference(), nil 485 } 486 487 func (ls *layerStore) GetRWLayer(id string) (RWLayer, error) { 488 ls.mountL.Lock() 489 defer ls.mountL.Unlock() 490 mount, ok := ls.mounts[id] 491 if !ok { 492 return nil, ErrMountDoesNotExist 493 } 494 495 return mount.getReference(), nil 496 } 497 498 func (ls *layerStore) GetMountID(id string) (string, error) { 499 ls.mountL.Lock() 500 defer ls.mountL.Unlock() 501 mount, ok := ls.mounts[id] 502 if !ok { 503 return "", ErrMountDoesNotExist 504 } 505 logrus.Debugf("GetMountID id: %s -> mountID: %s", id, mount.mountID) 506 507 return mount.mountID, nil 508 } 509 510 func (ls *layerStore) ReleaseRWLayer(l RWLayer) ([]Metadata, error) { 511 ls.mountL.Lock() 512 defer ls.mountL.Unlock() 513 m, ok := ls.mounts[l.Name()] 514 if !ok { 515 return []Metadata{}, nil 516 } 517 518 if err := m.deleteReference(l); err != nil { 519 return nil, err 520 } 521 522 if m.hasReferences() { 523 return []Metadata{}, nil 524 } 525 526 if err := ls.driver.Remove(m.mountID); err != nil { 527 logrus.Errorf("Error removing mounted layer %s: %s", m.name, err) 528 m.retakeReference(l) 529 return nil, err 530 } 531 532 if m.initID != "" { 533 if err := ls.driver.Remove(m.initID); err != nil { 534 logrus.Errorf("Error removing init layer %s: %s", m.name, err) 535 m.retakeReference(l) 536 return nil, err 537 } 538 } 539 540 if err := ls.store.RemoveMount(m.name); err != nil { 541 logrus.Errorf("Error removing mount metadata: %s: %s", m.name, err) 542 m.retakeReference(l) 543 return nil, err 544 } 545 546 delete(ls.mounts, m.Name()) 547 548 ls.layerL.Lock() 549 defer ls.layerL.Unlock() 550 if m.parent != nil { 551 return ls.releaseLayer(m.parent) 552 } 553 554 return []Metadata{}, nil 555 } 556 557 func (ls *layerStore) saveMount(mount *mountedLayer) error { 558 if err := ls.store.SetMountID(mount.name, mount.mountID); err != nil { 559 return err 560 } 561 562 if mount.initID != "" { 563 if err := ls.store.SetInitID(mount.name, mount.initID); err != nil { 564 return err 565 } 566 } 567 568 if mount.parent != nil { 569 if err := ls.store.SetMountParent(mount.name, mount.parent.chainID); err != nil { 570 return err 571 } 572 } 573 574 ls.mounts[mount.name] = mount 575 576 return nil 577 } 578 579 func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc MountInit, storageOpt map[string]string) (string, error) { 580 // Use "<graph-id>-init" to maintain compatibility with graph drivers 581 // which are expecting this layer with this special name. If all 582 // graph drivers can be updated to not rely on knowing about this layer 583 // then the initID should be randomly generated. 584 initID := fmt.Sprintf("%s-init", graphID) 585 586 if err := ls.driver.Create(initID, parent, mountLabel, storageOpt); err != nil { 587 return "", err 588 } 589 p, err := ls.driver.Get(initID, "") 590 if err != nil { 591 return "", err 592 } 593 594 if err := initFunc(p); err != nil { 595 ls.driver.Put(initID) 596 return "", err 597 } 598 599 if err := ls.driver.Put(initID); err != nil { 600 return "", err 601 } 602 603 return initID, nil 604 } 605 606 func (ls *layerStore) assembleTarTo(graphID string, metadata io.ReadCloser, size *int64, w io.Writer) error { 607 diffDriver, ok := ls.driver.(graphdriver.DiffGetterDriver) 608 if !ok { 609 diffDriver = &naiveDiffPathDriver{ls.driver} 610 } 611 612 defer metadata.Close() 613 614 // get our relative path to the container 615 fileGetCloser, err := diffDriver.DiffGetter(graphID) 616 if err != nil { 617 return err 618 } 619 defer fileGetCloser.Close() 620 621 metaUnpacker := storage.NewJSONUnpacker(metadata) 622 upackerCounter := &unpackSizeCounter{metaUnpacker, size} 623 logrus.Debugf("Assembling tar data for %s", graphID) 624 return asm.WriteOutputTarStream(fileGetCloser, upackerCounter, w) 625 } 626 627 func (ls *layerStore) Cleanup() error { 628 return ls.driver.Cleanup() 629 } 630 631 func (ls *layerStore) DriverStatus() [][2]string { 632 return ls.driver.Status() 633 } 634 635 func (ls *layerStore) DriverName() string { 636 return ls.driver.String() 637 } 638 639 type naiveDiffPathDriver struct { 640 graphdriver.Driver 641 } 642 643 type fileGetPutter struct { 644 storage.FileGetter 645 driver graphdriver.Driver 646 id string 647 } 648 649 func (w *fileGetPutter) Close() error { 650 return w.driver.Put(w.id) 651 } 652 653 func (n *naiveDiffPathDriver) DiffGetter(id string) (graphdriver.FileGetCloser, error) { 654 p, err := n.Driver.Get(id, "") 655 if err != nil { 656 return nil, err 657 } 658 return &fileGetPutter{storage.NewPathFileGetter(p), n.Driver, id}, nil 659 }