-
Notifications
You must be signed in to change notification settings - Fork 384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Additional Layer Store] Use TOCDigest as ID of each layer (patch for c/image) #2416
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,11 +94,11 @@ type storageImageDestinationLockProtected struct { | |
blobDiffIDs map[digest.Digest]digest.Digest // Mapping from layer blobsums to their corresponding DiffIDs | ||
indexToTOCDigest map[int]digest.Digest // Mapping from layer index to a TOC Digest, IFF the layer was created/found/reused by TOC digest | ||
|
||
// Layer data: Before commitLayer is called, either at least one of (diffOutputs, blobAdditionalLayer, filenames) | ||
// Layer data: Before commitLayer is called, either at least one of (diffOutputs, indexToAdditionalLayer, filenames) | ||
// should be available; or indexToTOCDigest/blobDiffIDs should be enough to locate an existing c/storage layer. | ||
// They are looked up in the order they are mentioned above. | ||
diffOutputs map[int]*graphdriver.DriverWithDifferOutput // Mapping from layer index to a partially-pulled layer intermediate data | ||
blobAdditionalLayer map[digest.Digest]storage.AdditionalLayer // Mapping from layer blobsums to their corresponding additional layer | ||
diffOutputs map[int]*graphdriver.DriverWithDifferOutput // Mapping from layer index to a partially-pulled layer intermediate data | ||
indexToAdditionalLayer map[int]storage.AdditionalLayer // Mapping from layer index to their corresponding additional layer | ||
// Mapping from layer blobsums to names of files we used to hold them. If set, fileSizes and blobDiffIDs must also be set. | ||
filenames map[digest.Digest]string | ||
// Mapping from layer blobsums to their sizes. If set, filenames and blobDiffIDs must also be set. | ||
|
@@ -145,13 +145,13 @@ func newImageDestination(sys *types.SystemContext, imageRef storageReference) (* | |
}, | ||
indexToStorageID: make(map[int]string), | ||
lockProtected: storageImageDestinationLockProtected{ | ||
indexToAddedLayerInfo: make(map[int]addedLayerInfo), | ||
blobDiffIDs: make(map[digest.Digest]digest.Digest), | ||
indexToTOCDigest: make(map[int]digest.Digest), | ||
diffOutputs: make(map[int]*graphdriver.DriverWithDifferOutput), | ||
blobAdditionalLayer: make(map[digest.Digest]storage.AdditionalLayer), | ||
filenames: make(map[digest.Digest]string), | ||
fileSizes: make(map[digest.Digest]int64), | ||
indexToAddedLayerInfo: make(map[int]addedLayerInfo), | ||
blobDiffIDs: make(map[digest.Digest]digest.Digest), | ||
indexToTOCDigest: make(map[int]digest.Digest), | ||
diffOutputs: make(map[int]*graphdriver.DriverWithDifferOutput), | ||
indexToAdditionalLayer: make(map[int]storage.AdditionalLayer), | ||
filenames: make(map[digest.Digest]string), | ||
fileSizes: make(map[digest.Digest]int64), | ||
}, | ||
} | ||
dest.Compat = impl.AddCompat(dest) | ||
|
@@ -167,7 +167,7 @@ func (s *storageImageDestination) Reference() types.ImageReference { | |
// Close cleans up the temporary directory and additional layer store handlers. | ||
func (s *storageImageDestination) Close() error { | ||
// This is outside of the scope of HasThreadSafePutBlob, so we don’t need to hold s.lock. | ||
for _, al := range s.lockProtected.blobAdditionalLayer { | ||
for _, al := range s.lockProtected.indexToAdditionalLayer { | ||
al.Release() | ||
} | ||
for _, v := range s.lockProtected.diffOutputs { | ||
|
@@ -382,14 +382,18 @@ func (s *storageImageDestination) tryReusingBlobAsPending(blobDigest digest.Dige | |
s.lock.Lock() | ||
defer s.lock.Unlock() | ||
|
||
if options.SrcRef != nil { | ||
if options.SrcRef != nil && options.TOCDigest != "" && options.LayerIndex != nil { | ||
// Check if we have the layer in the underlying additional layer store. | ||
aLayer, err := s.imageRef.transport.store.LookupAdditionalLayer(blobDigest, options.SrcRef.String()) | ||
aLayer, err := s.imageRef.transport.store.LookupAdditionalLayer(options.TOCDigest, options.SrcRef.String()) | ||
if err != nil && !errors.Is(err, storage.ErrLayerUnknown) { | ||
return false, private.ReusedBlob{}, fmt.Errorf(`looking for compressed layers with digest %q and labels: %w`, blobDigest, err) | ||
} else if err == nil { | ||
s.lockProtected.blobDiffIDs[blobDigest] = aLayer.UncompressedDigest() | ||
s.lockProtected.blobAdditionalLayer[blobDigest] = aLayer | ||
d := aLayer.TOCDigest() | ||
if d == "" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When can this happen? Wouldn’t it be appropriate to pull the layer in the ordinary way, instead of failing? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per the other comment, this can happen if the FUSE server is old and not expecting TOCs at all. |
||
return false, private.ReusedBlob{}, fmt.Errorf(`failed to get TOCDigest of %q: %w`, blobDigest, err) | ||
} | ||
s.lockProtected.indexToTOCDigest[*options.LayerIndex] = d | ||
s.lockProtected.indexToAdditionalLayer[*options.LayerIndex] = aLayer | ||
return true, private.ReusedBlob{ | ||
Digest: blobDigest, | ||
Size: aLayer.CompressedSize(), | ||
|
@@ -804,7 +808,7 @@ func (s *storageImageDestination) createNewLayer(index int, layerDigest digest.D | |
} | ||
|
||
s.lock.Lock() | ||
al, ok := s.lockProtected.blobAdditionalLayer[layerDigest] | ||
al, ok := s.lockProtected.indexToAdditionalLayer[index] | ||
s.lock.Unlock() | ||
if ok { | ||
layer, err := al.PutAs(newLayerID, parentLayer, nil) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -308,7 +308,7 @@ func (s *storageImageSource) LayerInfosForCopy(ctx context.Context, instanceDige | |
return nil, fmt.Errorf("reading layer %q in image %q: %w", layerID, s.image.ID, err) | ||
} | ||
if layer.UncompressedSize < 0 { | ||
return nil, fmt.Errorf("uncompressed size for layer %q is unknown", layerID) | ||
layer.UncompressedSize = -1 | ||
mtrmac marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
mtrmac marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
blobDigest := layer.UncompressedDigest | ||
|
@@ -452,9 +452,12 @@ func (s *storageImageSource) getSize() (int64, error) { | |
if err != nil { | ||
return -1, err | ||
} | ||
if (layer.TOCDigest == "" && layer.UncompressedDigest == "") || layer.UncompressedSize < 0 { | ||
if (layer.TOCDigest == "" && layer.UncompressedDigest == "") || (layer.TOCDigest == "" && layer.UncompressedSize < 0) { | ||
return -1, fmt.Errorf("size for layer %q is unknown, failing getSize()", layerID) | ||
} | ||
if layer.UncompressedSize < 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a TOC-identified layer can have … but, also, note to self: is a new behavior of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The commit says
but we collect all metadata at the time of layer creation ( Actually, in https://github.com/containerd/stargz-snapshotter/pull/1673/files , it is now reported always as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That’s actually fine because that is already conditional on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. … and I don’t know whether |
||
sum = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This means that if there 3 layers, and the middle one has an unknown size, the total returned size of the image is… some value larger than the true size, but the particular value can AFAICS not be reasonably used for anything. Why is that better than returning There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #2428 modifies this to treat the unknown-size layer as zero-size, while returning the size of the other components. |
||
} | ||
sum += layer.UncompressedSize | ||
if layer.Parent == "" { | ||
break | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have passed down the expected TOC digest in
LookupAdditionalLayer
. Would this ever return a different value? If so, what does that mean / what is the guaranteed relationship between the two TOCs?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the implementation in containerd/stargz-snapshotter#1673 , this seems to always return the digest that is used in the FUSE request, i.e. it is exactly the value we passed in … unless the FUSE server is old and does not return the value at all; and in that case we don’t want to use any layers in the ALS — the FUSE server would be looking up a layer with compressed (non-TOC) digest
options.TOCDigest
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#2428 modifies this to only trust
options.TOCDigest
(but to require the one from the ALS to match).