@@ -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
16171657type deleteRecord struct {
0 commit comments