Skip to content

Commit 37072ac

Browse files
committed
Support overlaybd image format instead of OCI
1 parent 807f5a7 commit 37072ac

1 file changed

Lines changed: 64 additions & 5 deletions

File tree

pkg/snapshot/overlay.go

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,21 @@ func (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
966966

967967
opts = append(opts, snapshots.WithLabels(map[string]string{label.LocalOverlayBDPath: o.overlaybdSealedFilePath(id)}))
968968
}
969+
} else if oinfo.Labels[label.AccelerationLayer] != "yes" {
970+
// Fallback: detect writable overlaybd layers without SupportReadWriteMode label.
971+
// buildkit OCI worker never sets SupportReadWriteMode, so we detect by checking
972+
// whether a backing store config and writable_data file both exist.
973+
if _, err := o.loadBackingStoreConfig(id); err == nil {
974+
if _, statErr := os.Stat(o.overlaybdWritableDataPath(id)); statErr == nil {
975+
if err := o.unmountAndDetachBlockDevice(ctx, id, key); err != nil {
976+
return errors.Wrapf(err, "failed to unmount device for snapshot %s", key)
977+
}
978+
if err := o.sealWritableOverlaybd(ctx, id); err != nil {
979+
return err
980+
}
981+
opts = append(opts, snapshots.WithLabels(map[string]string{label.LocalOverlayBDPath: o.overlaybdSealedFilePath(id)}))
982+
}
983+
}
969984
}
970985

971986
if isOverlaybd, err := zdfs.PrepareOverlayBDSpec(ctx, key, id, o.snPath(id), oinfo, o.snPath); isOverlaybd {
@@ -988,24 +1003,41 @@ func (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
9881003
log.G(ctx).Debugf("Commit info (id: %s, info: %v, stype: %d)", id, info.Labels, stype)
9891004

9901005
// For turboOCI, we need to construct OverlayBD spec after unpacking
991-
// since there could be multiple fs metadata in a turboOCI layer
1006+
// since there could be multiple fs metadata in a turboOCI layer.
1007+
// For normal OCI layers (e.g. ubuntu:22.04 extracted by buildkit OCI worker), tar the upper
1008+
// directory to feed the existing turboOCI conversion pipeline.
1009+
ociLayerConverted := false
9921010
if isTurboOCI, digest, _ := o.checkTurboOCI(info.Labels); isTurboOCI {
9931011
log.G(ctx).Infof("commit turboOCI.v1 layer: (%s, %s)", id, digest)
9941012
if err := o.constructOverlayBDSpec(ctx, name, false); err != nil {
9951013
return errors.Wrapf(err, "failed to construct overlaybd config")
9961014
}
9971015
stype = storageTypeNormal
1016+
} else if stype == storageTypeNormal {
1017+
if err := o.createLayerTarFromUpper(ctx, id); err != nil {
1018+
log.G(ctx).Debugf("skipping overlaybd conversion for snapshot %s: %v", id, err)
1019+
} else {
1020+
stype = storageTypeLocalLayer
1021+
ociLayerConverted = true
1022+
}
9981023
}
9991024

10001025
// Firstly, try to convert an OCIv1 tarball to a turboOCI layer.
10011026
// then change stype to 'storageTypeLocalBlock' which can make it attach a overlaybd block
10021027
if stype == storageTypeLocalLayer {
10031028
// PERFORMANCE WARNING: Converting local layer to turboOCI format
1004-
log.G(ctx).Warnf("Converting local blob to turboOCI layer (sn: %s). This is a heavyweight operation that processes the entire layer and may take significant time.", id)
1029+
log.G(ctx).Warnf("Converting local blob to turboOCI layer (sn: %s)...", id)
10051030
if err := o.constructOverlayBDSpec(ctx, name, false); err != nil {
1006-
return errors.Wrapf(err, "failed to construct overlaybd config")
1031+
if ociLayerConverted {
1032+
log.G(ctx).Warnf("Failed to convert OCI layer to overlaybd for sn %s, falling back: %v", id, err)
1033+
os.Remove(o.overlaybdOCILayerPath(id))
1034+
stype = storageTypeNormal
1035+
} else {
1036+
return errors.Wrapf(err, "failed to construct overlaybd config")
1037+
}
1038+
} else {
1039+
stype = storageTypeLocalBlock
10071040
}
1008-
stype = storageTypeLocalBlock
10091041
}
10101042

10111043
if stype == storageTypeLocalBlock {
@@ -1017,7 +1049,11 @@ func (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
10171049
info.Labels = make(map[string]string)
10181050
}
10191051

1020-
info.Labels[label.LocalOverlayBDPath] = o.overlaybdSealedFilePath(id)
1052+
obdPath := o.overlaybdSealedFilePath(id)
1053+
if _, statErr := os.Stat(obdPath); os.IsNotExist(statErr) {
1054+
obdPath = o.magicFilePath(id)
1055+
}
1056+
info.Labels[label.LocalOverlayBDPath] = obdPath
10211057
delete(info.Labels, label.SupportReadWriteMode)
10221058
info, err = storage.UpdateInfo(ctx, info)
10231059
if err != nil {
@@ -1031,6 +1067,29 @@ func (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
10311067
return t.Commit()
10321068
}
10331069

1070+
// createLayerTarFromUpper creates a layer.tar from the snapshot's upper (fs/) directory.
1071+
// This enables the existing storageTypeLocalLayer → overlaybd conversion path for snapshots
1072+
// that were prepared and committed as plain overlayfs (e.g. OCI base image layers pulled by
1073+
// the buildkit OCI worker). Returns an error if the upper dir is empty or the tar fails.
1074+
func (o *snapshotter) createLayerTarFromUpper(ctx context.Context, id string) error {
1075+
upper := o.upperPath(id)
1076+
entries, err := os.ReadDir(upper)
1077+
if err != nil {
1078+
return fmt.Errorf("cannot read upper dir %s: %w", upper, err)
1079+
}
1080+
if len(entries) == 0 {
1081+
return fmt.Errorf("upper dir %s is empty, nothing to convert", upper)
1082+
}
1083+
tarPath := o.overlaybdOCILayerPath(id)
1084+
log.G(ctx).Infof("creating layer.tar from upper directory for overlaybd conversion (sn: %s)", id)
1085+
cmd := exec.CommandContext(ctx, "tar", "--xattrs", "--xattrs-include=*", "-C", upper, "-cf", tarPath, ".")
1086+
if out, err := cmd.CombinedOutput(); err != nil {
1087+
os.Remove(tarPath)
1088+
return errors.Wrapf(err, "failed to create layer.tar (output: %s)", out)
1089+
}
1090+
return nil
1091+
}
1092+
10341093
func (o *snapshotter) commit(ctx context.Context, name, key string, opts ...snapshots.Opt) (string, snapshots.Info, error) {
10351094
ctx, span := tracing.GetDefaultTracer().Start(ctx, "snapshotter.commit", trace.WithAttributes(
10361095
attribute.String("snapshot_name", name),

0 commit comments

Comments
 (0)