internal/pkg: automatic overlay mount on work

This directly submits the upperdir to cache. It is primarily used in bootstrapping where tools are limited and should not be used unless there is a very good reason to.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-01-07 03:14:33 +09:00
parent 54da6ce03d
commit 8e08e8f518
4 changed files with 140 additions and 25 deletions

View File

@@ -16,6 +16,9 @@ import (
"hakurei.app/message"
)
// AbsWork is the container pathname [CureContext.GetWorkDir] is mounted on.
var AbsWork = fhs.AbsRoot.Append("work/")
// ExecContainerPath is an [Artifact] and the [check.Absolute] pathname to make
// it available under in the container.
type ExecContainerPath struct {
@@ -90,9 +93,14 @@ func (a *execNetArtifact) Cure(c *CureContext) error {
// A private instance of /proc and /dev is made available to the container.
//
// The working and temporary directories are both created and mounted writable
// on /work and /tmp respectively. If one or more paths target [fhs.AbsTmp], the
// final entry is set up as a writable overlay mount on /tmp backed by the host
// side temporary directory.
// on [AbsWork] and [fhs.AbsTmp] respectively. If one or more paths target
// [fhs.AbsTmp], the final entry is set up as a writable overlay mount on /tmp
// backed by the host side temporary directory. If one or more paths target
// [AbsWork], the final entry is set up as a writable overlay mount on /work for
// which the upperdir is the host side work directory. In this configuration,
// the program must avoid causing whiteout files to be created, cure fails if
// upperdir ends up with anything other than directory, regular or symlink
// entries.
//
// If the first path targets [fhs.AbsRoot], it is made writable via an overlay
// mount with writes going to an ephemeral tmpfs bound to the lifetime of the
@@ -186,7 +194,7 @@ func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) {
cures = runtime.NumCPU()
}
overlayTempIndex := -1
overlayTempIndex, overlayWorkIndex := -1, -1
paths := make([][2]*check.Absolute, len(a.paths))
for i, p := range a.paths {
if p.P == nil || p.A == nil {
@@ -194,6 +202,8 @@ func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) {
}
if p.P.Is(fhs.AbsTmp) {
overlayTempIndex = i
} else if p.P.Is(AbsWork) {
overlayWorkIndex = i
}
paths[i][1] = p.P
}
@@ -280,11 +290,12 @@ func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) {
z.OverlayEphemeral(fhs.AbsRoot, paths[0][0])
paths = paths[1:]
overlayTempIndex--
overlayWorkIndex--
}
temp, work := c.GetTempDir(), c.GetWorkDir()
for i, b := range paths {
if i == overlayTempIndex {
temp := c.GetTempDir()
tempUpper := temp.Append("upper")
if err = os.MkdirAll(tempUpper.String(), 0700); err != nil {
return
@@ -301,14 +312,31 @@ func (a *execArtifact) cure(c *CureContext, hostNet bool) (err error) {
)
continue
}
if i == overlayWorkIndex {
if err = os.MkdirAll(work.String(), 0700); err != nil {
return
}
tempWork := temp.Append(".work")
if err = os.MkdirAll(tempWork.String(), 0700); err != nil {
return
}
z.Overlay(
AbsWork,
work,
tempWork,
b[0],
)
continue
}
z.Bind(b[0], b[1], 0)
}
work := c.GetWorkDir()
z.Bind(
work,
fhs.AbsRoot.Append("work"),
std.BindWritable|std.BindEnsure,
)
if overlayWorkIndex < 0 {
z.Bind(
work,
AbsWork,
std.BindWritable|std.BindEnsure,
)
}
if overlayTempIndex < 0 {
z.Bind(
c.GetTempDir(),