Skip to content

Commit

Permalink
Merge pull request #5079 from jedevc/free-bytes-gc
Browse files Browse the repository at this point in the history
Allow more complex GC policies
  • Loading branch information
tonistiigi committed Sep 26, 2024
2 parents 856ae24 + ac7caa8 commit b82235c
Show file tree
Hide file tree
Showing 28 changed files with 725 additions and 299 deletions.
385 changes: 228 additions & 157 deletions api/services/control/control.pb.go

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion api/services/control/control.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ message PruneRequest {
repeated string filter = 1;
bool all = 2;
int64 keepDuration = 3 [(gogoproto.nullable) = true];
int64 keepBytes = 4 [(gogoproto.nullable) = true];

int64 minStorage = 5 [(gogoproto.nullable) = true];
int64 maxStorage = 4 [(gogoproto.nullable) = true];
int64 free = 6 [(gogoproto.nullable) = true];
}

message DiskUsageRequest {
Expand Down
157 changes: 115 additions & 42 deletions api/types/worker.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/types/worker.proto
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ message WorkerRecord {
message GCPolicy {
bool all = 1;
int64 keepDuration = 2;
int64 keepBytes = 3;
repeated string filters = 4;

int64 minStorage = 5 [(gogoproto.nullable) = true];
// maxStorage was renamed from freeBytes
int64 maxStorage = 3 [(gogoproto.nullable) = true];
int64 free = 6 [(gogoproto.nullable) = true];
}

message BuildkitVersion {
Expand Down
54 changes: 47 additions & 7 deletions cache/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/util/bklog"
"github.com/moby/buildkit/util/disk"
"github.com/moby/buildkit/util/flightcontrol"
"github.com/moby/buildkit/util/progress"
digest "github.com/opencontainers/go-digest"
Expand All @@ -48,6 +49,7 @@ type ManagerOpt struct {
Applier diff.Applier
Differ diff.Comparer
MetadataStore *metadata.Store
Root string
MountPoolRoot string
}

Expand Down Expand Up @@ -93,6 +95,8 @@ type cacheManager struct {
Differ diff.Comparer
MetadataStore *metadata.Store

root string

mountPool sharableMountPool

muPrune sync.Mutex // make sure parallel prune is not allowed so there will not be inconsistent results
Expand All @@ -109,6 +113,7 @@ func NewManager(opt ManagerOpt) (Manager, error) {
Applier: opt.Applier,
Differ: opt.Differ,
MetadataStore: opt.MetadataStore,
root: opt.Root,
records: make(map[string]*cacheRecord),
}

Expand Down Expand Up @@ -1040,7 +1045,7 @@ func (cm *cacheManager) pruneOnce(ctx context.Context, ch chan client.UsageInfo,
}

totalSize := int64(0)
if opt.KeepBytes != 0 {
if opt.MaxStorage != 0 {
du, err := cm.DiskUsage(ctx, client.DiskUsageInfo{})
if err != nil {
return err
Expand All @@ -1053,27 +1058,61 @@ func (cm *cacheManager) pruneOnce(ctx context.Context, ch chan client.UsageInfo,
}
}

dstat, err := disk.GetDiskStat(cm.root)
if err != nil {
if opt.Free != 0 {
// if we are pruning based on disk space, failing to get info on it
// is fatal
return err
}
bklog.L.Warnf("failed to get disk size: %v", err)
}

return cm.prune(ctx, ch, pruneOpt{
filter: filter,
all: opt.All,
checkShared: check,
keepDuration: opt.KeepDuration,
keepBytes: opt.KeepBytes,
keepBytes: calculateKeepBytes(totalSize, dstat, opt),
totalSize: totalSize,
})
}

func (cm *cacheManager) prune(ctx context.Context, ch chan client.UsageInfo, opt pruneOpt) (err error) {
var toDelete []*deleteRecord
func calculateKeepBytes(totalSize int64, dstat disk.DiskStat, opt client.PruneInfo) int64 {
// 0 values are special, and means we have no keep cap
if opt.MaxStorage == 0 && opt.MinStorage == 0 && opt.Free == 0 {
return 0
}

// try and keep as many bytes as we can
keepBytes := opt.MaxStorage

// if we need to free up space, then decrease to that
if excess := opt.Free - dstat.Free; excess > 0 {
if keepBytes == 0 {
keepBytes = totalSize - excess
} else {
keepBytes = min(keepBytes, totalSize-excess)
}
}

// but make sure we don't take the total below the minimum
keepBytes = max(keepBytes, opt.MinStorage)

return keepBytes
}

func (cm *cacheManager) prune(ctx context.Context, ch chan client.UsageInfo, opt pruneOpt) (err error) {
if opt.keepBytes != 0 && opt.totalSize < opt.keepBytes {
return nil
}

var toDelete []*deleteRecord

cm.mu.Lock()

gcMode := opt.keepBytes != 0
cutOff := time.Now().Add(-opt.keepDuration)
gcMode := opt.keepBytes != 0

locked := map[*sync.Mutex]struct{}{}

Expand Down Expand Up @@ -1610,8 +1649,9 @@ type pruneOpt struct {
all bool
checkShared ExternalRefChecker
keepDuration time.Duration
keepBytes int64
totalSize int64

keepBytes int64
totalSize int64
}

type deleteRecord struct {
Expand Down
Loading

0 comments on commit b82235c

Please sign in to comment.