overlay coreos/user-patches: Add a patch for app-containers/containerd

Signed-off-by: Krzesimir Nowak <knowak@microsoft.com>
This commit is contained in:
Krzesimir Nowak 2026-02-19 18:25:42 +01:00
parent 0e130f4ac8
commit 634685563d
2 changed files with 231 additions and 0 deletions

View File

@ -0,0 +1,228 @@
From 3d509bcd335b15cece69ebfa117681d2715df930 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Poulin?= <jeromepoulin@gmail.com>
Date: Wed, 26 Nov 2025 18:28:26 -0500
Subject: [PATCH 1/2] core/mount/manager: add tests for WithTemporary option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add tests for the WithTemporary mount activation used by `ctr images mount`.
Covers bind mount and overlay scenarios to catch regressions like #12549.
Signed-off-by: Jérôme Poulin <jeromepoulin@gmail.com>
---
core/mount/manager/manager_linux_test.go | 157 ++++++++++++++++++++++-
1 file changed, 156 insertions(+), 1 deletion(-)
diff --git a/core/mount/manager/manager_linux_test.go b/core/mount/manager/manager_linux_test.go
index 06ab38c2b7b0..b62f3fdc8cf4 100644
--- a/core/mount/manager/manager_linux_test.go
+++ b/core/mount/manager/manager_linux_test.go
@@ -314,6 +314,161 @@ func TestLoopbackOverlay(t *testing.T) {
}
}
+// TestTemporaryMountActivation tests the WithTemporary option used by
+// `ctr images mount`. This verifies the bind mount returned in info.System
+// points to a valid, mounted directory.
+func TestTemporaryMountActivation(t *testing.T) {
+ testutil.RequiresRoot(t)
+ ctx := logtest.WithT(context.Background(), t)
+ ctx = namespaces.WithNamespace(ctx, "test")
+ td := t.TempDir()
+ metadb := filepath.Join(td, "mounts.db")
+ targetdir := filepath.Join(td, "m")
+ db, err := bolt.Open(metadb, 0600, nil)
+ require.NoError(t, err)
+ defer db.Close()
+
+ sourcedir := filepath.Join(td, "source")
+ require.NoError(t, os.MkdirAll(sourcedir, 0755))
+
+ a := fstest.Apply(
+ fstest.CreateFile("/testfile.txt", []byte("test content\n"), 0644),
+ fstest.CreateDir("/testdir", 0755),
+ )
+ require.NoError(t, a.Apply(sourcedir))
+
+ mounts := []mount.Mount{
+ {
+ Type: "bind",
+ Source: sourcedir,
+ Options: []string{"rbind", "ro"},
+ },
+ }
+
+ m, err := NewManager(db, targetdir)
+ require.NoError(t, err)
+
+ ainfo, err := m.Activate(ctx, "temp-mount-test", mounts, mount.WithTemporary)
+ require.NoError(t, err)
+ defer func() {
+ assert.NoError(t, m.Deactivate(ctx, "temp-mount-test"))
+ }()
+
+ require.NotEmpty(t, ainfo.System, "Expected system mounts to be returned")
+
+ require.Len(t, ainfo.System, 1, "Expected exactly one system mount")
+ systemMount := ainfo.System[0]
+ assert.Equal(t, "bind", systemMount.Type, "Expected bind mount type")
+
+ sourceInfo, err := os.Stat(systemMount.Source)
+ require.NoError(t, err, "Bind mount source %q should exist", systemMount.Source)
+ assert.True(t, sourceInfo.IsDir(), "Bind mount source should be a directory")
+
+ testFile := filepath.Join(systemMount.Source, "testfile.txt")
+ content, err := os.ReadFile(testFile)
+ require.NoError(t, err, "Should be able to read test file from bind mount source")
+ assert.Equal(t, "test content\n", string(content), "Test file content should match")
+
+ targetMount := filepath.Join(td, "target")
+ require.NoError(t, os.MkdirAll(targetMount, 0755))
+
+ err = mount.All(ainfo.System, targetMount)
+ require.NoError(t, err, "Should be able to mount system mounts to target")
+ defer testutil.Unmount(t, targetMount)
+
+ targetTestFile := filepath.Join(targetMount, "testfile.txt")
+ targetContent, err := os.ReadFile(targetTestFile)
+ require.NoError(t, err, "Should be able to read test file from target mount")
+ assert.Equal(t, "test content\n", string(targetContent), "Target test file content should match")
+}
+
+// TestTemporaryOverlayMountActivation tests WithTemporary with overlay mounts,
+// which is the more common case for `ctr images mount` with overlay snapshotter.
+func TestTemporaryOverlayMountActivation(t *testing.T) {
+ testutil.RequiresRoot(t)
+ ctx := logtest.WithT(context.Background(), t)
+ ctx = namespaces.WithNamespace(ctx, "test")
+ td := t.TempDir()
+ metadb := filepath.Join(td, "mounts.db")
+ targetdir := filepath.Join(td, "m")
+ db, err := bolt.Open(metadb, 0600, nil)
+ require.NoError(t, err)
+ defer db.Close()
+
+ lower1 := filepath.Join(td, "lower1")
+ lower2 := filepath.Join(td, "lower2")
+ upper := filepath.Join(td, "upper")
+ work := filepath.Join(td, "work")
+
+ require.NoError(t, os.MkdirAll(lower1, 0755))
+ require.NoError(t, os.MkdirAll(lower2, 0755))
+ require.NoError(t, os.MkdirAll(upper, 0755))
+ require.NoError(t, os.MkdirAll(work, 0755))
+
+ require.NoError(t, os.WriteFile(filepath.Join(lower1, "file1.txt"), []byte("layer1\n"), 0644))
+ require.NoError(t, os.WriteFile(filepath.Join(lower2, "file2.txt"), []byte("layer2\n"), 0644))
+
+ mounts := []mount.Mount{
+ {
+ Type: "overlay",
+ Source: "overlay",
+ Options: []string{
+ fmt.Sprintf("lowerdir=%s:%s", lower2, lower1),
+ fmt.Sprintf("upperdir=%s", upper),
+ fmt.Sprintf("workdir=%s", work),
+ },
+ },
+ }
+
+ m, err := NewManager(db, targetdir)
+ require.NoError(t, err)
+
+ ainfo, err := m.Activate(ctx, "temp-overlay-test", mounts, mount.WithTemporary)
+ require.NoError(t, err)
+ defer func() {
+ assert.NoError(t, m.Deactivate(ctx, "temp-overlay-test"))
+ }()
+
+ require.NotEmpty(t, ainfo.System, "Expected system mounts to be returned")
+
+ require.Len(t, ainfo.System, 1, "Expected exactly one system mount")
+ systemMount := ainfo.System[0]
+ assert.Equal(t, "bind", systemMount.Type, "Expected bind mount type")
+
+ sourceInfo, err := os.Stat(systemMount.Source)
+ require.NoError(t, err, "Bind mount source %q should exist", systemMount.Source)
+ assert.True(t, sourceInfo.IsDir(), "Bind mount source should be a directory")
+
+ file1 := filepath.Join(systemMount.Source, "file1.txt")
+ file2 := filepath.Join(systemMount.Source, "file2.txt")
+
+ content1, err := os.ReadFile(file1)
+ require.NoError(t, err, "Should be able to read file1 from overlay via bind source")
+ assert.Equal(t, "layer1\n", string(content1))
+
+ content2, err := os.ReadFile(file2)
+ require.NoError(t, err, "Should be able to read file2 from overlay via bind source")
+ assert.Equal(t, "layer2\n", string(content2))
+
+ targetMount := filepath.Join(td, "target")
+ require.NoError(t, os.MkdirAll(targetMount, 0755))
+
+ err = mount.All(ainfo.System, targetMount)
+ require.NoError(t, err, "Should be able to mount system mounts to target")
+ defer testutil.Unmount(t, targetMount)
+
+ targetFile1 := filepath.Join(targetMount, "file1.txt")
+ targetFile2 := filepath.Join(targetMount, "file2.txt")
+
+ targetContent1, err := os.ReadFile(targetFile1)
+ require.NoError(t, err)
+ assert.Equal(t, "layer1\n", string(targetContent1))
+
+ targetContent2, err := os.ReadFile(targetFile2)
+ require.NoError(t, err)
+ assert.Equal(t, "layer2\n", string(targetContent2))
+}
+
func initalizeBlockDevice(td string, a fstest.Applier) (string, error) {
file, err := os.CreateTemp(td, "fs-")
if err != nil {
@@ -342,7 +497,7 @@ func initalizeBlockDevice(td string, a fstest.Applier) (string, error) {
m := mount.Mount{
Type: "ext4",
- Source: dpath, // previous mount
+ Source: dpath,
Options: []string{"loop"},
}
target, err := os.MkdirTemp(td, "mount-")
From 1d79082735d46fe24ded00a55ea6e3a33954593e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Poulin?= <jeromepoulin@gmail.com>
Date: Wed, 26 Nov 2025 18:29:31 -0500
Subject: [PATCH 2/2] core/mount/manager: fix bind mount missing rbind option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The bind mount created for temporary activations was missing the
Options field, causing mount to fail with "no such device" because
the MS_BIND flag wasn't being set.
Fixes #12549
Signed-off-by: Jérôme Poulin <jeromepoulin@gmail.com>
---
core/mount/manager/manager.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/core/mount/manager/manager.go b/core/mount/manager/manager.go
index d43c1beb8e7c..5163c17dbcac 100644
--- a/core/mount/manager/manager.go
+++ b/core/mount/manager/manager.go
@@ -430,9 +430,9 @@ func (mm *mountManager) Activate(ctx context.Context, name string, mounts []moun
// TODO: Add config for whether to add the bind mount?
if config.Temporary && firstSystemMount > 0 {
mounts = append(mounts, mount.Mount{
- Type: "bind",
- Source: mounted[firstSystemMount-1].MountPoint,
- // TODO : Configurable bind mount options?
+ Type: "bind",
+ Source: mounted[firstSystemMount-1].MountPoint,
+ Options: []string{"rbind"},
})
}

View File

@ -0,0 +1,3 @@
The `0001-ctr-no-such-device-fix.patch` fixes a regression detected by
our `cl.toolbox.dnf-install` test. It is merged into the 2.2 release
branch in upstream, but no release with the fix happened yet.