Skip to content

Commit

Permalink
cmd/convertor: support --fstype=erofs for TurboOCI format
Browse files Browse the repository at this point in the history
Similiar to EXT4 which uses "ext4.fs.meta", add EROFS metadata
"erofs.fs.meta" support too.  Multiple metadata could exist in
each TurboOCI layer, but let's make single fs metadata work first.

To build a EROFS TurboOCI image,
$ bin/convertor --fstype erofs -r <repo> -i <input-tag> --turboOCI <turboOCI-tag>

If `--fstype` is not given, ext4 is used by default.

Signed-off-by: Gao Xiang <[email protected]>
  • Loading branch information
hsiangkao committed Jun 27, 2024
1 parent daacefc commit 5352e62
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 11 deletions.
2 changes: 2 additions & 0 deletions cmd/convertor/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type BuilderOptions struct {
PlainHTTP bool
WorkDir string
OCI bool
FsType string
Mkfs bool
Vsize int
DB database.ConversionDatabase
Expand Down Expand Up @@ -234,6 +235,7 @@ func (b *graphBuilder) buildOne(ctx context.Context, src v1.Descriptor, tag bool
}
engineBase.workDir = workdir
engineBase.oci = b.OCI
engineBase.fstype = b.FsType
engineBase.mkfs = b.Mkfs
engineBase.vsize = b.Vsize
engineBase.db = b.DB
Expand Down
1 change: 1 addition & 0 deletions cmd/convertor/builder/builder_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ type builderEngineBase struct {
config specs.Image
workDir string
oci bool
fstype string
mkfs bool
vsize int
db database.ConversionDatabase
Expand Down
21 changes: 17 additions & 4 deletions cmd/convertor/builder/turboOCI_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const (
gzipMetaFile = "gzip.meta"

// index of block device
fsMetaFile = "ext4.fs.meta"
fsMetaFileSuffix = ".fs.meta"

// foci index layer (gzip)
tociLayerTar = "turboOCIv1.tar.gz"
Expand Down Expand Up @@ -103,12 +103,21 @@ func (e *turboOCIBuilderEngine) BuildLayer(ctx context.Context, idx int) error {
if err := e.apply(ctx, layerDir); err != nil {
return err
}
if err := e.commit(ctx, layerDir); err != nil {

var fsMetaFile string
if e.fstype == "" {
fsMetaFile = "ext4" + fsMetaFileSuffix
} else {
fsMetaFile = e.fstype + fsMetaFileSuffix
}

if err := e.commit(ctx, layerDir, fsMetaFile); err != nil {
return err
}
if err := e.createIdentifier(idx); err != nil {
return errors.Wrapf(err, "failed to create identifier %q", tociIdentifier)
}

files := []string{
path.Join(layerDir, fsMetaFile),
path.Join(layerDir, tociIdentifier),
Expand Down Expand Up @@ -249,18 +258,22 @@ func (e *turboOCIBuilderEngine) create(ctx context.Context, dir string, mkfs boo
vsizeGB = e.vsize
}
opts := []string{"-s", fmt.Sprintf("%d", vsizeGB), "--turboOCI"}
if mkfs {
if mkfs && e.fstype != "erofs" {
opts = append(opts, "--mkfs")
logrus.Infof("mkfs for baselayer, vsize: %d GB", vsizeGB)
}
return utils.Create(ctx, dir, opts...)
}

func (e *turboOCIBuilderEngine) apply(ctx context.Context, dir string) error {
if e.fstype != "" {
opts := []string{"--fstype", e.fstype}
return utils.ApplyTurboOCI(ctx, dir, gzipMetaFile, opts...)
}
return utils.ApplyTurboOCI(ctx, dir, gzipMetaFile)
}

func (e *turboOCIBuilderEngine) commit(ctx context.Context, dir string) error {
func (e *turboOCIBuilderEngine) commit(ctx context.Context, dir string, fsMetaFile string) error {
if err := utils.Commit(ctx, dir, dir, false, "-z", "--fastoci"); err != nil {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/convertor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ var (
tagOutput string
dir string
oci bool
fsType string
mkfs bool
verbose bool
vsize int
Expand Down Expand Up @@ -93,6 +94,7 @@ Version: ` + commitID,
PlainHTTP: plain,
WorkDir: dir,
OCI: oci,
FsType: fsType,
Mkfs: mkfs,
Vsize: vsize,
CertOption: builder.CertOption{
Expand Down Expand Up @@ -159,6 +161,7 @@ func init() {
rootCmd.Flags().StringVarP(&tagOutput, "output-tag", "o", "", "tag for image converting to")
rootCmd.Flags().StringVarP(&dir, "dir", "d", "tmp_conv", "directory used for temporary data")
rootCmd.Flags().BoolVarP(&oci, "oci", "", false, "export image with oci spec")
rootCmd.Flags().StringVar(&fsType, "fstype", "ext4", "filesystem type of converted image. Default ext4")
rootCmd.Flags().BoolVarP(&mkfs, "mkfs", "", true, "make ext4 fs in bottom layer")
rootCmd.Flags().IntVarP(&vsize, "vsize", "", 64, "virtual block device size (GB)")
rootCmd.Flags().StringVar(&fastoci, "fastoci", "", "build 'Overlaybd-Turbo OCIv1' format (old name of turboOCIv1. deprecated)")
Expand Down
23 changes: 18 additions & 5 deletions pkg/snapshot/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,12 @@ func (o *snapshotter) createMountPoint(ctx context.Context, kind snapshots.Kind,
}
fsType, ok := obdInfo.Labels[label.OverlayBDBlobFsType]
if !ok {
log.G(ctx).Warnf("cannot get fs type from label, %v, using %s", obdInfo.Labels, o.defaultFsType)
fsType = o.defaultFsType
if isTurboOCI, _, _ := o.checkTurboOCI(obdInfo.Labels); isTurboOCI {
_, fsType = o.turboOCIFsMeta(obdID)
} else {
fsType = o.defaultFsType
}
log.G(ctx).Warnf("cannot get fs type from label, %v, using %s", obdInfo.Labels, fsType)
}
log.G(ctx).Debugf("attachAndMountBlockDevice (obdID: %s, writeType: %s, fsType %s, targetPath: %s)",
obdID, writeType, fsType, o.overlaybdTargetPath(obdID))
Expand Down Expand Up @@ -733,7 +737,11 @@ func (o *snapshotter) Mounts(ctx context.Context, key string) (_ []mount.Mount,
if parentStype == storageTypeRemoteBlock || parentStype == storageTypeLocalBlock {
fsType, ok := parentInfo.Labels[label.OverlayBDBlobFsType]
if !ok {
fsType = o.defaultFsType
if isTurboOCI, _, _ := o.checkTurboOCI(parentInfo.Labels); isTurboOCI {
_, fsType = o.turboOCIFsMeta(parentID)
} else {
fsType = o.defaultFsType
}
}
if err := o.attachAndMountBlockDevice(ctx, parentID, RoDir, fsType, false); err != nil {
return nil, errors.Wrapf(err, "failed to attach and mount for snapshot %v", key)
Expand Down Expand Up @@ -1355,8 +1363,13 @@ func (o *snapshotter) blockPath(id string) string {
return filepath.Join(o.root, "snapshots", id, "block")
}

func (o *snapshotter) turboOCIFsMeta(id string) string {
return filepath.Join(o.root, "snapshots", id, "fs", "ext4.fs.meta")
func (o *snapshotter) turboOCIFsMeta(id string) (string, string) {
// TODO: make the priority order (multi-meta exists) configurable later if needed
erofsmeta := filepath.Join(o.root, "snapshots", id, "fs", "erofs.fs.meta")
if _, err := os.Stat(erofsmeta); err == nil {
return erofsmeta, "erofs"
}
return filepath.Join(o.root, "snapshots", id, "fs", "ext4.fs.meta"), "ext4"
}

func (o *snapshotter) magicFilePath(id string) string {
Expand Down
3 changes: 2 additions & 1 deletion pkg/snapshot/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,10 +502,11 @@ func (o *snapshotter) constructOverlayBDSpec(ctx context.Context, key string, wr

configJSON.RepoBlobURL = blobPrefixURL
if isTurboOCI, dataDgst, compType := o.checkTurboOCI(info.Labels); isTurboOCI {
fsmeta, _ := o.turboOCIFsMeta(id)
lower := sn.OverlayBDBSConfigLower{
Dir: o.upperPath(id),
// keep this to support ondemand turboOCI loading.
File: o.turboOCIFsMeta(id),
File: fsmeta,
TargetDigest: dataDgst,
}
if isGzipLayerType(compType) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/utils/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func ApplyTurboOCI(ctx context.Context, dir, gzipMetaFile string, opts ...string
path.Join(dir, "config.json"),
"--gz_index_path", path.Join(dir, gzipMetaFile)}, opts...)
log.G(ctx).Debugf("%s %s", obdBinApply, strings.Join(args, " "))
out, err := exec.CommandContext(ctx, obdBinApply, args...).CombinedOutput()
out, err := exec.CommandContext(ctx, obdBinTurboOCIApply, args...).CombinedOutput()
if err != nil {
return errors.Wrapf(err, "failed to overlaybd-apply[turboOCI]: %s", out)
}
Expand Down

0 comments on commit 5352e62

Please sign in to comment.