Skip to content
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

composefs: use mount from file where supported #2145

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 35 additions & 12 deletions drivers/overlay/composefs.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"path/filepath"
"strings"
"sync"
"sync/atomic"

"github.com/containers/storage/pkg/chunked/dump"
"github.com/containers/storage/pkg/fsverity"
Expand All @@ -24,6 +25,10 @@ var (
composeFsHelperOnce sync.Once
composeFsHelperPath string
composeFsHelperErr error

// skipMountViaFile is used to avoid trying to mount EROFS directly via the file if we already know the current kernel
// does not support it. Mounting directly via a file will be supported in kernel 6.12.
skipMountViaFile atomic.Bool
)

func getComposeFsHelper() (string, error) {
Expand Down Expand Up @@ -136,17 +141,15 @@ func hasACL(path string) (bool, error) {
return binary.LittleEndian.Uint32(flags)&LCFS_EROFS_FLAGS_HAS_ACL != 0, nil
}

func openComposefsMount(dataDir string) (int, error) {
blobFile := getComposefsBlob(dataDir)
loop, err := loopback.AttachLoopDeviceRO(blobFile)
if err != nil {
return -1, err
}
defer loop.Close()
func openBlobFile(blobFile string, hasACL, useLoopDevice bool) (int, error) {
if useLoopDevice {
loop, err := loopback.AttachLoopDeviceRO(blobFile)
if err != nil {
return -1, err
}
defer loop.Close()

hasACL, err := hasACL(blobFile)
if err != nil {
return -1, err
blobFile = loop.Name()
}

fsfd, err := unix.Fsopen("erofs", 0)
Expand All @@ -155,7 +158,7 @@ func openComposefsMount(dataDir string) (int, error) {
}
defer unix.Close(fsfd)

if err := unix.FsconfigSetString(fsfd, "source", loop.Name()); err != nil {
if err := unix.FsconfigSetString(fsfd, "source", blobFile); err != nil {
return -1, fmt.Errorf("failed to set source for erofs filesystem: %w", err)
}

Expand All @@ -172,7 +175,7 @@ func openComposefsMount(dataDir string) (int, error) {
if err := unix.FsconfigCreate(fsfd); err != nil {
buffer := make([]byte, 4096)
if n, _ := unix.Read(fsfd, buffer); n > 0 {
return -1, fmt.Errorf("failed to create erofs filesystem: %s: %w", string(buffer[:n]), err)
return -1, fmt.Errorf("failed to create erofs filesystem: %s: %w", strings.TrimSuffix(string(buffer[:n]), "\n"), err)
}
return -1, fmt.Errorf("failed to create erofs filesystem: %w", err)
}
Expand All @@ -188,6 +191,26 @@ func openComposefsMount(dataDir string) (int, error) {
return mfd, nil
}

func openComposefsMount(dataDir string) (int, error) {
blobFile := getComposefsBlob(dataDir)

hasACL, err := hasACL(blobFile)
if err != nil {
return -1, err
}

if !skipMountViaFile.Load() {
fd, err := openBlobFile(blobFile, hasACL, false)
if err == nil || !errors.Is(err, unix.ENOTBLK) {
return fd, err
}
logrus.Debugf("The current kernel doesn't support mounting EROFS directly from a file, fallback to a loopback device")
skipMountViaFile.Store(true)
}

return openBlobFile(blobFile, hasACL, true)
}

func mountComposefsBlob(dataDir, mountPoint string) error {
mfd, err := openComposefsMount(dataDir)
if err != nil {
Expand Down