Skip to content

Newtype OverlayMedium #11735

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions runsc/boot/mount_hints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ func TestRootfsHintHappy(t *testing.T) {
Annotations: map[string]string{
RootfsPrefix + "source": imagePath,
RootfsPrefix + "type": erofs.Name,
RootfsPrefix + "overlay": config.MemoryOverlay.String(),
RootfsPrefix + "overlay": config.OverlayMediumMemory().String(),
},
}
hint, err := NewRootfsHint(spec)
Expand All @@ -272,7 +272,7 @@ func TestRootfsHintHappy(t *testing.T) {
if hint.Mount.Type != erofs.Name {
t.Errorf("rootfs type, want: %q, got: %q", erofs.Name, hint.Mount.Type)
}
if hint.Overlay != config.MemoryOverlay {
if hint.Overlay.MediumType() != config.MemoryOverlay {
t.Errorf("rootfs overlay, want: %q, got: %q", config.MemoryOverlay, hint.Overlay)
}
}
Expand Down Expand Up @@ -317,23 +317,23 @@ func TestRootfsHintErrors(t *testing.T) {
RootfsPrefix + "invalid": "invalid",
RootfsPrefix + "source": imagePath,
RootfsPrefix + "type": erofs.Name,
RootfsPrefix + "overlay": config.MemoryOverlay.String(),
RootfsPrefix + "overlay": config.OverlayMediumMemory().String(),
},
error: "invalid rootfs annotation",
},
{
name: "missing source",
annotations: map[string]string{
RootfsPrefix + "type": erofs.Name,
RootfsPrefix + "overlay": config.MemoryOverlay.String(),
RootfsPrefix + "overlay": config.OverlayMediumMemory().String(),
},
error: "rootfs annotations missing required field",
},
{
name: "missing type",
annotations: map[string]string{
RootfsPrefix + "source": imagePath,
RootfsPrefix + "overlay": config.MemoryOverlay.String(),
RootfsPrefix + "overlay": config.OverlayMediumMemory().String(),
},
error: "rootfs annotations missing required field",
},
Expand Down
77 changes: 55 additions & 22 deletions runsc/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ func (c *Config) GetOverlay2() Overlay2 {
panic(fmt.Sprintf("Overlay2 cannot be set when --overlay=true"))
}
// Using a deprecated flag, honor it to avoid breaking users.
return Overlay2{rootMount: true, subMounts: true, medium: "memory"}
return Overlay2{rootMount: true, subMounts: true, medium: OverlayMediumMemory()}
}
return c.Overlay2
}
Expand Down Expand Up @@ -844,49 +844,82 @@ func (g HostFifo) AllowOpen() bool {
return g&HostFifoOpen != 0
}

// OverlayMedium describes how overlay medium is configured.
type OverlayMedium string
// OverlayMediumType describes types of overlay medium.
type OverlayMediumType string

const (
// NoOverlay indicates that no overlay will be applied.
NoOverlay = OverlayMedium("")
NoOverlay = OverlayMediumType("")

// MemoryOverlay indicates that the overlay is backed by app memory.
MemoryOverlay = OverlayMedium("memory")
MemoryOverlay = OverlayMediumType("memory")

// SelfOverlay indicates that the overlaid mount is backed by itself.
SelfOverlay = OverlayMedium("self")
SelfOverlay = OverlayMediumType("self")

AnonOverlay = OverlayMediumType("dir")

// AnonOverlayPrefix is the prefix that users should specify in the
// anonOverlayPrefix is the prefix that users should specify in the
// config for the anonymous overlay.
AnonOverlayPrefix = "dir="
anonOverlayPrefix = "dir="
)

// OverlayMedium describes how overlay medium is configured.
type OverlayMedium struct {
medium OverlayMediumType
// Set iff medium is AnonOverlay.
dir string
}

func OverlayMediumNoOverlay() OverlayMedium {
return OverlayMedium{medium: NoOverlay}
}

func OverlayMediumMemory() OverlayMedium {
return OverlayMedium{medium: MemoryOverlay}
}

// String returns a human-readable string representing the overlay medium config.
func (m OverlayMedium) String() string {
return string(m)
switch m.medium {
case NoOverlay, MemoryOverlay, SelfOverlay:
return string(m.medium)
case AnonOverlay:
return fmt.Sprintf("%s=%s", AnonOverlay, m.dir)
default:
panic(fmt.Sprintf("Invalid overlay medium %q", m.medium))
}
}

// Set sets the value. Set(String()) should be idempotent.
func (m *OverlayMedium) Set(v string) error {
switch OverlayMedium(v) {
case NoOverlay, MemoryOverlay, SelfOverlay: // OK
switch OverlayMediumType(v) {
case NoOverlay, MemoryOverlay, SelfOverlay:
{
*m = OverlayMedium{medium: OverlayMediumType(v), dir: ""}
return nil
}
default:
if !strings.HasPrefix(v, AnonOverlayPrefix) {
if !strings.HasPrefix(v, anonOverlayPrefix) {
return fmt.Errorf("unexpected medium: %q", v)
}
if hostFileDir := strings.TrimPrefix(v, AnonOverlayPrefix); !filepath.IsAbs(hostFileDir) {
hostFileDir := strings.TrimPrefix(v, anonOverlayPrefix)
if !filepath.IsAbs(hostFileDir) {
return fmt.Errorf("overlay host file directory should be an absolute path, got %q", hostFileDir)
}
*m = OverlayMedium{medium: OverlayMediumType(v), dir: hostFileDir}
}
*m = OverlayMedium(v)
return nil
}

func (m OverlayMedium) MediumType() OverlayMediumType {
return m.medium
}

// IsBackedByAnon indicates whether the overlaid mount is backed by a host file
// in an anonymous directory.
func (m OverlayMedium) IsBackedByAnon() bool {
return strings.HasPrefix(string(m), AnonOverlayPrefix)
return m.medium == AnonOverlay
}

// HostFileDir indicates the directory in which the overlay-backing host file
Expand All @@ -895,9 +928,9 @@ func (m OverlayMedium) IsBackedByAnon() bool {
// Precondition: m.IsBackedByAnon().
func (m OverlayMedium) HostFileDir() string {
if !m.IsBackedByAnon() {
panic(fmt.Sprintf("anonymous overlay medium = %q does not have %v prefix", m, AnonOverlayPrefix))
panic(fmt.Sprintf("anonymous overlay medium = %q does not have %v prefix", m, anonOverlayPrefix))
}
return strings.TrimPrefix(string(m), AnonOverlayPrefix)
return m.dir
}

// Overlay2 holds the configuration for setting up overlay filesystems for the
Expand All @@ -910,15 +943,15 @@ type Overlay2 struct {

func defaultOverlay2() *Overlay2 {
// Rootfs overlay is enabled by default and backed by a file in rootfs itself.
return &Overlay2{rootMount: true, subMounts: false, medium: SelfOverlay}
return &Overlay2{rootMount: true, subMounts: false, medium: OverlayMedium{medium: SelfOverlay}}
}

// Set implements flag.Value. Set(String()) should be idempotent.
func (o *Overlay2) Set(v string) error {
if v == "none" {
o.rootMount = false
o.subMounts = false
o.medium = NoOverlay
o.medium = OverlayMediumNoOverlay()
return nil
}
vs := strings.Split(v, ":")
Expand Down Expand Up @@ -963,21 +996,21 @@ func (o Overlay2) String() string {

// Enabled returns true if the overlay option is enabled for any mounts.
func (o *Overlay2) Enabled() bool {
return o.medium != NoOverlay
return o.medium.medium != NoOverlay
}

// RootOverlayMedium returns the overlay medium config of the root mount.
func (o *Overlay2) RootOverlayMedium() OverlayMedium {
if !o.rootMount {
return NoOverlay
return OverlayMediumNoOverlay()
}
return o.medium
}

// SubMountOverlayMedium returns the overlay medium config of submounts.
func (o *Overlay2) SubMountOverlayMedium() OverlayMedium {
if !o.subMounts {
return NoOverlay
return OverlayMediumNoOverlay()
}
return o.medium
}
Expand Down
2 changes: 1 addition & 1 deletion runsc/config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ func checkOverlay2(name string, value string) error {
if err := o.Set(value); err != nil {
return fmt.Errorf("invalid overlay2 annotation: %w", err)
}
switch o.medium {
switch o.medium.MediumType() {
case NoOverlay, MemoryOverlay, SelfOverlay:
return nil
default:
Expand Down
8 changes: 4 additions & 4 deletions runsc/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ func createGoferConf(overlayMedium config.OverlayMedium, mountType string, mount
default:
return boot.GoferMountConf{}, fmt.Errorf("unsupported mount type %q in mount hint", mountType)
}
switch overlayMedium {
switch overlayMedium.MediumType() {
case config.NoOverlay:
return boot.GoferMountConf{Lower: lower, Upper: boot.NoOverlay}, nil
case config.MemoryOverlay:
Expand Down Expand Up @@ -947,7 +947,7 @@ func (c *Container) initGoferConfs(ovlConf config.Overlay2, mountHints *boot.Pod
}
}
if c.Spec.Root.Readonly {
overlayMedium = config.NoOverlay
overlayMedium = config.OverlayMediumNoOverlay()
}
goferConf, err := createGoferConf(overlayMedium, mountType, c.Spec.Root.Path)
if err != nil {
Expand All @@ -963,12 +963,12 @@ func (c *Container) initGoferConfs(ovlConf config.Overlay2, mountHints *boot.Pod
overlayMedium = ovlConf.SubMountOverlayMedium()
mountType = boot.Bind
if specutils.IsReadonlyMount(c.Spec.Mounts[i].Options) {
overlayMedium = config.NoOverlay
overlayMedium = config.OverlayMediumNoOverlay()
}
if hint := mountHints.FindMount(c.Spec.Mounts[i].Source); hint != nil {
// Note that we want overlayMedium=self even if this is a read-only mount so that
// the shared mount is created correctly. Future containers may mount this writably.
overlayMedium = config.SelfOverlay
overlayMedium = config.OverlayMediumNoOverlay()
if !specutils.IsGoferMount(hint.Mount) {
mountType = hint.Mount.Type
}
Expand Down
4 changes: 2 additions & 2 deletions runsc/container/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3486,7 +3486,7 @@ func TestRootfsEROFS(t *testing.T) {
spec.Annotations[boot.RootfsPrefix+"source"] = rootfsImage
// Disable the overlay, as we want to be sure that rootfs will always be
// shown as EROFS in mountinfo.
spec.Annotations[boot.RootfsPrefix+"overlay"] = config.NoOverlay.String()
spec.Annotations[boot.RootfsPrefix+"overlay"] = config.OverlayMediumNoOverlay().String()

conf := testutil.TestConfig(t)

Expand Down Expand Up @@ -3563,7 +3563,7 @@ func TestCheckpointRestoreEROFS(t *testing.T) {
// a writeable and savable overlay for rootfs, which allows the sentry to
// create the mount point for the bind mount of the temporary directory shared
// between host and test container.
spec.Annotations[boot.RootfsPrefix+"overlay"] = config.MemoryOverlay.String()
spec.Annotations[boot.RootfsPrefix+"overlay"] = config.OverlayMediumMemory().String()
return spec
})
})
Expand Down