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