aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-04-05 14:00:52 +0900
committerOphestra <cat@gensokyo.uk>2026-04-05 14:04:21 +0900
commit33a0e6c01bb93488f5442231eef3b93012d3af1e (patch)
tree0ae62faa64d82d64ffc9f7ac6de7d754a251d501
parentd58f5c7590c1500055af6b8682d50134100c3a94 (diff)
hst: conditionally skip root remount
This enables the writable root overlay use case. Signed-off-by: Ophestra <cat@gensokyo.uk>
-rw-r--r--hst/fs.go4
-rw-r--r--hst/fsoverlay.go8
-rw-r--r--hst/fsoverlay_test.go13
-rw-r--r--internal/outcome/spcontainer.go4
4 files changed, 25 insertions, 4 deletions
diff --git a/hst/fs.go b/hst/fs.go
index 92ca51af..13645d1a 100644
--- a/hst/fs.go
+++ b/hst/fs.go
@@ -56,8 +56,10 @@ type Ops interface {
// ApplyState holds the address of [Ops] and any relevant application state.
type ApplyState struct {
- // AutoEtcPrefix is the prefix for [FSBind] in autoetc [FSBind.Special] condition.
+ // Prefix for [FSBind] in autoetc [FSBind.Special] condition.
AutoEtcPrefix string
+ // Whether to skip remounting root.
+ NoRemountRoot bool
Ops
}
diff --git a/hst/fsoverlay.go b/hst/fsoverlay.go
index 738ecf53..b06c1e7e 100644
--- a/hst/fsoverlay.go
+++ b/hst/fsoverlay.go
@@ -5,6 +5,7 @@ import (
"strings"
"hakurei.app/check"
+ "hakurei.app/fhs"
)
func init() { gob.Register(new(FSOverlay)) }
@@ -69,9 +70,12 @@ func (o *FSOverlay) Apply(z *ApplyState) {
return
}
- if o.Upper != nil && o.Work != nil { // rw
+ if o.Upper != nil && o.Work != nil {
z.Overlay(o.Target, o.Upper, o.Work, o.Lower...)
- } else { // ro
+ if o.Target.Is(fhs.AbsRoot) {
+ z.NoRemountRoot = true
+ }
+ } else {
z.OverlayReadonly(o.Target, o.Lower...)
}
}
diff --git a/hst/fsoverlay_test.go b/hst/fsoverlay_test.go
index f1097481..1b14e7c9 100644
--- a/hst/fsoverlay_test.go
+++ b/hst/fsoverlay_test.go
@@ -49,5 +49,18 @@ func TestFSOverlay(t *testing.T) {
Lower: ms("/tmp/.src0", "/tmp/.src1"),
}}, m("/mnt/src"), ms("/tmp/.src0", "/tmp/.src1"),
"*/mnt/src:/tmp/.src0:/tmp/.src1"},
+
+ {"no remount root", &hst.FSOverlay{
+ Target: m("/"),
+ Lower: ms("/tmp/.src0", "/tmp/.src1"),
+ Upper: m("/tmp/upper"),
+ Work: m("/tmp/work"),
+ }, true, container.Ops{&container.MountOverlayOp{
+ Target: m("/"),
+ Lower: ms("/tmp/.src0", "/tmp/.src1"),
+ Upper: m("/tmp/upper"),
+ Work: m("/tmp/work"),
+ }}, m("/"), ms("/tmp/upper", "/tmp/work", "/tmp/.src0", "/tmp/.src1"),
+ "w*/:/tmp/upper:/tmp/work:/tmp/.src0:/tmp/.src1"},
})
}
diff --git a/internal/outcome/spcontainer.go b/internal/outcome/spcontainer.go
index 0ad1de50..d9398d2c 100644
--- a/internal/outcome/spcontainer.go
+++ b/internal/outcome/spcontainer.go
@@ -290,7 +290,9 @@ func (s *spFilesystemOp) toContainer(state *outcomeStateParams) error {
if state.Container.Flags&hst.FDevice == 0 {
state.params.Remount(fhs.AbsDev, syscall.MS_RDONLY)
}
- state.params.Remount(fhs.AbsRoot, syscall.MS_RDONLY)
+ if !state.as.NoRemountRoot {
+ state.params.Remount(fhs.AbsRoot, syscall.MS_RDONLY)
+ }
state.params.Env = make([]string, 0, len(state.env))
for key, value := range state.env {