Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4133967
Materialize per-layer artifacts with explicit whiteout handling
chruffins Aug 31, 2026
285a8c6
Harden layer artifact materialization
chruffins Sep 1, 2026
820d196
Address layer artifact review findings
chruffins Sep 1, 2026
480372f
Fix layer artifact composition edge cases
chruffins Sep 2, 2026
a0ea61a
Fix layer artifact composition and metadata handling edge cases
chruffins Sep 2, 2026
be91308
Harden layer artifact composition
chruffins Sep 2, 2026
122c28c
Harden layer tree portability and file copying
chruffins Sep 3, 2026
8416746
Harden layer materialization and metadata restoration
chruffins Sep 3, 2026
c2e927e
Share context-aware cached layer unpacking
chruffins Sep 3, 2026
8892900
Serialize layer store writes
chruffins Sep 3, 2026
2b7928e
Preserve explicit layer directory metadata
chruffins Sep 3, 2026
75f2d17
Use singleflight for layer materialization
chruffins Sep 3, 2026
deb563d
Test synthesized directory metadata preservation
chruffins Sep 3, 2026
53437a7
Collapse layer helper wrappers and dead branches
chruffins Sep 3, 2026
21b7c15
Drop access time preservation from layer metadata
chruffins Sep 3, 2026
f950306
Extract layers with umoci instead of a private tar walker
chruffins Sep 3, 2026
d3cb0cf
Detach shared layer builds from the initiating context
chruffins Sep 3, 2026
6681c41
Trim layer artifact plumbing
chruffins Sep 3, 2026
57d56ae
Harden layer artifact builds and drop unused plumbing
chruffins Sep 3, 2026
ae7ca83
Add layer artifact edge-case smoke tests
chruffins Sep 3, 2026
f18a718
Trim redundant smoke tests
chruffins Sep 3, 2026
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
40 changes: 39 additions & 1 deletion lib/images/disk_usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package images
import (
"encoding/json"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
"syscall"
)

Expand Down Expand Up @@ -82,6 +84,38 @@ func totalReadyImageBytesFromMetadata(imagesDir string) (int64, error) {
return total, nil
}

// totalLayerArtifactBytesFromFilesystem sums materialized layer artifacts.
func totalLayerArtifactBytesFromFilesystem(layersDir string) (int64, error) {
var total int64
err := filepath.WalkDir(layersDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
if d.IsDir() {
if strings.HasPrefix(d.Name(), ".") && path != layersDir {
return filepath.SkipDir
}
return nil
}
if !strings.HasPrefix(d.Name(), "layer.") {
return nil
}
info, err := d.Info()
if err != nil {
return err
}
total += info.Size()
return nil
})
if err != nil {
return 0, fmt.Errorf("walk layer artifacts: %w", err)
}
return total, nil
}

// totalOCICacheBlobBytesFromFilesystem sums blob sizes directly from the OCI cache blob store.
// This counts the actual bytes on disk, including any blob files that are currently
// present but no longer referenced by the OCI layout index.
Expand Down Expand Up @@ -158,7 +192,11 @@ func (m *manager) computeDiskUsageTotals() (int64, int64, error) {
if err != nil {
return 0, 0, err
}
return readyImageBytes, ociCacheBytes, nil
layerArtifactBytes, err := totalLayerArtifactBytesFromFilesystem(m.paths.ImageLayersDir())
if err != nil {
return 0, 0, err
}
return readyImageBytes, ociCacheBytes + layerArtifactBytes, nil
}

func totalRootfsBytesInDigestDir(digestDir string) (int64, error) {
Expand Down
20 changes: 20 additions & 0 deletions lib/images/disk_usage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,26 @@ func TestTotalReadyImageBytesFromMetadata_DeduplicatesMalformedAliases(t *testin
require.Equal(t, int64(len("shared-rootfs")), total)
}

func TestTotalLayerArtifactBytesFromFilesystem(t *testing.T) {
t.Parallel()

layersDir := t.TempDir()
digestDir := filepath.Join(layersDir, "a", "b")
require.NoError(t, os.MkdirAll(digestDir, 0o755))
require.NoError(t, os.WriteFile(filepath.Join(digestDir, "layer.erofs"), []byte("erofs"), 0o644))
require.NoError(t, os.WriteFile(filepath.Join(digestDir, "layer.ext4"), []byte("ext4"), 0o644))
require.NoError(t, os.WriteFile(filepath.Join(digestDir, "artifact.erofs.json"), []byte("record"), 0o644))

// In-progress temp dirs should be skipped.
unpackDir := filepath.Join(digestDir, ".unpack-tmp")
require.NoError(t, os.MkdirAll(unpackDir, 0o755))
require.NoError(t, os.WriteFile(filepath.Join(unpackDir, "layer.bin"), []byte("unpacked-content"), 0o644))

total, err := totalLayerArtifactBytesFromFilesystem(layersDir)
require.NoError(t, err)
require.Equal(t, int64(len("erofs")+len("ext4")), total)
}

func TestTotalReadyImageBytesFromMetadata_UsesRootfsFallbackForReadyImageWithoutSize(t *testing.T) {
t.Parallel()

Expand Down
Loading
Loading