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
fad93df
Materialize per-layer artifacts with explicit whiteout handling
chruffins Aug 31, 2026
aa23396
Harden layer artifact materialization
chruffins Sep 1, 2026
de5cf83
Address layer artifact review findings
chruffins Sep 1, 2026
66f4a00
Fix layer artifact composition edge cases
chruffins Sep 2, 2026
6f771a7
Fix layer artifact composition and metadata handling edge cases
chruffins Sep 2, 2026
10c578d
Harden layer artifact composition
chruffins Sep 2, 2026
599be21
Harden layer tree portability and file copying
chruffins Sep 3, 2026
30eb223
Harden layer materialization and metadata restoration
chruffins Sep 3, 2026
5ee953a
Share context-aware cached layer unpacking
chruffins Sep 3, 2026
bee89ee
Serialize layer store writes
chruffins Sep 3, 2026
f24b4bb
Preserve explicit layer directory metadata
chruffins Sep 3, 2026
21e863c
Use singleflight for layer materialization
chruffins Sep 3, 2026
2398f43
Test synthesized directory metadata preservation
chruffins Sep 3, 2026
1496c23
Collapse layer helper wrappers and dead branches
chruffins Sep 3, 2026
2c55549
Drop access time preservation from layer metadata
chruffins Sep 3, 2026
0809158
Extract layers with umoci instead of a private tar walker
chruffins Sep 3, 2026
75dee28
Detach shared layer builds from the initiating context
chruffins Sep 3, 2026
7459733
Trim layer artifact plumbing
chruffins Sep 3, 2026
46d02f3
Harden layer artifact builds and drop unused plumbing
chruffins Sep 3, 2026
7b8f9ef
Add layer artifact edge-case smoke tests
chruffins Sep 3, 2026
59eb8fb
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