@@ -54,170 +54,177 @@ type compressor func(dest io.Writer, requiredMediaType string) (io.WriteCloser,
5454
5555func computeBlobChain (ctx context.Context , sr * immutableRef , createIfNeeded bool , compressionType compression.Type , forceCompression bool , s session.Group ) error {
5656 eg , ctx := errgroup .WithContext (ctx )
57- if sr .parent != nil {
57+ switch sr .kind () {
58+ case Merge :
59+ for _ , parent := range sr .mergeParents {
60+ parent := parent
61+ eg .Go (func () error {
62+ return computeBlobChain (ctx , parent , createIfNeeded , compressionType , forceCompression , s )
63+ })
64+ }
65+ case Layer :
5866 eg .Go (func () error {
59- return computeBlobChain (ctx , sr .parent , createIfNeeded , compressionType , forceCompression , s )
67+ return computeBlobChain (ctx , sr .layerParent , createIfNeeded , compressionType , forceCompression , s )
6068 })
61- }
62-
63- eg .Go (func () error {
64- _ , err := g .Do (ctx , fmt .Sprintf ("%s-%t" , sr .ID (), createIfNeeded ), func (ctx context.Context ) (interface {}, error ) {
65- if sr .getBlob () != "" {
66- return nil , nil
67- }
68- if ! createIfNeeded {
69- return nil , errors .WithStack (ErrNoBlobs )
70- }
69+ fallthrough
70+ case BaseLayer :
71+ eg .Go (func () error {
72+ _ , err := g .Do (ctx , fmt .Sprintf ("%s-%t" , sr .ID (), createIfNeeded ), func (ctx context.Context ) (interface {}, error ) {
73+ if sr .getBlob () != "" {
74+ return nil , nil
75+ }
76+ if ! createIfNeeded {
77+ return nil , errors .WithStack (ErrNoBlobs )
78+ }
7179
72- var mediaType string
73- var compressorFunc compressor
74- var finalize func (context.Context , content.Store ) (map [string ]string , error )
75- switch compressionType {
76- case compression .Uncompressed :
77- mediaType = ocispecs .MediaTypeImageLayer
78- case compression .Gzip :
79- mediaType = ocispecs .MediaTypeImageLayerGzip
80- case compression .EStargz :
81- compressorFunc , finalize = compressEStargz ()
82- mediaType = ocispecs .MediaTypeImageLayerGzip
83- case compression .Zstd :
84- compressorFunc = zstdWriter
85- mediaType = ocispecs .MediaTypeImageLayer + "+zstd"
86- default :
87- return nil , errors .Errorf ("unknown layer compression type: %q" , compressionType )
88- }
80+ var mediaType string
81+ var compressorFunc compressor
82+ var finalize func (context.Context , content.Store ) (map [string ]string , error )
83+ switch compressionType {
84+ case compression .Uncompressed :
85+ mediaType = ocispecs .MediaTypeImageLayer
86+ case compression .Gzip :
87+ mediaType = ocispecs .MediaTypeImageLayerGzip
88+ case compression .EStargz :
89+ compressorFunc , finalize = compressEStargz ()
90+ mediaType = ocispecs .MediaTypeImageLayerGzip
91+ case compression .Zstd :
92+ compressorFunc = zstdWriter
93+ mediaType = ocispecs .MediaTypeImageLayer + "+zstd"
94+ default :
95+ return nil , errors .Errorf ("unknown layer compression type: %q" , compressionType )
96+ }
8997
90- var lower []mount.Mount
91- if sr .parent != nil {
92- m , err := sr .parent .Mount (ctx , true , s )
98+ var lower []mount.Mount
99+ if sr .layerParent != nil {
100+ m , err := sr .layerParent .Mount (ctx , true , s )
101+ if err != nil {
102+ return nil , err
103+ }
104+ var release func () error
105+ lower , release , err = m .Mount ()
106+ if err != nil {
107+ return nil , err
108+ }
109+ if release != nil {
110+ defer release ()
111+ }
112+ }
113+ m , err := sr .Mount (ctx , true , s )
93114 if err != nil {
94115 return nil , err
95116 }
96- var release func () error
97- lower , release , err = m .Mount ()
117+ upper , release , err := m .Mount ()
98118 if err != nil {
99119 return nil , err
100120 }
101121 if release != nil {
102122 defer release ()
103123 }
104- }
105- m , err := sr .Mount (ctx , true , s )
106- if err != nil {
107- return nil , err
108- }
109- upper , release , err := m .Mount ()
110- if err != nil {
111- return nil , err
112- }
113- if release != nil {
114- defer release ()
115- }
116- var desc ocispecs.Descriptor
117-
118- // Determine differ and error/log handling according to the platform, envvar and the snapshotter.
119- var enableOverlay , fallback , logWarnOnErr bool
120- if forceOvlStr := os .Getenv ("BUILDKIT_DEBUG_FORCE_OVERLAY_DIFF" ); forceOvlStr != "" {
121- enableOverlay , err = strconv .ParseBool (forceOvlStr )
122- if err != nil {
123- return nil , errors .Wrapf (err , "invalid boolean in BUILDKIT_DEBUG_FORCE_OVERLAY_DIFF" )
124- }
125- fallback = false // prohibit fallback on debug
126- } else if ! isTypeWindows (sr ) {
127- enableOverlay , fallback = true , true
128- switch sr .cm .ManagerOpt .Snapshotter .Name () {
129- case "overlayfs" , "stargz" :
130- // overlayfs-based snapshotters should support overlay diff. so print warn log on failure.
131- logWarnOnErr = true
132- case "fuse-overlayfs" :
133- // not supported with fuse-overlayfs snapshotter which doesn't provide overlayfs mounts.
134- // TODO: add support for fuse-overlayfs
135- enableOverlay = false
124+ var desc ocispecs.Descriptor
125+
126+ // Determine differ and error/log handling according to the platform, envvar and the snapshotter.
127+ var enableOverlay , fallback , logWarnOnErr bool
128+ if forceOvlStr := os .Getenv ("BUILDKIT_DEBUG_FORCE_OVERLAY_DIFF" ); forceOvlStr != "" {
129+ enableOverlay , err = strconv .ParseBool (forceOvlStr )
130+ if err != nil {
131+ return nil , errors .Wrapf (err , "invalid boolean in BUILDKIT_DEBUG_FORCE_OVERLAY_DIFF" )
132+ }
133+ fallback = false // prohibit fallback on debug
134+ } else if ! isTypeWindows (sr ) {
135+ enableOverlay , fallback = true , true
136+ switch sr .cm .Snapshotter .Name () {
137+ case "overlayfs" , "stargz" :
138+ // overlayfs-based snapshotters should support overlay diff. so print warn log on failure.
139+ logWarnOnErr = true
140+ case "fuse-overlayfs" :
141+ // not supported with fuse-overlayfs snapshotter which doesn't provide overlayfs mounts.
142+ // TODO: add support for fuse-overlayfs
143+ enableOverlay = false
144+ }
136145 }
137- }
138- if enableOverlay {
139- computed , ok , err := sr .tryComputeOverlayBlob (ctx , lower , upper , mediaType , sr .ID (), compressorFunc )
140- if ! ok || err != nil {
141- if ! fallback {
142- if ! ok {
143- return nil , errors .Errorf ("overlay mounts not detected (lower=%+v,upper=%+v)" , lower , upper )
146+ if enableOverlay {
147+ computed , ok , err := sr .tryComputeOverlayBlob (ctx , lower , upper , mediaType , sr .ID (), compressorFunc )
148+ if ! ok || err != nil {
149+ if ! fallback {
150+ if ! ok {
151+ return nil , errors .Errorf ("overlay mounts not detected (lower=%+v,upper=%+v)" , lower , upper )
152+ }
153+ if err != nil {
154+ return nil , errors .Wrapf (err , "failed to compute overlay diff" )
155+ }
144156 }
145- if err != nil {
146- return nil , errors . Wrapf ( err , "failed to compute overlay diff" )
157+ if logWarnOnErr {
158+ logrus . Warnf ( "failed to compute blob by overlay differ (ok=%v): %v" , ok , err )
147159 }
148160 }
149- if logWarnOnErr {
150- logrus . Warnf ( "failed to compute blob by overlay differ (ok=%v): %v" , ok , err )
161+ if ok {
162+ desc = computed
151163 }
152164 }
153- if ok {
154- desc = computed
165+
166+ if desc .Digest == "" {
167+ desc , err = sr .cm .Differ .Compare (ctx , lower , upper ,
168+ diff .WithMediaType (mediaType ),
169+ diff .WithReference (sr .ID ()),
170+ diff .WithCompressor (compressorFunc ),
171+ )
172+ if err != nil {
173+ return nil , err
174+ }
155175 }
156- }
157176
158- if desc .Digest == "" {
159- desc , err = sr .cm .Differ .Compare (ctx , lower , upper ,
160- diff .WithMediaType (mediaType ),
161- diff .WithReference (sr .ID ()),
162- diff .WithCompressor (compressorFunc ),
163- )
177+ if desc .Annotations == nil {
178+ desc .Annotations = map [string ]string {}
179+ }
180+ if finalize != nil {
181+ a , err := finalize (ctx , sr .cm .ContentStore )
182+ if err != nil {
183+ return nil , errors .Wrapf (err , "failed to finalize compression" )
184+ }
185+ for k , v := range a {
186+ desc .Annotations [k ] = v
187+ }
188+ }
189+ info , err := sr .cm .ContentStore .Info (ctx , desc .Digest )
164190 if err != nil {
165191 return nil , err
166192 }
167- }
168193
169- if desc .Annotations == nil {
170- desc .Annotations = map [string ]string {}
171- }
172- if finalize != nil {
173- a , err := finalize (ctx , sr .cm .ContentStore )
174- if err != nil {
175- return nil , errors .Wrapf (err , "failed to finalize compression" )
194+ if diffID , ok := info .Labels [containerdUncompressed ]; ok {
195+ desc .Annotations [containerdUncompressed ] = diffID
196+ } else if mediaType == ocispecs .MediaTypeImageLayer {
197+ desc .Annotations [containerdUncompressed ] = desc .Digest .String ()
198+ } else {
199+ return nil , errors .Errorf ("unknown layer compression type" )
176200 }
177- for k , v := range a {
178- desc .Annotations [k ] = v
179- }
180- }
181201
182- info , err := sr .cm .ContentStore .Info (ctx , desc .Digest )
202+ if err := sr .setBlob (ctx , compressionType , desc ); err != nil {
203+ return nil , err
204+ }
205+ return nil , nil
206+ })
183207 if err != nil {
184- return nil , err
208+ return err
185209 }
186210
187- if diffID , ok := info .Labels [containerdUncompressed ]; ok {
188- desc .Annotations [containerdUncompressed ] = diffID
189- } else if mediaType == ocispecs .MediaTypeImageLayer {
190- desc .Annotations [containerdUncompressed ] = desc .Digest .String ()
191- } else {
192- return nil , errors .Errorf ("unknown layer compression type" )
193- }
194-
195- if err := sr .setBlob (ctx , compressionType , desc ); err != nil {
196- return nil , err
211+ if forceCompression {
212+ if err := ensureCompression (ctx , sr , compressionType , s ); err != nil {
213+ return errors .Wrapf (err , "failed to ensure compression type of %q" , compressionType )
214+ }
197215 }
198-
199- return nil , nil
216+ return nil
200217 })
201- if err != nil {
202- return err
203- }
204- if forceCompression {
205- if err := ensureCompression (ctx , sr , compressionType , s ); err != nil {
206- return errors .Wrapf (err , "failed to ensure compression type of %q" , compressionType )
207- }
208- }
209- return nil
210- })
218+ }
211219
212220 if err := eg .Wait (); err != nil {
213221 return err
214222 }
215- return sr .setChains (ctx )
223+ return sr .computeChainMetadata (ctx )
216224}
217225
218226// setBlob associates a blob with the cache record.
219227// A lease must be held for the blob when calling this function
220- // Caller should call Info() for knowing what current values are actually set
221228func (sr * immutableRef ) setBlob (ctx context.Context , compressionType compression.Type , desc ocispecs.Descriptor ) error {
222229 if _ , ok := leases .FromContext (ctx ); ! ok {
223230 return errors .Errorf ("missing lease requirement for setBlob" )
@@ -267,9 +274,9 @@ func (sr *immutableRef) setBlob(ctx context.Context, compressionType compression
267274 return nil
268275}
269276
270- func (sr * immutableRef ) setChains (ctx context.Context ) error {
277+ func (sr * immutableRef ) computeChainMetadata (ctx context.Context ) error {
271278 if _ , ok := leases .FromContext (ctx ); ! ok {
272- return errors .Errorf ("missing lease requirement for setChains " )
279+ return errors .Errorf ("missing lease requirement for computeChainMetadata " )
273280 }
274281
275282 sr .mu .Lock ()
@@ -281,13 +288,37 @@ func (sr *immutableRef) setChains(ctx context.Context) error {
281288
282289 var chainIDs []digest.Digest
283290 var blobChainIDs []digest.Digest
284- if sr .parent != nil {
285- chainIDs = append (chainIDs , digest .Digest (sr .parent .getChainID ()))
286- blobChainIDs = append (blobChainIDs , digest .Digest (sr .parent .getBlobChainID ()))
291+
292+ // Blobs should be set the actual layers in the ref's chain, no
293+ // any merge refs.
294+ layerChain := sr .layerChain ()
295+ var layerParent * cacheRecord
296+ switch sr .kind () {
297+ case Merge :
298+ layerParent = layerChain [len (layerChain )- 1 ].cacheRecord
299+ case Layer :
300+ // skip the last layer in the chain, which is this ref itself
301+ layerParent = layerChain [len (layerChain )- 2 ].cacheRecord
302+ }
303+ if layerParent != nil {
304+ if parentChainID := layerParent .getChainID (); parentChainID != "" {
305+ chainIDs = append (chainIDs , parentChainID )
306+ } else {
307+ return errors .Errorf ("failed to set chain for reference with non-addressable parent" )
308+ }
309+ if parentBlobChainID := layerParent .getBlobChainID (); parentBlobChainID != "" {
310+ blobChainIDs = append (blobChainIDs , parentBlobChainID )
311+ } else {
312+ return errors .Errorf ("failed to set blobchain for reference with non-addressable parent" )
313+ }
314+ }
315+
316+ switch sr .kind () {
317+ case Layer , BaseLayer :
318+ diffID := digest .Digest (sr .getDiffID ())
319+ chainIDs = append (chainIDs , diffID )
320+ blobChainIDs = append (blobChainIDs , imagespecidentity .ChainID ([]digest.Digest {digest .Digest (sr .getBlob ()), diffID }))
287321 }
288- diffID := digest .Digest (sr .getDiffID ())
289- chainIDs = append (chainIDs , diffID )
290- blobChainIDs = append (blobChainIDs , imagespecidentity .ChainID ([]digest.Digest {digest .Digest (sr .getBlob ()), diffID }))
291322
292323 chainID := imagespecidentity .ChainID (chainIDs )
293324 blobChainID := imagespecidentity .ChainID (blobChainIDs )
@@ -304,8 +335,15 @@ func isTypeWindows(sr *immutableRef) bool {
304335 if sr .GetLayerType () == "windows" {
305336 return true
306337 }
307- if parent := sr .parent ; parent != nil {
308- return isTypeWindows (parent )
338+ switch sr .kind () {
339+ case Merge :
340+ for _ , p := range sr .mergeParents {
341+ if isTypeWindows (p ) {
342+ return true
343+ }
344+ }
345+ case Layer :
346+ return isTypeWindows (sr .layerParent )
309347 }
310348 return false
311349}
0 commit comments