github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/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 11 12 import ( 13 "errors" 14 "io" 15 16 "github.com/Sirupsen/logrus" 17 "github.com/docker/distribution/digest" 18 "github.com/docker/docker/pkg/archive" 19 ) 20 21 var ( 22 // ErrLayerDoesNotExist is used when an operation is 23 // attempted on a layer which does not exist. 24 ErrLayerDoesNotExist = errors.New("layer does not exist") 25 26 // ErrLayerNotRetained is used when a release is 27 // attempted on a layer which is not retained. 28 ErrLayerNotRetained = errors.New("layer not retained") 29 30 // ErrMountDoesNotExist is used when an operation is 31 // attempted on a mount layer which does not exist. 32 ErrMountDoesNotExist = errors.New("mount does not exist") 33 34 // ErrMountNameConflict is used when a mount is attempted 35 // to be created but there is already a mount with the name 36 // used for creation. 37 ErrMountNameConflict = errors.New("mount already exists with name") 38 39 // ErrActiveMount is used when an operation on a 40 // mount is attempted but the layer is still 41 // mounted and the operation cannot be performed. 42 ErrActiveMount = errors.New("mount still active") 43 44 // ErrNotMounted is used when requesting an active 45 // mount but the layer is not mounted. 46 ErrNotMounted = errors.New("not mounted") 47 48 // ErrMaxDepthExceeded is used when a layer is attempted 49 // to be created which would result in a layer depth 50 // greater than the 125 max. 51 ErrMaxDepthExceeded = errors.New("max depth exceeded") 52 53 // ErrNotSupported is used when the action is not supppoted 54 // on the current platform 55 ErrNotSupported = errors.New("not support on this platform") 56 ) 57 58 // ChainID is the content-addressable ID of a layer. 59 type ChainID digest.Digest 60 61 // String returns a string rendition of a layer ID 62 func (id ChainID) String() string { 63 return string(id) 64 } 65 66 // DiffID is the hash of an individual layer tar. 67 type DiffID digest.Digest 68 69 // String returns a string rendition of a layer DiffID 70 func (diffID DiffID) String() string { 71 return string(diffID) 72 } 73 74 // TarStreamer represents an object which may 75 // have its contents exported as a tar stream. 76 type TarStreamer interface { 77 // TarStream returns a tar archive stream 78 // for the contents of a layer. 79 TarStream() (io.ReadCloser, error) 80 } 81 82 // Layer represents a read-only layer 83 type Layer interface { 84 TarStreamer 85 86 // ChainID returns the content hash of the entire layer chain. The hash 87 // chain is made up of DiffID of top layer and all of its parents. 88 ChainID() ChainID 89 90 // DiffID returns the content hash of the layer 91 // tar stream used to create this layer. 92 DiffID() DiffID 93 94 // Parent returns the next layer in the layer chain. 95 Parent() Layer 96 97 // Size returns the size of the entire layer chain. The size 98 // is calculated from the total size of all files in the layers. 99 Size() (int64, error) 100 101 // DiffSize returns the size difference of the top layer 102 // from parent layer. 103 DiffSize() (int64, error) 104 105 // Metadata returns the low level storage metadata associated 106 // with layer. 107 Metadata() (map[string]string, error) 108 } 109 110 // RWLayer represents a layer which is 111 // read and writable 112 type RWLayer interface { 113 TarStreamer 114 115 // Name of mounted layer 116 Name() string 117 118 // Parent returns the layer which the writable 119 // layer was created from. 120 Parent() Layer 121 122 // Mount mounts the RWLayer and returns the filesystem path 123 // the to the writable layer. 124 Mount(mountLabel string) (string, error) 125 126 // Unmount unmounts the RWLayer. This should be called 127 // for every mount. If there are multiple mount calls 128 // this operation will only decrement the internal mount counter. 129 Unmount() error 130 131 // Size represents the size of the writable layer 132 // as calculated by the total size of the files 133 // changed in the mutable layer. 134 Size() (int64, error) 135 136 // Changes returns the set of changes for the mutable layer 137 // from the base layer. 138 Changes() ([]archive.Change, error) 139 140 // Metadata returns the low level metadata for the mutable layer 141 Metadata() (map[string]string, error) 142 } 143 144 // Metadata holds information about a 145 // read-only layer 146 type Metadata struct { 147 // ChainID is the content hash of the layer 148 ChainID ChainID 149 150 // DiffID is the hash of the tar data used to 151 // create the layer 152 DiffID DiffID 153 154 // Size is the size of the layer and all parents 155 Size int64 156 157 // DiffSize is the size of the top layer 158 DiffSize int64 159 } 160 161 // MountInit is a function to initialize a 162 // writable mount. Changes made here will 163 // not be included in the Tar stream of the 164 // RWLayer. 165 type MountInit func(root string) error 166 167 // Store represents a backend for managing both 168 // read-only and read-write layers. 169 type Store interface { 170 Register(io.Reader, ChainID) (Layer, error) 171 Get(ChainID) (Layer, error) 172 Release(Layer) ([]Metadata, error) 173 174 CreateRWLayer(id string, parent ChainID, mountLabel string, initFunc MountInit, storageOpt map[string]string) (RWLayer, error) 175 GetRWLayer(id string) (RWLayer, error) 176 GetMountID(id string) (string, error) 177 ReinitRWLayer(l RWLayer) error 178 ReleaseRWLayer(RWLayer) ([]Metadata, error) 179 180 Cleanup() error 181 DriverStatus() [][2]string 182 DriverName() string 183 } 184 185 // MetadataTransaction represents functions for setting layer metadata 186 // with a single transaction. 187 type MetadataTransaction interface { 188 SetSize(int64) error 189 SetParent(parent ChainID) error 190 SetDiffID(DiffID) error 191 SetCacheID(string) error 192 TarSplitWriter(compressInput bool) (io.WriteCloser, error) 193 194 Commit(ChainID) error 195 Cancel() error 196 String() string 197 } 198 199 // MetadataStore represents a backend for persisting 200 // metadata about layers and providing the metadata 201 // for restoring a Store. 202 type MetadataStore interface { 203 // StartTransaction starts an update for new metadata 204 // which will be used to represent an ID on commit. 205 StartTransaction() (MetadataTransaction, error) 206 207 GetSize(ChainID) (int64, error) 208 GetParent(ChainID) (ChainID, error) 209 GetDiffID(ChainID) (DiffID, error) 210 GetCacheID(ChainID) (string, error) 211 TarSplitReader(ChainID) (io.ReadCloser, error) 212 213 SetMountID(string, string) error 214 SetInitID(string, string) error 215 SetMountParent(string, ChainID) error 216 217 GetMountID(string) (string, error) 218 GetInitID(string) (string, error) 219 GetMountParent(string) (ChainID, error) 220 221 // List returns the full list of referenced 222 // read-only and read-write layers 223 List() ([]ChainID, []string, error) 224 225 Remove(ChainID) error 226 RemoveMount(string) error 227 } 228 229 // CreateChainID returns ID for a layerDigest slice 230 func CreateChainID(dgsts []DiffID) ChainID { 231 return createChainIDFromParent("", dgsts...) 232 } 233 234 func createChainIDFromParent(parent ChainID, dgsts ...DiffID) ChainID { 235 if len(dgsts) == 0 { 236 return parent 237 } 238 if parent == "" { 239 return createChainIDFromParent(ChainID(dgsts[0]), dgsts[1:]...) 240 } 241 // H = "H(n-1) SHA256(n)" 242 dgst := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0]))) 243 return createChainIDFromParent(ChainID(dgst), dgsts[1:]...) 244 } 245 246 // ReleaseAndLog releases the provided layer from the given layer 247 // store, logging any error and release metadata 248 func ReleaseAndLog(ls Store, l Layer) { 249 metadata, err := ls.Release(l) 250 if err != nil { 251 logrus.Errorf("Error releasing layer %s: %v", l.ChainID(), err) 252 } 253 LogReleaseMetadata(metadata) 254 } 255 256 // LogReleaseMetadata logs a metadata array, uses this to 257 // ensure consistent logging for release metadata 258 func LogReleaseMetadata(metadatas []Metadata) { 259 for _, metadata := range metadatas { 260 logrus.Infof("Layer %s cleaned up", metadata.ChainID) 261 } 262 }