From 8e08e8f51882fd8152eec349117f4f8dd7e056f0 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Wed, 7 Jan 2026 03:14:33 +0900 Subject: 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 --- internal/pkg/exec.go | 50 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) (limited to 'internal/pkg/exec.go') diff --git a/internal/pkg/exec.go b/internal/pkg/exec.go index 6e050b15..8d736b5b 100644 --- a/internal/pkg/exec.go +++ b/internal/pkg/exec.go @@ -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(), -- cgit v1.3.1