Skip to content

Commit 1ce04dd

Browse files
committed
Support tmpfs-backed sandbox mount for LCOW containers
Signed-off-by: Jie Chen <[email protected]>
1 parent 04735e0 commit 1ce04dd

File tree

6 files changed

+70
-9
lines changed

6 files changed

+70
-9
lines changed

cmd/containerd-shim-runhcs-v1/task_hcs.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,8 +988,9 @@ func isMountTypeSupported(hostPath, mountType string) bool {
988988
hcsoci.MountTypeVirtualDisk, hcsoci.MountTypeExtensibleVirtualDisk:
989989
return false
990990
default:
991-
// Ensure that host path is not sandbox://, hugepages://, \\.\pipe, uvm://
991+
// Ensure that host path is not sandbox://, sandbox-tmp://, hugepages://, \\.\pipe, uvm://
992992
if strings.HasPrefix(hostPath, guestpath.SandboxMountPrefix) ||
993+
strings.HasPrefix(hostPath, guestpath.SandboxTmpfsMountPrefix) ||
993994
strings.HasPrefix(hostPath, guestpath.HugePagesMountPrefix) ||
994995
strings.HasPrefix(hostPath, guestpath.PipePrefix) ||
995996
strings.HasPrefix(hostPath, guestpath.UVMMountPrefix) {

internal/guest/runtime/hcsv2/uvm.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,31 @@ func setupSandboxMountsPath(id string) (err error) {
290290
return storage.MountRShared(mountPath)
291291
}
292292

293+
func setupSandboxTmpfsMountsPath(id string) error {
294+
var err error
295+
tmpfsDir := specGuest.SandboxTmpfsMountsDir(id)
296+
if err := os.MkdirAll(tmpfsDir, 0755); err != nil {
297+
return errors.Wrapf(err, "failed to create sandbox tmpfs mounts dir in sandbox %v", id)
298+
}
299+
300+
defer func() {
301+
if err != nil {
302+
_ = os.RemoveAll(tmpfsDir)
303+
}
304+
}()
305+
306+
// mount a tmpfs at the tmpfsDir
307+
// this ensures that the tmpfsDir is a mount point and not just a directory
308+
// we don't care if it is already mounted, so ignore EBUSY
309+
if err := unix.Mount("tmpfs", tmpfsDir, "tmpfs", 0, ""); err != nil && !errors.Is(err, unix.EBUSY) {
310+
return errors.Wrapf(err, "failed to mount tmpfs at %s", tmpfsDir)
311+
}
312+
313+
//TODO: should tmpfs be mounted as noexec?
314+
315+
return storage.MountRShared(tmpfsDir)
316+
}
317+
293318
func setupSandboxHugePageMountsPath(id string) error {
294319
mountPath := specGuest.HugePagesMountsDir(id)
295320
if err := os.MkdirAll(mountPath, 0755); err != nil {
@@ -351,6 +376,10 @@ func (h *Host) CreateContainer(ctx context.Context, id string, settings *prot.VM
351376
return nil, err
352377
}
353378

379+
if err = setupSandboxTmpfsMountsPath(id); err != nil {
380+
return nil, err
381+
}
382+
354383
if err = setupSandboxHugePageMountsPath(id); err != nil {
355384
return nil, err
356385
}

internal/guest/runtime/hcsv2/workload_container.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,28 @@ func mkdirAllModePerm(target string) error {
3434

3535
func updateSandboxMounts(sbid string, spec *oci.Spec) error {
3636
for i, m := range spec.Mounts {
37-
if !strings.HasPrefix(m.Source, guestpath.SandboxMountPrefix) {
37+
if !strings.HasPrefix(m.Source, guestpath.SandboxMountPrefix) &&
38+
!strings.HasPrefix(m.Source, guestpath.SandboxTmpfsMountPrefix) {
3839
continue
3940
}
40-
sandboxSource := specGuest.SandboxMountSource(sbid, m.Source)
4141

42-
// filepath.Join cleans the resulting path before returning, so it would resolve the relative path if one was given.
43-
// Hence, we need to ensure that the resolved path is still under the correct directory
44-
if !strings.HasPrefix(sandboxSource, specGuest.SandboxMountsDir(sbid)) {
45-
return errors.Errorf("mount path %v for mount %v is not within sandbox's mounts dir", sandboxSource, m.Source)
42+
var sandboxSource string
43+
// if using `sandbox-tmp://` prefix, we mount a tmpfs in sandboxTmpfsMountsDir
44+
if strings.HasPrefix(m.Source, guestpath.SandboxTmpfsMountPrefix) {
45+
sandboxSource = specGuest.SandboxTmpfsMountSource(sbid, m.Source)
46+
// filepath.Join cleans the resulting path before returning, so it would resolve the relative path if one was given.
47+
// Hence, we need to ensure that the resolved path is still under the correct directory
48+
if !strings.HasPrefix(sandboxSource, specGuest.SandboxTmpfsMountsDir(sbid)) {
49+
return errors.Errorf("mount path %v for mount %v is not within sandboxTmpfsMountsDir", sandboxSource, m.Source)
50+
}
51+
52+
} else {
53+
sandboxSource = specGuest.SandboxMountSource(sbid, m.Source)
54+
// filepath.Join cleans the resulting path before returning, so it would resolve the relative path if one was given.
55+
// Hence, we need to ensure that the resolved path is still under the correct directory
56+
if !strings.HasPrefix(sandboxSource, specGuest.SandboxMountsDir(sbid)) {
57+
return errors.Errorf("mount path %v for mount %v is not within sandbox's mounts dir", sandboxSource, m.Source)
58+
}
4659
}
4760

4861
spec.Mounts[i].Source = sandboxSource

internal/guest/spec/spec.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ func SandboxMountsDir(sandboxID string) string {
8484
return filepath.Join(SandboxRootDir(sandboxID), "sandboxMounts")
8585
}
8686

87+
// SandboxTmpfsMountsDir returns sandbox tmpfs mounts directory inside UVM.
88+
func SandboxTmpfsMountsDir(sandboxID string) string {
89+
return filepath.Join(SandboxRootDir(sandboxID), "sandboxTmpfsMounts")
90+
}
91+
8792
// HugePagesMountsDir returns hugepages mounts directory inside UVM.
8893
func HugePagesMountsDir(sandboxID string) string {
8994
return filepath.Join(SandboxRootDir(sandboxID), "hugepages")
@@ -96,6 +101,13 @@ func SandboxMountSource(sandboxID, path string) string {
96101
return filepath.Join(mountsDir, subPath)
97102
}
98103

104+
// SandboxTmpfsMountSource returns sandbox tmpfs mount path inside UVM
105+
func SandboxTmpfsMountSource(sandboxID, path string) string {
106+
tmpfsMountDir := SandboxTmpfsMountsDir(sandboxID)
107+
subPath := strings.TrimPrefix(path, guestpath.SandboxTmpfsMountPrefix)
108+
return filepath.Join(tmpfsMountDir, subPath)
109+
}
110+
99111
// HugePagesMountSource returns hugepages mount path inside UVM
100112
func HugePagesMountSource(sandboxID, path string) string {
101113
mountsDir := HugePagesMountsDir(sandboxID)

internal/guestpath/paths.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ const (
1010
// SandboxMountPrefix is mount prefix used in container spec to mark a
1111
// sandbox-mount
1212
SandboxMountPrefix = "sandbox://"
13+
// SandboxTmpfsMountPrefix is mount prefix used in container spec to mark a
14+
// sandbox-tmp mount
15+
SandboxTmpfsMountPrefix = "sandbox-tmp://"
1316
// HugePagesMountPrefix is mount prefix used in container spec to mark a
1417
// huge-pages mount
1518
HugePagesMountPrefix = "hugepages://"

internal/hcsoci/resources_lcow.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,13 @@ func allocateLinuxResources(ctx context.Context, coi *createOptionsInternal, r *
129129
mt = "bind"
130130
}
131131
coi.Spec.Mounts[i].Type = mt
132-
} else if strings.HasPrefix(mount.Source, guestpath.SandboxMountPrefix) || strings.HasPrefix(mount.Source, guestpath.UVMMountPrefix) {
133-
// Mounts that map to a path in UVM are specified with a 'sandbox://' or 'uvm://' prefix.
132+
} else if strings.HasPrefix(mount.Source, guestpath.SandboxMountPrefix) ||
133+
strings.HasPrefix(mount.Source, guestpath.SandboxTmpfsMountPrefix) ||
134+
strings.HasPrefix(mount.Source, guestpath.UVMMountPrefix) {
135+
// Mounts that map to a path in UVM are specified with a 'sandbox://', 'sandbox-tmp://', or 'uvm://' prefix.
134136
// examples:
135137
// - sandbox:///a/dirInUvm destination:/b/dirInContainer
138+
// - sandbox-tmp:///a/dirInUvm destination:/b/dirInContainer
136139
// - uvm:///a/dirInUvm destination:/b/dirInContainer
137140
uvmPathForFile = mount.Source
138141
} else if strings.HasPrefix(mount.Source, guestpath.HugePagesMountPrefix) {

0 commit comments

Comments
 (0)