Skip to content

Commit b82235c

Browse files
authored
Merge pull request moby#5079 from jedevc/free-bytes-gc
Allow more complex GC policies
2 parents 856ae24 + ac7caa8 commit b82235c

File tree

28 files changed

+725
-299
lines changed

28 files changed

+725
-299
lines changed

api/services/control/control.pb.go

Lines changed: 228 additions & 157 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/services/control/control.proto

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ message PruneRequest {
3131
repeated string filter = 1;
3232
bool all = 2;
3333
int64 keepDuration = 3 [(gogoproto.nullable) = true];
34-
int64 keepBytes = 4 [(gogoproto.nullable) = true];
34+
35+
int64 minStorage = 5 [(gogoproto.nullable) = true];
36+
int64 maxStorage = 4 [(gogoproto.nullable) = true];
37+
int64 free = 6 [(gogoproto.nullable) = true];
3538
}
3639

3740
message DiskUsageRequest {

api/types/worker.pb.go

Lines changed: 115 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/types/worker.proto

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ message WorkerRecord {
2020
message GCPolicy {
2121
bool all = 1;
2222
int64 keepDuration = 2;
23-
int64 keepBytes = 3;
2423
repeated string filters = 4;
24+
25+
int64 minStorage = 5 [(gogoproto.nullable) = true];
26+
// maxStorage was renamed from freeBytes
27+
int64 maxStorage = 3 [(gogoproto.nullable) = true];
28+
int64 free = 6 [(gogoproto.nullable) = true];
2529
}
2630

2731
message BuildkitVersion {

cache/manager.go

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/moby/buildkit/session"
2323
"github.com/moby/buildkit/snapshot"
2424
"github.com/moby/buildkit/util/bklog"
25+
"github.com/moby/buildkit/util/disk"
2526
"github.com/moby/buildkit/util/flightcontrol"
2627
"github.com/moby/buildkit/util/progress"
2728
digest "github.com/opencontainers/go-digest"
@@ -48,6 +49,7 @@ type ManagerOpt struct {
4849
Applier diff.Applier
4950
Differ diff.Comparer
5051
MetadataStore *metadata.Store
52+
Root string
5153
MountPoolRoot string
5254
}
5355

@@ -93,6 +95,8 @@ type cacheManager struct {
9395
Differ diff.Comparer
9496
MetadataStore *metadata.Store
9597

98+
root string
99+
96100
mountPool sharableMountPool
97101

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

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

10421047
totalSize := int64(0)
1043-
if opt.KeepBytes != 0 {
1048+
if opt.MaxStorage != 0 {
10441049
du, err := cm.DiskUsage(ctx, client.DiskUsageInfo{})
10451050
if err != nil {
10461051
return err
@@ -1053,27 +1058,61 @@ func (cm *cacheManager) pruneOnce(ctx context.Context, ch chan client.UsageInfo,
10531058
}
10541059
}
10551060

1061+
dstat, err := disk.GetDiskStat(cm.root)
1062+
if err != nil {
1063+
if opt.Free != 0 {
1064+
// if we are pruning based on disk space, failing to get info on it
1065+
// is fatal
1066+
return err
1067+
}
1068+
bklog.L.Warnf("failed to get disk size: %v", err)
1069+
}
1070+
10561071
return cm.prune(ctx, ch, pruneOpt{
10571072
filter: filter,
10581073
all: opt.All,
10591074
checkShared: check,
10601075
keepDuration: opt.KeepDuration,
1061-
keepBytes: opt.KeepBytes,
1076+
keepBytes: calculateKeepBytes(totalSize, dstat, opt),
10621077
totalSize: totalSize,
10631078
})
10641079
}
10651080

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

1087+
// try and keep as many bytes as we can
1088+
keepBytes := opt.MaxStorage
1089+
1090+
// if we need to free up space, then decrease to that
1091+
if excess := opt.Free - dstat.Free; excess > 0 {
1092+
if keepBytes == 0 {
1093+
keepBytes = totalSize - excess
1094+
} else {
1095+
keepBytes = min(keepBytes, totalSize-excess)
1096+
}
1097+
}
1098+
1099+
// but make sure we don't take the total below the minimum
1100+
keepBytes = max(keepBytes, opt.MinStorage)
1101+
1102+
return keepBytes
1103+
}
1104+
1105+
func (cm *cacheManager) prune(ctx context.Context, ch chan client.UsageInfo, opt pruneOpt) (err error) {
10691106
if opt.keepBytes != 0 && opt.totalSize < opt.keepBytes {
10701107
return nil
10711108
}
10721109

1110+
var toDelete []*deleteRecord
1111+
10731112
cm.mu.Lock()
10741113

1075-
gcMode := opt.keepBytes != 0
10761114
cutOff := time.Now().Add(-opt.keepDuration)
1115+
gcMode := opt.keepBytes != 0
10771116

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

@@ -1610,8 +1649,9 @@ type pruneOpt struct {
16101649
all bool
16111650
checkShared ExternalRefChecker
16121651
keepDuration time.Duration
1613-
keepBytes int64
1614-
totalSize int64
1652+
1653+
keepBytes int64
1654+
totalSize int64
16151655
}
16161656

16171657
type deleteRecord struct {

0 commit comments

Comments
 (0)