github.com/toplink-cn/moby@v0.0.0-20240305205811-460b4aebdf81/layer/layer.go (about)

     1  // Package layer is package for managing read-only
     2  // and read-write mounts on the union file system
     3  // driver. Read-only mounts are referenced using a
     4  // content hash and are protected from mutation in
     5  // the exposed interface. The tar format is used
     6  // to create read-only layers and export both
     7  // read-only and writable layers. The exported
     8  // tar data for a read-only layer should match
     9  // the tar used to create the layer.
    10  package layer // import "github.com/docker/docker/layer"
    11  
    12  import (
    13  	"context"
    14  	"errors"
    15  	"io"
    16  
    17  	"github.com/containerd/log"
    18  	"github.com/docker/distribution"
    19  	"github.com/docker/docker/pkg/archive"
    20  	"github.com/opencontainers/go-digest"
    21  )
    22  
    23  var (
    24  	// ErrLayerDoesNotExist is used when an operation is
    25  	// attempted on a layer which does not exist.
    26  	ErrLayerDoesNotExist = errors.New("layer does not exist")
    27  
    28  	// ErrLayerNotRetained is used when a release is
    29  	// attempted on a layer which is not retained.
    30  	ErrLayerNotRetained = errors.New("layer not retained")
    31  
    32  	// ErrMountDoesNotExist is used when an operation is
    33  	// attempted on a mount layer which does not exist.
    34  	ErrMountDoesNotExist = errors.New("mount does not exist")
    35  
    36  	// ErrMountNameConflict is used when a mount is attempted
    37  	// to be created but there is already a mount with the name
    38  	// used for creation.
    39  	ErrMountNameConflict = errors.New("mount already exists with name")
    40  
    41  	// ErrMaxDepthExceeded is used when a layer is attempted
    42  	// to be created which would result in a layer depth
    43  	// greater than the 125 max.
    44  	ErrMaxDepthExceeded = errors.New("max depth exceeded")
    45  )
    46  
    47  // ChainID is the content-addressable ID of a layer.
    48  type ChainID digest.Digest
    49  
    50  // String returns a string rendition of a layer ID
    51  func (id ChainID) String() string {
    52  	return string(id)
    53  }
    54  
    55  // DiffID is the hash of an individual layer tar.
    56  type DiffID digest.Digest
    57  
    58  // String returns a string rendition of a layer DiffID
    59  func (diffID DiffID) String() string {
    60  	return string(diffID)
    61  }
    62  
    63  // TarStreamer represents an object which may
    64  // have its contents exported as a tar stream.
    65  type TarStreamer interface {
    66  	// TarStream returns a tar archive stream
    67  	// for the contents of a layer.
    68  	TarStream() (io.ReadCloser, error)
    69  }
    70  
    71  // Layer represents a read-only layer
    72  type Layer interface {
    73  	TarStreamer
    74  
    75  	// TarStreamFrom returns a tar archive stream for all the layer chain with
    76  	// arbitrary depth.
    77  	TarStreamFrom(ChainID) (io.ReadCloser, error)
    78  
    79  	// ChainID returns the content hash of the entire layer chain. The hash
    80  	// chain is made up of DiffID of top layer and all of its parents.
    81  	ChainID() ChainID
    82  
    83  	// DiffID returns the content hash of the layer
    84  	// tar stream used to create this layer.
    85  	DiffID() DiffID
    86  
    87  	// Parent returns the next layer in the layer chain.
    88  	Parent() Layer
    89  
    90  	// Size returns the size of the entire layer chain. The size
    91  	// is calculated from the total size of all files in the layers.
    92  	Size() int64
    93  
    94  	// DiffSize returns the size difference of the top layer
    95  	// from parent layer.
    96  	DiffSize() int64
    97  
    98  	// Metadata returns the low level storage metadata associated
    99  	// with layer.
   100  	Metadata() (map[string]string, error)
   101  }
   102  
   103  // RWLayer represents a layer which is
   104  // read and writable
   105  type RWLayer interface {
   106  	TarStreamer
   107  
   108  	// Name of mounted layer
   109  	Name() string
   110  
   111  	// Parent returns the layer which the writable
   112  	// layer was created from.
   113  	Parent() Layer
   114  
   115  	// Mount mounts the RWLayer and returns the filesystem path
   116  	// to the writable layer.
   117  	Mount(mountLabel string) (string, error)
   118  
   119  	// Unmount unmounts the RWLayer. This should be called
   120  	// for every mount. If there are multiple mount calls
   121  	// this operation will only decrement the internal mount counter.
   122  	Unmount() error
   123  
   124  	// Size represents the size of the writable layer
   125  	// as calculated by the total size of the files
   126  	// changed in the mutable layer.
   127  	Size() (int64, error)
   128  
   129  	// Changes returns the set of changes for the mutable layer
   130  	// from the base layer.
   131  	Changes() ([]archive.Change, error)
   132  
   133  	// Metadata returns the low level metadata for the mutable layer
   134  	Metadata() (map[string]string, error)
   135  
   136  	// ApplyDiff applies the diff to the RW layer
   137  	ApplyDiff(diff io.Reader) (int64, error)
   138  }
   139  
   140  // Metadata holds information about a
   141  // read-only layer
   142  type Metadata struct {
   143  	// ChainID is the content hash of the layer
   144  	ChainID ChainID
   145  
   146  	// DiffID is the hash of the tar data used to
   147  	// create the layer
   148  	DiffID DiffID
   149  
   150  	// Size is the size of the layer and all parents
   151  	Size int64
   152  
   153  	// DiffSize is the size of the top layer
   154  	DiffSize int64
   155  }
   156  
   157  // MountInit is a function to initialize a
   158  // writable mount. Changes made here will
   159  // not be included in the Tar stream of the
   160  // RWLayer.
   161  type MountInit func(root string) error
   162  
   163  // CreateRWLayerOpts contains optional arguments to be passed to CreateRWLayer
   164  type CreateRWLayerOpts struct {
   165  	MountLabel string
   166  	InitFunc   MountInit
   167  	StorageOpt map[string]string
   168  }
   169  
   170  // Store represents a backend for managing both
   171  // read-only and read-write layers.
   172  type Store interface {
   173  	Register(io.Reader, ChainID) (Layer, error)
   174  	Get(ChainID) (Layer, error)
   175  	Map() map[ChainID]Layer
   176  	Release(Layer) ([]Metadata, error)
   177  	CreateRWLayer(id string, parent ChainID, opts *CreateRWLayerOpts) (RWLayer, error)
   178  	GetRWLayer(id string) (RWLayer, error)
   179  	GetMountID(id string) (string, error)
   180  	ReleaseRWLayer(RWLayer) ([]Metadata, error)
   181  	Cleanup() error
   182  	DriverStatus() [][2]string
   183  	DriverName() string
   184  }
   185  
   186  // DescribableStore represents a layer store capable of storing
   187  // descriptors for layers.
   188  type DescribableStore interface {
   189  	RegisterWithDescriptor(io.Reader, ChainID, distribution.Descriptor) (Layer, error)
   190  }
   191  
   192  // CreateChainID returns ID for a layerDigest slice
   193  func CreateChainID(dgsts []DiffID) ChainID {
   194  	return createChainIDFromParent("", dgsts...)
   195  }
   196  
   197  func createChainIDFromParent(parent ChainID, dgsts ...DiffID) ChainID {
   198  	if len(dgsts) == 0 {
   199  		return parent
   200  	}
   201  	if parent == "" {
   202  		return createChainIDFromParent(ChainID(dgsts[0]), dgsts[1:]...)
   203  	}
   204  	// H = "H(n-1) SHA256(n)"
   205  	dgst := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0])))
   206  	return createChainIDFromParent(ChainID(dgst), dgsts[1:]...)
   207  }
   208  
   209  // ReleaseAndLog releases the provided layer from the given layer
   210  // store, logging any error and release metadata
   211  func ReleaseAndLog(ls Store, l Layer) {
   212  	metadata, err := ls.Release(l)
   213  	if err != nil {
   214  		log.G(context.TODO()).Errorf("Error releasing layer %s: %v", l.ChainID(), err)
   215  	}
   216  	LogReleaseMetadata(metadata)
   217  }
   218  
   219  // LogReleaseMetadata logs a metadata array, uses this to
   220  // ensure consistent logging for release metadata
   221  func LogReleaseMetadata(metadatas []Metadata) {
   222  	for _, metadata := range metadatas {
   223  		log.G(context.TODO()).Infof("Layer %s cleaned up", metadata.ChainID)
   224  	}
   225  }