Skip to content

Commit e73942d

Browse files
authored
Merge pull request containerd#9555 from KodieGlosserIBM/strip-volatile-option-tmp-mounts
Remove overlayfs volatile option on temp mounts
2 parents 6f44916 + cfe8321 commit e73942d

File tree

2 files changed

+150
-1
lines changed

2 files changed

+150
-1
lines changed

core/mount/mount_test.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,114 @@ func TestReadonlyMounts(t *testing.T) {
148148
}
149149
}
150150
}
151+
152+
func TestRemoveVolatileTempMount(t *testing.T) {
153+
testCases := []struct {
154+
desc string
155+
input []Mount
156+
expected []Mount
157+
}{
158+
{
159+
desc: "remove volatile option from overlay mounts, ignore non overlay",
160+
input: []Mount{
161+
{
162+
Type: "overlay",
163+
Source: "overlay",
164+
Options: []string{
165+
"index=off",
166+
"workdir=/path/to/snapshots/4/work",
167+
"upperdir=/path/to/snapshots/4/fs",
168+
"lowerdir=/path/to/snapshots/1/fs",
169+
"volatile",
170+
},
171+
},
172+
{
173+
Type: "underlay",
174+
Source: "underlay",
175+
Options: []string{
176+
"index=on",
177+
"lowerdir=/another/path/to/snapshots/2/fs",
178+
"volatile",
179+
},
180+
},
181+
},
182+
expected: []Mount{
183+
{
184+
Type: "overlay",
185+
Source: "overlay",
186+
Options: []string{
187+
"index=off",
188+
"workdir=/path/to/snapshots/4/work",
189+
"upperdir=/path/to/snapshots/4/fs",
190+
"lowerdir=/path/to/snapshots/1/fs",
191+
},
192+
},
193+
{
194+
Type: "underlay",
195+
Source: "underlay",
196+
Options: []string{
197+
"index=on",
198+
"lowerdir=/another/path/to/snapshots/2/fs",
199+
"volatile",
200+
},
201+
},
202+
},
203+
},
204+
{
205+
desc: "return original slice since no volatile options on overlay",
206+
input: []Mount{
207+
{
208+
Type: "overlay",
209+
Source: "overlay",
210+
Options: []string{
211+
"index=off",
212+
"workdir=/path/to/snapshots/4/work",
213+
"upperdir=/path/to/snapshots/4/fs",
214+
"lowerdir=/path/to/snapshots/1/fs",
215+
},
216+
},
217+
{
218+
Type: "underlay",
219+
Source: "underlay",
220+
Options: []string{
221+
"index=on",
222+
"lowerdir=/another/path/to/snapshots/2/fs",
223+
"volatile",
224+
},
225+
},
226+
},
227+
expected: []Mount{
228+
{
229+
Type: "overlay",
230+
Source: "overlay",
231+
Options: []string{
232+
"index=off",
233+
"workdir=/path/to/snapshots/4/work",
234+
"upperdir=/path/to/snapshots/4/fs",
235+
"lowerdir=/path/to/snapshots/1/fs",
236+
},
237+
},
238+
{
239+
Type: "underlay",
240+
Source: "underlay",
241+
Options: []string{
242+
"index=on",
243+
"lowerdir=/another/path/to/snapshots/2/fs",
244+
"volatile",
245+
},
246+
},
247+
},
248+
},
249+
}
250+
251+
for _, tc := range testCases {
252+
original := copyMounts(tc.input)
253+
actual := removeVolatileTempMount(tc.input)
254+
if !reflect.DeepEqual(actual, tc.expected) {
255+
t.Fatalf("incorrectly modified mounts: %s.\n\n Expected: %v\n\n, Actual: %v", tc.desc, tc.expected, actual)
256+
}
257+
if !reflect.DeepEqual(original, tc.input) {
258+
t.Fatalf("modified original mounts: %s.\n\n Expected: %v\n\n, Actual: %v", tc.desc, original, tc.input)
259+
}
260+
}
261+
}

core/mount/temp.go

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ var tempMountLocation = getTempDir()
2828

2929
// WithTempMount mounts the provided mounts to a temp dir, and pass the temp dir to f.
3030
// The mounts are valid during the call to the f.
31+
// The volatile option of overlayfs doesn't allow to mount again using the same upper / work dirs. Since it's a temp mount, avoid using that option here if found.
3132
// Finally we will unmount and remove the temp dir regardless of the result of f.
3233
func WithTempMount(ctx context.Context, mounts []Mount, f func(root string) error) (err error) {
3334
root, uerr := os.MkdirTemp(tempMountLocation, "containerd-mount")
@@ -58,7 +59,8 @@ func WithTempMount(ctx context.Context, mounts []Mount, f func(root string) erro
5859
}
5960
}
6061
}()
61-
if uerr = All(mounts, root); uerr != nil {
62+
63+
if uerr = All(removeVolatileTempMount(mounts), root); uerr != nil {
6264
return fmt.Errorf("failed to mount %s: %w", root, uerr)
6365
}
6466
if err := f(root); err != nil {
@@ -67,6 +69,42 @@ func WithTempMount(ctx context.Context, mounts []Mount, f func(root string) erro
6769
return nil
6870
}
6971

72+
// removeVolatileTempMount The volatile option of overlayfs doesn't allow to mount again using the
73+
// same upper / work dirs. Since it's a temp mount, avoid using that
74+
// option here. Reference: https://docs.kernel.org/filesystems/overlayfs.html#volatile-mount
75+
// TODO: Make this logic conditional once the kernel supports reusing
76+
// overlayfs volatile mounts.
77+
func removeVolatileTempMount(mounts []Mount) []Mount {
78+
var out []Mount
79+
for i, m := range mounts {
80+
if m.Type != "overlay" {
81+
continue
82+
}
83+
for j, opt := range m.Options {
84+
if opt == "volatile" {
85+
if out == nil {
86+
out = copyMounts(mounts)
87+
}
88+
out[i].Options = append(out[i].Options[:j], out[i].Options[j+1:]...)
89+
break
90+
}
91+
}
92+
}
93+
94+
if out != nil {
95+
return out
96+
}
97+
98+
return mounts
99+
}
100+
101+
// copyMounts creates a copy of the original slice to allow for modification and not altering the original
102+
func copyMounts(in []Mount) []Mount {
103+
out := make([]Mount, len(in))
104+
copy(out, in)
105+
return out
106+
}
107+
70108
// WithReadonlyTempMount mounts the provided mounts to a temp dir as readonly,
71109
// and pass the temp dir to f. The mounts are valid during the call to the f.
72110
// Finally we will unmount and remove the temp dir regardless of the result of f.

0 commit comments

Comments
 (0)