From 384c325d7bdce142fab7654672dbd1157ae9f587 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 23 Oct 2024 13:50:48 +0200 Subject: [PATCH 1/3] composefs: remove \n from fsconfig_create error Signed-off-by: Giuseppe Scrivano --- drivers/overlay/composefs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/overlay/composefs.go b/drivers/overlay/composefs.go index db302dde0f..65fc3fe806 100644 --- a/drivers/overlay/composefs.go +++ b/drivers/overlay/composefs.go @@ -172,7 +172,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) } From dceaef71501a5ed340f38335869d55f33a30261d Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 23 Oct 2024 13:52:40 +0200 Subject: [PATCH 2/3] composefs: refactor openComposefsMount preparation for the next commit Signed-off-by: Giuseppe Scrivano --- drivers/overlay/composefs.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/overlay/composefs.go b/drivers/overlay/composefs.go index 65fc3fe806..6dd28f85de 100644 --- a/drivers/overlay/composefs.go +++ b/drivers/overlay/composefs.go @@ -136,19 +136,13 @@ 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) +func openBlobFile(blobFile string, hasACL bool) (int, error) { loop, err := loopback.AttachLoopDeviceRO(blobFile) if err != nil { return -1, err } defer loop.Close() - hasACL, err := hasACL(blobFile) - if err != nil { - return -1, err - } - fsfd, err := unix.Fsopen("erofs", 0) if err != nil { return -1, fmt.Errorf("failed to open erofs filesystem: %w", err) @@ -188,6 +182,17 @@ 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 + } + + return openBlobFile(blobFile, hasACL) +} + func mountComposefsBlob(dataDir, mountPoint string) error { mfd, err := openComposefsMount(dataDir) if err != nil { From db1be7432ae125d5c06e4b4c60db107e57c815b6 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 23 Oct 2024 14:03:48 +0200 Subject: [PATCH 3/3] composefs: use mount from file where supported https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fb176750266a3d7f42ebdcf28e8ba40350b27847 adds the possibility to mount a EROFS file system directly from its backing file instead of using a loopback device. Signed-off-by: Giuseppe Scrivano --- drivers/overlay/composefs.go | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/overlay/composefs.go b/drivers/overlay/composefs.go index 6dd28f85de..a8f28e153a 100644 --- a/drivers/overlay/composefs.go +++ b/drivers/overlay/composefs.go @@ -12,6 +12,7 @@ import ( "path/filepath" "strings" "sync" + "sync/atomic" "github.com/containers/storage/pkg/chunked/dump" "github.com/containers/storage/pkg/fsverity" @@ -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) { @@ -136,12 +141,16 @@ func hasACL(path string) (bool, error) { return binary.LittleEndian.Uint32(flags)&LCFS_EROFS_FLAGS_HAS_ACL != 0, nil } -func openBlobFile(blobFile string, hasACL bool) (int, error) { - loop, err := loopback.AttachLoopDeviceRO(blobFile) - if err != nil { - return -1, err +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() + + blobFile = loop.Name() } - defer loop.Close() fsfd, err := unix.Fsopen("erofs", 0) if err != nil { @@ -149,7 +158,7 @@ func openBlobFile(blobFile string, hasACL bool) (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) } @@ -190,7 +199,16 @@ func openComposefsMount(dataDir string) (int, error) { return -1, err } - return openBlobFile(blobFile, hasACL) + 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 {