Skip to content

Commit

Permalink
overlay: integrate ComposeFS
Browse files Browse the repository at this point in the history
This commit introduces support for ComposeFS using the EROFS
filesystem to mount the file system metadata.

The current implementation allows each layer to be mounted
individually.

Only images that are using the zstd:chunked and eStargz format can be
used in this way since the metadata is stored in the image itself.

In future support for arbitrary images can be added.

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Jun 20, 2023
1 parent 96ba2e9 commit 8e4e965
Show file tree
Hide file tree
Showing 5 changed files with 290 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
vendor-in-container

NATIVETAGS :=
AUTOTAGS := $(shell ./hack/btrfs_tag.sh) $(shell ./hack/libdm_tag.sh) $(shell ./hack/libsubid_tag.sh)
AUTOTAGS := $(shell ./hack/btrfs_tag.sh) $(shell ./hack/libdm_tag.sh) $(shell ./hack/libsubid_tag.sh) $(shell ./hack/composefs_tag.sh)
BUILDFLAGS := -tags "$(AUTOTAGS) $(TAGS)" $(FLAGS)
GO ?= go
TESTFLAGS := $(shell $(GO) test -race $(BUILDFLAGS) ./pkg/stringutils 2>&1 > /dev/null && echo -race)
Expand Down
20 changes: 20 additions & 0 deletions drivers/overlay/composefs_notsupported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//go:build !linux || !composefs || !cgo
// +build !linux !composefs !cgo

package overlay

import (
"fmt"
)

func composeFsSupported() bool {
return false
}

func generateComposeFsBlob(toc []byte, destFile string) error {
return fmt.Errorf("composefs is not supported")
}

func mountErofsBlob(blobFile, mountPoint string) error {
return fmt.Errorf("composefs is not supported")
}
91 changes: 91 additions & 0 deletions drivers/overlay/composefs_supported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//go:build linux && composefs && cgo
// +build linux,composefs,cgo

package overlay

import (
"fmt"
"os"
"os/exec"
"sync"

"github.com/containers/storage/pkg/loopback"
"golang.org/x/sys/unix"
)

var (
ComposeFsHelperOnce sync.Once
ComposeFsHelperPath string
ComposeFsHelperErr error
)

func getComposeFsHelper() (string, error) {
ComposeFsHelperOnce.Do(func() {
ComposeFsHelperPath, ComposeFsHelperErr = exec.LookPath("composefs-from-json")
})
return ComposeFsHelperPath, ComposeFsHelperErr
}

func composeFsSupported() bool {
_, err := getComposeFsHelper()
return err == nil
}

func generateComposeFsBlob(toc []byte, destFile string) error {
outFd, err := unix.Openat(unix.AT_FDCWD, destFile, unix.O_WRONLY|unix.O_CREAT|unix.O_TRUNC|unix.O_EXCL, 0o644)
if err != nil {
return fmt.Errorf("failed to open output file: %w", err)
}


writerJson, err := getComposeFsHelper()
if err != nil {
return fmt.Errorf("failed to find composefs-from-json: %w", err)
}

err = func() error {
// Use a func to have a scope for the close. This must be closed before
// fsverity can be enabled.
defer unix.Close(outFd)

fd, err := unix.MemfdCreate("json-toc", unix.MFD_ALLOW_SEALING)
if err != nil {
return fmt.Errorf("failed to create memfd: %w", err)
}
defer unix.Close(fd)

if err := unix.Ftruncate(fd, int64(len(toc))); err != nil {
return fmt.Errorf("failed to truncate memfd: %w", err)
}

buf := toc
for len(buf) > 0 {
n, err := unix.Write(fd, buf)
if err != nil {
return fmt.Errorf("failed to write to memfd: %w", err)
}
buf = buf[n:]
}

cmd := exec.Command(writerJson, "--format=erofs", fmt.Sprintf("--out=/proc/self/fd/%d", outFd), fmt.Sprintf("/proc/self/fd/%d", fd))
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to convert json to erofs")
}
return nil
}()
if err != nil {
return err
}
return nil
}

func mountErofsBlob(blobFile, mountPoint string) error {
loop, err := loopback.AttachLoopDevice(blobFile)
if err != nil {
return err
}
defer loop.Close()

return unix.Mount(loop.Name(), mountPoint, "erofs", unix.MS_RDONLY, "")
}
Loading

0 comments on commit 8e4e965

Please sign in to comment.