Skip to content

Commit 660de19

Browse files
henry118k8s-infra-cherrypick-robot
authored andcommitted
Tweak mount info for overlayfs in case of parallel unpack
Signed-off-by: Henry Wang <[email protected]>
1 parent bc9274a commit 660de19

2 files changed

Lines changed: 115 additions & 0 deletions

File tree

core/unpack/unpacker.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,15 @@ func (u *Unpacker) unpack(
524524
case <-fetchC[i-fetchOffset]:
525525
}
526526

527+
// In case of parallel unpack, the parent snapshot isn't provided to the snapshotter.
528+
// The overlayfs will return bind mounts for all layers, we need to convert them
529+
// to overlay mounts for the applier to perform whiteout conversion correctly.
530+
// TODO: this is a temporary workaround until #13053 lands.
531+
// See: https://github.com/containerd/containerd/issues/13030
532+
if i > 0 && parallel && unpack.SnapshotterKey == "overlayfs" {
533+
mounts = bindToOverlay(mounts)
534+
}
535+
527536
diff, err := a.Apply(ctx, desc, mounts, unpack.ApplyOpts...)
528537
if err != nil {
529538
cleanup.Do(ctx, abort)
@@ -747,3 +756,23 @@ func uniquePart() string {
747756
rand.Read(b[:])
748757
return fmt.Sprintf("%d-%s", t.Nanosecond(), base64.URLEncoding.EncodeToString(b[:]))
749758
}
759+
760+
// TODO: this is a temporary workaround until #13053 lands.
761+
func bindToOverlay(mounts []mount.Mount) []mount.Mount {
762+
if len(mounts) != 1 || mounts[0].Type != "bind" {
763+
return mounts
764+
}
765+
766+
m := mount.Mount{
767+
Type: "overlay",
768+
Source: "overlay",
769+
}
770+
for _, o := range mounts[0].Options {
771+
if o != "rbind" {
772+
m.Options = append(m.Options, o)
773+
}
774+
}
775+
m.Options = append(m.Options, "upperdir="+mounts[0].Source)
776+
777+
return []mount.Mount{m}
778+
}

core/unpack/unpacker_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ package unpack
1919
import (
2020
"crypto/rand"
2121
"fmt"
22+
"reflect"
2223
"testing"
2324

25+
"github.com/containerd/containerd/v2/core/mount"
2426
"github.com/opencontainers/go-digest"
2527
"github.com/opencontainers/image-spec/identity"
2628
)
@@ -91,3 +93,87 @@ func BenchmarkUnpackWithChainIDs(b *testing.B) {
9193
})
9294
}
9395
}
96+
97+
func TestBindToOverlay(t *testing.T) {
98+
testCases := []struct {
99+
name string
100+
mounts []mount.Mount
101+
expect []mount.Mount
102+
}{
103+
{
104+
name: "single bind mount",
105+
mounts: []mount.Mount{
106+
{
107+
Type: "bind",
108+
Source: "/path/to/source",
109+
Options: []string{"ro", "rbind"},
110+
},
111+
},
112+
expect: []mount.Mount{
113+
{
114+
Type: "overlay",
115+
Source: "overlay",
116+
Options: []string{
117+
"ro",
118+
"upperdir=/path/to/source",
119+
},
120+
},
121+
},
122+
},
123+
{
124+
name: "overlay mount",
125+
mounts: []mount.Mount{
126+
{
127+
Type: "overlay",
128+
Source: "overlay",
129+
Options: []string{
130+
"lowerdir=/path/to/lower",
131+
"upperdir=/path/to/upper",
132+
},
133+
},
134+
},
135+
expect: []mount.Mount{
136+
{
137+
Type: "overlay",
138+
Source: "overlay",
139+
Options: []string{
140+
"lowerdir=/path/to/lower",
141+
"upperdir=/path/to/upper",
142+
},
143+
},
144+
},
145+
},
146+
{
147+
name: "multiple mounts",
148+
mounts: []mount.Mount{
149+
{
150+
Type: "bind",
151+
Source: "/path/to/source1",
152+
},
153+
{
154+
Type: "bind",
155+
Source: "/path/to/source2",
156+
},
157+
},
158+
expect: []mount.Mount{
159+
{
160+
Type: "bind",
161+
Source: "/path/to/source1",
162+
},
163+
{
164+
Type: "bind",
165+
Source: "/path/to/source2",
166+
},
167+
},
168+
},
169+
}
170+
171+
for _, tc := range testCases {
172+
t.Run(tc.name, func(t *testing.T) {
173+
result := bindToOverlay(tc.mounts)
174+
if !reflect.DeepEqual(result, tc.expect) {
175+
t.Errorf("unexpected result: got %v, want %v", result, tc.expect)
176+
}
177+
})
178+
}
179+
}

0 commit comments

Comments
 (0)