github.com/xdlianrong208/docker-ce-comments@v17.12.1-ce-rc2+incompatible/components/engine/layer/layer_store.go (about)

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